aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-eh.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-11-27 05:28:58 -0500
committerJeff Garzik <jeff@garzik.org>2008-01-23 05:24:11 -0500
commit00115e0f5bc3bfdf3f3855ad89c8895f10458f92 (patch)
tree5f174c1d68e1ec0770fefdb40b813f321a838095 /drivers/ata/libata-eh.c
parent663f99b86ac7d4c0eed8c239638da0ea8849288b (diff)
libata: implement ATA_DFLAG_DUBIOUS_XFER
ATA_DFLAG_DUBIOUS_XFER is set whenever data transfer speed or method changes and gets cleared when data transfer command succeeds in the newly configured transfer mode. This will be used to improve speed down logic. Signed-off-by: Tejun Heo <htejun@gmail.com< Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-eh.c')
-rw-r--r--drivers/ata/libata-eh.c33
1 files changed, 31 insertions, 2 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 7d766ada7a5d..359a5ace8473 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -456,9 +456,20 @@ void ata_scsi_error(struct Scsi_Host *host)
456 spin_lock_irqsave(ap->lock, flags); 456 spin_lock_irqsave(ap->lock, flags);
457 457
458 __ata_port_for_each_link(link, ap) { 458 __ata_port_for_each_link(link, ap) {
459 struct ata_eh_context *ehc = &link->eh_context;
460 struct ata_device *dev;
461
459 memset(&link->eh_context, 0, sizeof(link->eh_context)); 462 memset(&link->eh_context, 0, sizeof(link->eh_context));
460 link->eh_context.i = link->eh_info; 463 link->eh_context.i = link->eh_info;
461 memset(&link->eh_info, 0, sizeof(link->eh_info)); 464 memset(&link->eh_info, 0, sizeof(link->eh_info));
465
466 ata_link_for_each_dev(dev, link) {
467 int devno = dev->devno;
468
469 ehc->saved_xfer_mode[devno] = dev->xfer_mode;
470 if (ata_ncq_enabled(dev))
471 ehc->saved_ncq_enabled |= 1 << devno;
472 }
462 } 473 }
463 474
464 ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS; 475 ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS;
@@ -2376,11 +2387,27 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
2376int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) 2387int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
2377{ 2388{
2378 struct ata_port *ap = link->ap; 2389 struct ata_port *ap = link->ap;
2390 struct ata_device *dev;
2391 int rc;
2379 2392
2380 /* has private set_mode? */ 2393 /* has private set_mode? */
2381 if (ap->ops->set_mode) 2394 if (ap->ops->set_mode)
2382 return ap->ops->set_mode(link, r_failed_dev); 2395 rc = ap->ops->set_mode(link, r_failed_dev);
2383 return ata_do_set_mode(link, r_failed_dev); 2396 else
2397 rc = ata_do_set_mode(link, r_failed_dev);
2398
2399 /* if transfer mode has changed, set DUBIOUS_XFER on device */
2400 ata_link_for_each_dev(dev, link) {
2401 struct ata_eh_context *ehc = &link->eh_context;
2402 u8 saved_xfer_mode = ehc->saved_xfer_mode[dev->devno];
2403 u8 saved_ncq = !!(ehc->saved_ncq_enabled & (1 << dev->devno));
2404
2405 if (dev->xfer_mode != saved_xfer_mode ||
2406 ata_ncq_enabled(dev) != saved_ncq)
2407 dev->flags |= ATA_DFLAG_DUBIOUS_XFER;
2408 }
2409
2410 return rc;
2384} 2411}
2385 2412
2386static int ata_link_nr_enabled(struct ata_link *link) 2413static int ata_link_nr_enabled(struct ata_link *link)
@@ -2441,6 +2468,8 @@ static int ata_eh_schedule_probe(struct ata_device *dev)
2441 ata_dev_init(dev); 2468 ata_dev_init(dev);
2442 ehc->did_probe_mask |= (1 << dev->devno); 2469 ehc->did_probe_mask |= (1 << dev->devno);
2443 ehc->i.action |= ATA_EH_SOFTRESET; 2470 ehc->i.action |= ATA_EH_SOFTRESET;
2471 ehc->saved_xfer_mode[dev->devno] = 0;
2472 ehc->saved_ncq_enabled &= ~(1 << dev->devno);
2444 2473
2445 return 1; 2474 return 1;
2446} 2475}