aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-eh.c
diff options
context:
space:
mode:
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}