aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorxiangliang yu <yxlraid@gmail.com>2013-10-27 08:03:04 -0400
committerTejun Heo <tj@kernel.org>2013-10-27 08:03:04 -0400
commit89dafa20f3daab5b3e0c13d0068a28e8e64e2102 (patch)
tree63eecb374f7cff4c34b877f21d41f666a47cca82 /drivers/ata
parent3e85c3ecbc520751324a191d23bb94873ed01b10 (diff)
ahci: disabled FBS prior to issuing software reset
Tested with Marvell 88se9125, attached with one port mulitplier(5 ports) and one disk, we will get following boot log messages if using current code: ata8: SATA link up 6.0 Gbps (SStatus 133 SControl 330) ata8.15: Port Multiplier 1.2, 0x1b4b:0x9715 r160, 5 ports, feat 0x1/0x1f ahci 0000:03:00.0: FBS is enabled ata8.00: hard resetting link ata8.00: SATA link down (SStatus 0 SControl 330) ata8.01: hard resetting link ata8.01: SATA link down (SStatus 0 SControl 330) ata8.02: hard resetting link ata8.02: SATA link down (SStatus 0 SControl 330) ata8.03: hard resetting link ata8.03: SATA link up 6.0 Gbps (SStatus 133 SControl 133) ata8.04: hard resetting link ata8.04: failed to resume link (SControl 133) ata8.04: failed to read SCR 0 (Emask=0x40) ata8.04: failed to read SCR 0 (Emask=0x40) ata8.04: failed to read SCR 1 (Emask=0x40) ata8.04: failed to read SCR 0 (Emask=0x40) ata8.03: native sectors (2) is smaller than sectors (976773168) ata8.03: ATA-8: ST3500413AS, JC4B, max UDMA/133 ata8.03: 976773168 sectors, multi 0: LBA48 NCQ (depth 31/32) ata8.03: configured for UDMA/133 ata8.04: failed to IDENTIFY (I/O error, err_mask=0x100) ata8.15: hard resetting link ata8.15: SATA link up 6.0 Gbps (SStatus 133 SControl 330) ata8.15: Port Multiplier vendor mismatch '0x1b4b' != '0x133' ata8.15: PMP revalidation failed (errno=-19) ata8.15: hard resetting link ata8.15: SATA link up 6.0 Gbps (SStatus 133 SControl 330) ata8.15: Port Multiplier vendor mismatch '0x1b4b' != '0x133' ata8.15: PMP revalidation failed (errno=-19) ata8.15: limiting SATA link speed to 3.0 Gbps ata8.15: hard resetting link ata8.15: SATA link up 3.0 Gbps (SStatus 123 SControl 320) ata8.15: Port Multiplier vendor mismatch '0x1b4b' != '0x133' ata8.15: PMP revalidation failed (errno=-19) ata8.15: failed to recover PMP after 5 tries, giving up ata8.15: Port Multiplier detaching ata8.03: disabled ata8.00: disabled ata8: EH complete The reason is that current detection code doesn't follow AHCI spec: First,the port multiplier detection process look like this: ahci_hardreset(link, class, deadline) if (class == ATA_DEV_PMP) { sata_pmp_attach(dev) /* will enable FBS */ sata_pmp_init_links(ap, nr_ports); ata_for_each_link(link, ap, EDGE) { sata_std_hardreset(link, class, deadline); if (link_is_online) /* do soft reset */ ahci_softreset(link, class, deadline); } } But, according to chapter 9.3.9 in AHCI spec: Prior to issuing software reset, software shall clear PxCMD.ST to '0' and then clear PxFBS.EN to '0'. The patch test ok with kernel 3.11.1. tj: Patch white space contaminated, applied manually with trivial updates. Signed-off-by: Xiangliang Yu <yuxiangl@marvell.com> Signed-off-by: Tejun Heo <tj@kernel.org> Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/libahci.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 7e2a1b38093e..6686dbec4440 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -1267,9 +1267,11 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
1267{ 1267{
1268 struct ata_port *ap = link->ap; 1268 struct ata_port *ap = link->ap;
1269 struct ahci_host_priv *hpriv = ap->host->private_data; 1269 struct ahci_host_priv *hpriv = ap->host->private_data;
1270 struct ahci_port_priv *pp = ap->private_data;
1270 const char *reason = NULL; 1271 const char *reason = NULL;
1271 unsigned long now, msecs; 1272 unsigned long now, msecs;
1272 struct ata_taskfile tf; 1273 struct ata_taskfile tf;
1274 bool fbs_disabled = false;
1273 int rc; 1275 int rc;
1274 1276
1275 DPRINTK("ENTER\n"); 1277 DPRINTK("ENTER\n");
@@ -1279,6 +1281,16 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
1279 if (rc && rc != -EOPNOTSUPP) 1281 if (rc && rc != -EOPNOTSUPP)
1280 ata_link_warn(link, "failed to reset engine (errno=%d)\n", rc); 1282 ata_link_warn(link, "failed to reset engine (errno=%d)\n", rc);
1281 1283
1284 /*
1285 * According to AHCI-1.2 9.3.9: if FBS is enable, software shall
1286 * clear PxFBS.EN to '0' prior to issuing software reset to devices
1287 * that is attached to port multiplier.
1288 */
1289 if (!ata_is_host_link(link) && pp->fbs_enabled) {
1290 ahci_disable_fbs(ap);
1291 fbs_disabled = true;
1292 }
1293
1282 ata_tf_init(link->device, &tf); 1294 ata_tf_init(link->device, &tf);
1283 1295
1284 /* issue the first D2H Register FIS */ 1296 /* issue the first D2H Register FIS */
@@ -1319,6 +1331,10 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
1319 } else 1331 } else
1320 *class = ahci_dev_classify(ap); 1332 *class = ahci_dev_classify(ap);
1321 1333
1334 /* re-enable FBS if disabled before */
1335 if (fbs_disabled)
1336 ahci_enable_fbs(ap);
1337
1322 DPRINTK("EXIT, class=%u\n", *class); 1338 DPRINTK("EXIT, class=%u\n", *class);
1323 return 0; 1339 return 0;
1324 1340