aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/libata-core.c19
-rw-r--r--drivers/ata/libata-eh.c33
-rw-r--r--include/linux/libata.h3
3 files changed, 53 insertions, 2 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 86c10cc751e9..124b6f111cc3 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5797,6 +5797,22 @@ static void fill_result_tf(struct ata_queued_cmd *qc)
5797 ap->ops->tf_read(ap, &qc->result_tf); 5797 ap->ops->tf_read(ap, &qc->result_tf);
5798} 5798}
5799 5799
5800static void ata_verify_xfer(struct ata_queued_cmd *qc)
5801{
5802 struct ata_device *dev = qc->dev;
5803
5804 if (ata_tag_internal(qc->tag))
5805 return;
5806
5807 if (ata_is_nodata(qc->tf.protocol))
5808 return;
5809
5810 if ((dev->mwdma_mask || dev->udma_mask) && ata_is_pio(qc->tf.protocol))
5811 return;
5812
5813 dev->flags &= ~ATA_DFLAG_DUBIOUS_XFER;
5814}
5815
5800/** 5816/**
5801 * ata_qc_complete - Complete an active ATA command 5817 * ata_qc_complete - Complete an active ATA command
5802 * @qc: Command to complete 5818 * @qc: Command to complete
@@ -5868,6 +5884,9 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
5868 break; 5884 break;
5869 } 5885 }
5870 5886
5887 if (unlikely(dev->flags & ATA_DFLAG_DUBIOUS_XFER))
5888 ata_verify_xfer(qc);
5889
5871 __ata_qc_complete(qc); 5890 __ata_qc_complete(qc);
5872 } else { 5891 } else {
5873 if (qc->flags & ATA_QCFLAG_EH_SCHEDULED) 5892 if (qc->flags & ATA_QCFLAG_EH_SCHEDULED)
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}
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 74f1255e2524..131fb6625e14 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -143,6 +143,7 @@ enum {
143 ATA_DFLAG_NCQ_OFF = (1 << 13), /* device limited to non-NCQ mode */ 143 ATA_DFLAG_NCQ_OFF = (1 << 13), /* device limited to non-NCQ mode */
144 ATA_DFLAG_SPUNDOWN = (1 << 14), /* XXX: for spindown_compat */ 144 ATA_DFLAG_SPUNDOWN = (1 << 14), /* XXX: for spindown_compat */
145 ATA_DFLAG_SLEEPING = (1 << 15), /* device is sleeping */ 145 ATA_DFLAG_SLEEPING = (1 << 15), /* device is sleeping */
146 ATA_DFLAG_DUBIOUS_XFER = (1 << 16), /* data transfer not verified */
146 ATA_DFLAG_INIT_MASK = (1 << 24) - 1, 147 ATA_DFLAG_INIT_MASK = (1 << 24) - 1,
147 148
148 ATA_DFLAG_DETACH = (1 << 24), 149 ATA_DFLAG_DETACH = (1 << 24),
@@ -560,6 +561,8 @@ struct ata_eh_context {
560 int tries[ATA_MAX_DEVICES]; 561 int tries[ATA_MAX_DEVICES];
561 unsigned int classes[ATA_MAX_DEVICES]; 562 unsigned int classes[ATA_MAX_DEVICES];
562 unsigned int did_probe_mask; 563 unsigned int did_probe_mask;
564 unsigned int saved_ncq_enabled;
565 u8 saved_xfer_mode[ATA_MAX_DEVICES];
563}; 566};
564 567
565struct ata_acpi_drive 568struct ata_acpi_drive