diff options
Diffstat (limited to 'drivers/ata/libata-eh.c')
-rw-r--r-- | drivers/ata/libata-eh.c | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 7d766ada7a5..359a5ace847 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) spin_lock_irqsave(ap->lock, flags); __ata_port_for_each_link(link, ap) { + struct ata_eh_context *ehc = &link->eh_context; + struct ata_device *dev; + memset(&link->eh_context, 0, sizeof(link->eh_context)); link->eh_context.i = link->eh_info; memset(&link->eh_info, 0, sizeof(link->eh_info)); + + ata_link_for_each_dev(dev, link) { + int devno = dev->devno; + + ehc->saved_xfer_mode[devno] = dev->xfer_mode; + if (ata_ncq_enabled(dev)) + ehc->saved_ncq_enabled |= 1 << devno; + } } ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS; @@ -2376,11 +2387,27 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) { struct ata_port *ap = link->ap; + struct ata_device *dev; + int rc; /* has private set_mode? */ if (ap->ops->set_mode) - return ap->ops->set_mode(link, r_failed_dev); - return ata_do_set_mode(link, r_failed_dev); + rc = ap->ops->set_mode(link, r_failed_dev); + else + rc = ata_do_set_mode(link, r_failed_dev); + + /* if transfer mode has changed, set DUBIOUS_XFER on device */ + ata_link_for_each_dev(dev, link) { + struct ata_eh_context *ehc = &link->eh_context; + u8 saved_xfer_mode = ehc->saved_xfer_mode[dev->devno]; + u8 saved_ncq = !!(ehc->saved_ncq_enabled & (1 << dev->devno)); + + if (dev->xfer_mode != saved_xfer_mode || + ata_ncq_enabled(dev) != saved_ncq) + dev->flags |= ATA_DFLAG_DUBIOUS_XFER; + } + + return rc; } static int ata_link_nr_enabled(struct ata_link *link) @@ -2441,6 +2468,8 @@ static int ata_eh_schedule_probe(struct ata_device *dev) ata_dev_init(dev); ehc->did_probe_mask |= (1 << dev->devno); ehc->i.action |= ATA_EH_SOFTRESET; + ehc->saved_xfer_mode[dev->devno] = 0; + ehc->saved_ncq_enabled &= ~(1 << dev->devno); return 1; } |