[libata] Add ATA transport class
[deliverable/linux.git] / drivers / ata / libata-core.c
index c035b3d041ee1572492d7a17f56323bde0fccacd..4012b33e8b8a4e1598c2f62604b316ccc6cd9aca 100644 (file)
@@ -68,7 +68,7 @@
 #include <linux/ratelimit.h>
 
 #include "libata.h"
-
+#include "libata-transport.h"
 
 /* debounce timing parameters in msecs { interval, duration, timeout } */
 const unsigned long sata_deb_timing_normal[]           = {   5,  100, 2000 };
@@ -1017,7 +1017,7 @@ const char *ata_mode_string(unsigned long xfer_mask)
        return "<n/a>";
 }
 
-static const char *sata_spd_string(unsigned int spd)
+const char *sata_spd_string(unsigned int spd)
 {
        static const char * const spd_str[] = {
                "1.5 Gbps",
@@ -5418,6 +5418,7 @@ static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg,
  */
 int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
 {
+       unsigned int ehi_flags = ATA_EHI_QUIET;
        int rc;
 
        /*
@@ -5426,7 +5427,18 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
         */
        ata_lpm_enable(host);
 
-       rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1);
+       /*
+        * On some hardware, device fails to respond after spun down
+        * for suspend.  As the device won't be used before being
+        * resumed, we don't need to touch the device.  Ask EH to skip
+        * the usual stuff and proceed directly to suspend.
+        *
+        * http://thread.gmane.org/gmane.linux.ide/46764
+        */
+       if (mesg.event == PM_EVENT_SUSPEND)
+               ehi_flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_NO_RECOVERY;
+
+       rc = ata_host_request_pm(host, mesg, 0, ehi_flags, 1);
        if (rc == 0)
                host->dev->power.power_state = mesg;
        return rc;
@@ -5505,7 +5517,8 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
        int i;
 
        /* clear everything except for devices */
-       memset(link, 0, offsetof(struct ata_link, device[0]));
+       memset((void *)link + ATA_LINK_CLEAR_BEGIN, 0,
+              ATA_LINK_CLEAR_END - ATA_LINK_CLEAR_BEGIN);
 
        link->ap = ap;
        link->pmp = pmp;
@@ -5579,7 +5592,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
        ap = kzalloc(sizeof(*ap), GFP_KERNEL);
        if (!ap)
                return NULL;
-
+       
        ap->pflags |= ATA_PFLAG_INITIALIZING;
        ap->lock = &host->lock;
        ap->print_id = -1;
@@ -6081,9 +6094,18 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
        for (i = 0; i < host->n_ports; i++)
                host->ports[i]->print_id = ata_print_id++;
 
+       
+       /* Create associated sysfs transport objects  */
+       for (i = 0; i < host->n_ports; i++) {
+               rc = ata_tport_add(host->dev,host->ports[i]);
+               if (rc) {
+                       goto err_tadd;
+               }
+       }
+
        rc = ata_scsi_add_hosts(host, sht);
        if (rc)
-               return rc;
+               goto err_tadd;
 
        /* associate with ACPI nodes */
        ata_acpi_associate(host);
@@ -6124,6 +6146,13 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
        }
 
        return 0;
+
+ err_tadd:
+       while (--i >= 0) {
+               ata_tport_delete(host->ports[i]);
+       }
+       return rc;
+
 }
 
 /**
@@ -6214,6 +6243,13 @@ static void ata_port_detach(struct ata_port *ap)
        cancel_rearming_delayed_work(&ap->hotplug_task);
 
  skip_eh:
+       if (ap->pmp_link) {
+               int i;
+               for (i = 0; i < SATA_PMP_MAX_PORTS; i++)
+                       ata_tlink_delete(&ap->pmp_link[i]);
+       }
+       ata_tport_delete(ap);
+
        /* remove the associated SCSI host */
        scsi_remove_host(ap->scsi_host);
 }
@@ -6530,7 +6566,7 @@ static void __init ata_parse_force_param(void)
 
 static int __init ata_init(void)
 {
-       int rc = -ENOMEM;
+       int rc;
 
        ata_parse_force_param();
 
@@ -6540,12 +6576,25 @@ static int __init ata_init(void)
                return rc;
        }
 
+       libata_transport_init();
+       ata_scsi_transport_template = ata_attach_transport();
+       if (!ata_scsi_transport_template) {
+               ata_sff_exit();
+               rc = -ENOMEM;
+               goto err_out;
+       }               
+
        printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n");
        return 0;
+
+err_out:
+       return rc;
 }
 
 static void __exit ata_exit(void)
 {
+       ata_release_transport(ata_scsi_transport_template);
+       libata_transport_exit();
        ata_sff_exit();
        kfree(ata_force_tbl);
 }
This page took 0.124056 seconds and 5 git commands to generate.