mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 13:11:40 +00:00
[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: Grant Grundler <grundler@google.com> Signed-off-by: Gwendal Grignou <gwendal@google.com> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
parent
fbaf666b85
commit
4f2c774856
@ -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, ®);
|
||||
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]);
|
||||
|
Loading…
Reference in New Issue
Block a user