aboutsummaryrefslogtreecommitdiffstats
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
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>
-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