Commit 4f2c7748 authored by Grant Grundler's avatar Grant Grundler Committed by Jeff Garzik

[libata] Disable R_OK (Early ACK) on SII 3726 PMP

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: default avatarGrant Grundler <grundler@google.com>
Signed-off-by: default avatarGwendal Grignou <gwendal@google.com>
Acked-by: default avatarTejun Heo <tj@kernel.org>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent fbaf666b
...@@ -231,10 +231,14 @@ static const char *sata_pmp_spec_rev_str(const u32 *gscr) ...@@ -231,10 +231,14 @@ static const char *sata_pmp_spec_rev_str(const u32 *gscr)
return "<unknown>"; return "<unknown>";
} }
#define PMP_GSCR_SII_POL 129
static int sata_pmp_configure(struct ata_device *dev, int print_info) static int sata_pmp_configure(struct ata_device *dev, int print_info)
{ {
struct ata_port *ap = dev->link->ap; struct ata_port *ap = dev->link->ap;
u32 *gscr = dev->gscr; u32 *gscr = dev->gscr;
u16 vendor = sata_pmp_gscr_vendor(gscr);
u16 devid = sata_pmp_gscr_devid(gscr);
unsigned int err_mask = 0; unsigned int err_mask = 0;
const char *reason; const char *reason;
int nr_ports, rc; int nr_ports, rc;
...@@ -260,12 +264,34 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info) ...@@ -260,12 +264,34 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
goto fail; 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) { if (print_info) {
ata_dev_printk(dev, KERN_INFO, "Port Multiplier %s, " ata_dev_printk(dev, KERN_INFO, "Port Multiplier %s, "
"0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n", "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n",
sata_pmp_spec_rev_str(gscr), sata_pmp_spec_rev_str(gscr), vendor, devid,
sata_pmp_gscr_vendor(gscr),
sata_pmp_gscr_devid(gscr),
sata_pmp_gscr_rev(gscr), sata_pmp_gscr_rev(gscr),
nr_ports, gscr[SATA_PMP_GSCR_FEAT_EN], nr_ports, gscr[SATA_PMP_GSCR_FEAT_EN],
gscr[SATA_PMP_GSCR_FEAT]); gscr[SATA_PMP_GSCR_FEAT]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment