aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorGrant Grundler <grundler@google.com>2010-04-14 21:43:32 -0400
committerJeff Garzik <jgarzik@redhat.com>2010-05-14 17:08:02 -0400
commit4f2c774856708bccecb74c0e6296e9e2c9136ee1 (patch)
tree33ebceafd0f2f21b155dde40344addf45e2cb4ed /drivers/ata
parentfbaf666b854c04b2d8ebca17114ee409ddea08b5 (diff)
[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>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/libata-pmp.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 00305f41ed86..224faabd7b7e 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)
231 return "<unknown>"; 231 return "<unknown>";
232} 232}
233 233
234#define PMP_GSCR_SII_POL 129
235
234static int sata_pmp_configure(struct ata_device *dev, int print_info) 236static int sata_pmp_configure(struct ata_device *dev, int print_info)
235{ 237{
236 struct ata_port *ap = dev->link->ap; 238 struct ata_port *ap = dev->link->ap;
237 u32 *gscr = dev->gscr; 239 u32 *gscr = dev->gscr;
240 u16 vendor = sata_pmp_gscr_vendor(gscr);
241 u16 devid = sata_pmp_gscr_devid(gscr);
238 unsigned int err_mask = 0; 242 unsigned int err_mask = 0;
239 const char *reason; 243 const char *reason;
240 int nr_ports, rc; 244 int nr_ports, rc;
@@ -260,12 +264,34 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
260 goto fail; 264 goto fail;
261 } 265 }
262 266
267 /* Disable sending Early R_OK.
268 * With "cached read" HDD testing and multiple ports busy on a SATA
269 * host controller, 3726 PMP will very rarely drop a deferred
270 * R_OK that was intended for the host. Symptom will be all
271 * 5 drives under test will timeout, get reset, and recover.
272 */
273 if (vendor == 0x1095 && devid == 0x3726) {
274 u32 reg;
275
276 err_mask = sata_pmp_read(&ap->link, PMP_GSCR_SII_POL, &reg);
277 if (err_mask) {
278 rc = -EIO;
279 reason = "failed to read Sil3726 Private Register";
280 goto fail;
281 }
282 reg &= ~0x1;
283 err_mask = sata_pmp_write(&ap->link, PMP_GSCR_SII_POL, reg);
284 if (err_mask) {
285 rc = -EIO;
286 reason = "failed to write Sil3726 Private Register";
287 goto fail;
288 }
289 }
290
263 if (print_info) { 291 if (print_info) {
264 ata_dev_printk(dev, KERN_INFO, "Port Multiplier %s, " 292 ata_dev_printk(dev, KERN_INFO, "Port Multiplier %s, "
265 "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n", 293 "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n",
266 sata_pmp_spec_rev_str(gscr), 294 sata_pmp_spec_rev_str(gscr), vendor, devid,
267 sata_pmp_gscr_vendor(gscr),
268 sata_pmp_gscr_devid(gscr),
269 sata_pmp_gscr_rev(gscr), 295 sata_pmp_gscr_rev(gscr),
270 nr_ports, gscr[SATA_PMP_GSCR_FEAT_EN], 296 nr_ports, gscr[SATA_PMP_GSCR_FEAT_EN],
271 gscr[SATA_PMP_GSCR_FEAT]); 297 gscr[SATA_PMP_GSCR_FEAT]);