public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] 2.6.34-rc3 v2 Disable R_OK (Early ACK) on SII 3726 PMP
@ 2010-04-15  1:43 Grant Grundler
  2010-04-20 20:52 ` Grant Grundler
  2010-04-23  2:05 ` Jeff Garzik
  0 siblings, 2 replies; 6+ messages in thread
From: Grant Grundler @ 2010-04-15  1:43 UTC (permalink / raw)
  To: Linux IDE mailing list; +Cc: Jeff Garzik, Tejun Heo, LKML

[-- Attachment #1: Type: text/plain, Size: 4023 bytes --]

In 2009, While running "cache read" performance test of drives behind
SII PMP we encountered a "all 5 drives" timeout on more than 30% of the
machines under test.  This patch reduces the rate by a factor of about 70.
Low enough that we didn't care to further investigate the issue.

Performance impact with any sort of "normal" use was ~2%+ CPU and less
than 1% throughput degradation.  Worst case impact (cached read) was
6% IOPS reduction. This is with NCQ off (q=1) but I believe FIS based
switching enabled in the SATA driver.

The patch disables "Early ACK" in the 3726 port multiplier.
"Early ACK" is issued when device sends a FIS to the host (via PMP)
and the PMP sends an ACK immediately back to the device - well before
the host gets the response. Under worst case IOPs load (cached read
test) and more than 2 PMPs connected to a 4-port SATA controller,
I suspect the time to service all of the PMPs is exceeding the PMPs
ability to keep track of outstanding FIS it owes the Host. Reducing
the number of PMPs to 2 (or 1) reduces the frequency by several orders
of magnitude. Kudos to Gwendal for initial debugging of this issue.
[Any errors in the description are mine, not his.]

Patch is currently in production on Google servers.

Signed-off-by: Grant Grundler <grundler@google.com>
Signed-off-by: Gwendal Grignou <gwendal@google.com>
Acked-by: Tejun Heo <tj@kernel.org>

---

v2: dropped references to 4726 since I didn't test 4726,
    moved register definition directly into libata-pmp.c, and
    expanded the comment in the code to summarize the above description.

Code below is white space mangled. Please use attached file.

diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 00305f4..487227a 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -231,10 +231,14 @@ static const char *sata_pmp_spec_rev_str(const u32 *gscr)
        return "<unknown>";
 }

+#define PMP_GSCR_SII_POL 129
+
 static int sata_pmp_configure(struct ata_device *dev, int print_info)
 {
        struct ata_port *ap = dev->link->ap;
        u32 *gscr = dev->gscr;
+       u16 vendor = sata_pmp_gscr_vendor(gscr);
+       u16 devid = sata_pmp_gscr_devid(gscr);
        unsigned int err_mask = 0;
        const char *reason;
        int nr_ports, rc;
@@ -260,12 +264,34 @@ static int sata_pmp_configure(struct ata_device
*dev, int print_info)
                goto fail;
        }

+       /* Disable sending Early R_OK.
+        * With "cached read" HDD testing and multiple ports busy on a SATA
+        * host controller, 3726 PMP will very rarely drop a deferred
+        * R_OK that was intended for the host. Symptom will be all
+        * 5 drives under test will timeout, get reset, and recover.
+        */
+       if (vendor == 0x1095 && devid == 0x3726) {
+               u32 reg;
+
+               err_mask = sata_pmp_read(&ap->link, PMP_GSCR_SII_POL, &reg);
+               if (err_mask) {
+                       rc = -EIO;
+                       reason = "failed to read Sil3726 Private Register";
+                       goto fail;
+               }
+               reg &= ~0x1;
+               err_mask = sata_pmp_write(&ap->link, PMP_GSCR_SII_POL, reg);
+               if (err_mask) {
+                       rc = -EIO;
+                       reason = "failed to write Sil3726 Private Register";
+                       goto fail;
+               }
+       }
+
        if (print_info) {
                ata_dev_printk(dev, KERN_INFO, "Port Multiplier %s, "
                               "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n",
-                              sata_pmp_spec_rev_str(gscr),
-                              sata_pmp_gscr_vendor(gscr),
-                              sata_pmp_gscr_devid(gscr),
+                              sata_pmp_spec_rev_str(gscr), vendor, devid,
                               sata_pmp_gscr_rev(gscr),
                               nr_ports, gscr[SATA_PMP_GSCR_FEAT_EN],
                               gscr[SATA_PMP_GSCR_FEAT]);

[-- Attachment #2: 2.6.34-rc3-libata_pmp-disable_ImdAck-04 --]
[-- Type: application/octet-stream, Size: 1862 bytes --]

diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 00305f4..487227a 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -231,10 +231,14 @@ static const char *sata_pmp_spec_rev_str(const u32 *gscr)
 	return "<unknown>";
 }
 
+#define PMP_GSCR_SII_POL 129
+
 static int sata_pmp_configure(struct ata_device *dev, int print_info)
 {
 	struct ata_port *ap = dev->link->ap;
 	u32 *gscr = dev->gscr;
+	u16 vendor = sata_pmp_gscr_vendor(gscr);
+	u16 devid = sata_pmp_gscr_devid(gscr);
 	unsigned int err_mask = 0;
 	const char *reason;
 	int nr_ports, rc;
@@ -260,12 +264,34 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
 		goto fail;
 	}
 
+	/* Disable sending Early R_OK.
+	 * With "cached read" HDD testing and multiple ports busy on a SATA
+	 * host controller, 3726 PMP will very rarely drop a deferred
+	 * R_OK that was intended for the host. Symptom will be all
+	 * 5 drives under test will timeout, get reset, and recover.
+	 */
+	if (vendor == 0x1095 && devid == 0x3726) {
+		u32 reg;
+
+		err_mask = sata_pmp_read(&ap->link, PMP_GSCR_SII_POL, &reg);
+		if (err_mask) {
+			rc = -EIO;
+			reason = "failed to read Sil3726 Private Register";
+			goto fail;
+		}
+		reg &= ~0x1;
+		err_mask = sata_pmp_write(&ap->link, PMP_GSCR_SII_POL, reg);
+		if (err_mask) {
+			rc = -EIO;
+			reason = "failed to write Sil3726 Private Register";
+			goto fail;
+		}
+	}
+
 	if (print_info) {
 		ata_dev_printk(dev, KERN_INFO, "Port Multiplier %s, "
 			       "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n",
-			       sata_pmp_spec_rev_str(gscr),
-			       sata_pmp_gscr_vendor(gscr),
-			       sata_pmp_gscr_devid(gscr),
+			       sata_pmp_spec_rev_str(gscr), vendor, devid,
 			       sata_pmp_gscr_rev(gscr),
 			       nr_ports, gscr[SATA_PMP_GSCR_FEAT_EN],
 			       gscr[SATA_PMP_GSCR_FEAT]);

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2010-04-23 15:41 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-04-15  1:43 [PATCH] 2.6.34-rc3 v2 Disable R_OK (Early ACK) on SII 3726 PMP Grant Grundler
2010-04-20 20:52 ` Grant Grundler
2010-04-21 10:42   ` Tejun Heo
2010-04-23  2:16   ` Jeff Garzik
2010-04-23 15:41     ` Grant Grundler
2010-04-23  2:05 ` Jeff Garzik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox