]> Pileus Git - ~andy/linux/blobdiff - drivers/ata/libahci.c
staging: imx-drm: Fix modular build of DRM_IMX_IPUV3
[~andy/linux] / drivers / ata / libahci.c
index aaac4fb0d5645f8d52782fc55cb6f39da04830e7..c482f8cadd7aa3dd59bb7930bdb749b7bf230dfd 100644 (file)
@@ -89,7 +89,6 @@ static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
 static int ahci_hardreset(struct ata_link *link, unsigned int *class,
                          unsigned long deadline);
 static void ahci_postreset(struct ata_link *link, unsigned int *class);
-static void ahci_error_handler(struct ata_port *ap);
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
 static void ahci_dev_config(struct ata_device *dev);
 #ifdef CONFIG_PM
@@ -189,14 +188,15 @@ struct ata_port_operations ahci_pmp_retry_srst_ops = {
 };
 EXPORT_SYMBOL_GPL(ahci_pmp_retry_srst_ops);
 
-int ahci_em_messages = 1;
+static bool ahci_em_messages __read_mostly = true;
 EXPORT_SYMBOL_GPL(ahci_em_messages);
-module_param(ahci_em_messages, int, 0444);
+module_param(ahci_em_messages, bool, 0444);
 /* add other LED protocol types when they become supported */
 MODULE_PARM_DESC(ahci_em_messages,
        "AHCI Enclosure Management Message control (0 = off, 1 = on)");
 
-int devslp_idle_timeout = 1000;        /* device sleep idle timeout in ms */
+/* device sleep idle timeout in ms */
+static int devslp_idle_timeout __read_mostly = 1000;
 module_param(devslp_idle_timeout, int, 0644);
 MODULE_PARM_DESC(devslp_idle_timeout, "device sleep idle timeout");
 
@@ -1275,9 +1275,11 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
 {
        struct ata_port *ap = link->ap;
        struct ahci_host_priv *hpriv = ap->host->private_data;
+       struct ahci_port_priv *pp = ap->private_data;
        const char *reason = NULL;
        unsigned long now, msecs;
        struct ata_taskfile tf;
+       bool fbs_disabled = false;
        int rc;
 
        DPRINTK("ENTER\n");
@@ -1287,6 +1289,16 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
        if (rc && rc != -EOPNOTSUPP)
                ata_link_warn(link, "failed to reset engine (errno=%d)\n", rc);
 
+       /*
+        * According to AHCI-1.2 9.3.9: if FBS is enable, software shall
+        * clear PxFBS.EN to '0' prior to issuing software reset to devices
+        * that is attached to port multiplier.
+        */
+       if (!ata_is_host_link(link) && pp->fbs_enabled) {
+               ahci_disable_fbs(ap);
+               fbs_disabled = true;
+       }
+
        ata_tf_init(link->device, &tf);
 
        /* issue the first D2H Register FIS */
@@ -1327,6 +1339,10 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
        } else
                *class = ahci_dev_classify(ap);
 
+       /* re-enable FBS if disabled before */
+       if (fbs_disabled)
+               ahci_enable_fbs(ap);
+
        DPRINTK("EXIT, class=%u\n", *class);
        return 0;
 
@@ -1989,7 +2005,7 @@ static void ahci_thaw(struct ata_port *ap)
        writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
 }
 
-static void ahci_error_handler(struct ata_port *ap)
+void ahci_error_handler(struct ata_port *ap)
 {
        if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
                /* restart engine */
@@ -2002,6 +2018,7 @@ static void ahci_error_handler(struct ata_port *ap)
        if (!ata_dev_enabled(ap->link.device))
                ahci_stop_engine(ap);
 }
+EXPORT_SYMBOL_GPL(ahci_error_handler);
 
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
 {