Merge tag 'v3.10.67' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / ata / libahci.c
index a70ff154f586753d6c096b858ae5dbee0ad869c3..8905e03a53a24f132def4d73039c3dd2e0bdeb6a 100644 (file)
@@ -1266,9 +1266,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");
@@ -1278,6 +1280,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 */
@@ -1318,6 +1330,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;
 
@@ -1560,8 +1576,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
                u32 fbs = readl(port_mmio + PORT_FBS);
                int pmp = fbs >> PORT_FBS_DWE_OFFSET;
 
-               if ((fbs & PORT_FBS_SDE) && (pmp < ap->nr_pmp_links) &&
-                   ata_link_online(&ap->pmp_link[pmp])) {
+               if ((fbs & PORT_FBS_SDE) && (pmp < ap->nr_pmp_links)) {
                        link = &ap->pmp_link[pmp];
                        fbs_need_dec = true;
                }