aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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]);