aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-11-11 06:10:45 -0500
committerJeff Garzik <jeff@garzik.org>2006-12-01 22:45:54 -0500
commit6fc49adb9417b9c793e8f88d485387bb89ceb733 (patch)
treed94f536f24e504b1a654c392171fb6f08a195ca2
parent648a88be4a016d2637ace3ae74b85a0512255ee8 (diff)
[PATCH] libata: use FLUSH_EXT only when driver is larger than LBA28 limit
Many drives support LBA48 even when its capacity is smaller than 1<<28, as LBA48 is required for many functionalities. FLUSH_EXT is mandatory for drives w/ LBA48 support. Interestingly, at least one of such drives (ST960812A) has problems dealing with FLUSH_EXT. It eventually completes the command but takes around 7 seconds to finish in many cases thus drastically slowing down IO transactions. This seems to be a firmware bug which sneaked into production probably because no other ATA driver including linux IDE issues FLUSH_EXT to drives which report support for LBA48 & FLUSH_EXT but is smaller than 1<<28 blocks. This patch adds ATA_DFLAG_FLUSH_EXT which is set iff the drive supports LBA48 & FLUSH_EXT and is larger than LBA28 limit. Both cache flush paths are updated to issue FLUSH_EXT only when the flag is set. Note that the changed behavior is more inline with the rest of libata. libata prefers shorter commands whenever possible. Signed-off-by: Tejun Heo <htejun@gmail.com> Cc: Danny Kukawka <dkukawka@novell.com> Cc: Stefan Seyfried <seife@novell.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/ata/libata-core.c6
-rw-r--r--drivers/ata/libata-scsi.c3
-rw-r--r--include/linux/libata.h1
3 files changed, 7 insertions, 3 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index f531a89c26c9..d94b8a02c340 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1457,6 +1457,10 @@ int ata_dev_configure(struct ata_device *dev)
1457 if (ata_id_has_lba48(id)) { 1457 if (ata_id_has_lba48(id)) {
1458 dev->flags |= ATA_DFLAG_LBA48; 1458 dev->flags |= ATA_DFLAG_LBA48;
1459 lba_desc = "LBA48"; 1459 lba_desc = "LBA48";
1460
1461 if (dev->n_sectors >= (1UL << 28) &&
1462 ata_id_has_flush_ext(id))
1463 dev->flags |= ATA_DFLAG_FLUSH_EXT;
1460 } 1464 }
1461 1465
1462 /* config NCQ */ 1466 /* config NCQ */
@@ -5128,7 +5132,7 @@ int ata_flush_cache(struct ata_device *dev)
5128 if (!ata_try_flush_cache(dev)) 5132 if (!ata_try_flush_cache(dev))
5129 return 0; 5133 return 0;
5130 5134
5131 if (ata_id_has_flush_ext(dev->id)) 5135 if (dev->flags & ATA_DFLAG_FLUSH_EXT)
5132 cmd = ATA_CMD_FLUSH_EXT; 5136 cmd = ATA_CMD_FLUSH_EXT;
5133 else 5137 else
5134 cmd = ATA_CMD_FLUSH; 5138 cmd = ATA_CMD_FLUSH;
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index f13dd07a5331..7a55c2e4ea6e 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1027,8 +1027,7 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, const u8 *scs
1027 tf->flags |= ATA_TFLAG_DEVICE; 1027 tf->flags |= ATA_TFLAG_DEVICE;
1028 tf->protocol = ATA_PROT_NODATA; 1028 tf->protocol = ATA_PROT_NODATA;
1029 1029
1030 if ((qc->dev->flags & ATA_DFLAG_LBA48) && 1030 if (qc->dev->flags & ATA_DFLAG_FLUSH_EXT)
1031 (ata_id_has_flush_ext(qc->dev->id)))
1032 tf->command = ATA_CMD_FLUSH_EXT; 1031 tf->command = ATA_CMD_FLUSH_EXT;
1033 else 1032 else
1034 tf->command = ATA_CMD_FLUSH; 1033 tf->command = ATA_CMD_FLUSH;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 0d0ddeaee73f..36e233cc3886 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -140,6 +140,7 @@ enum {
140 ATA_DFLAG_LBA48 = (1 << 1), /* device supports LBA48 */ 140 ATA_DFLAG_LBA48 = (1 << 1), /* device supports LBA48 */
141 ATA_DFLAG_CDB_INTR = (1 << 2), /* device asserts INTRQ when ready for CDB */ 141 ATA_DFLAG_CDB_INTR = (1 << 2), /* device asserts INTRQ when ready for CDB */
142 ATA_DFLAG_NCQ = (1 << 3), /* device supports NCQ */ 142 ATA_DFLAG_NCQ = (1 << 3), /* device supports NCQ */
143 ATA_DFLAG_FLUSH_EXT = (1 << 4), /* do FLUSH_EXT instead of FLUSH */
143 ATA_DFLAG_CFG_MASK = (1 << 8) - 1, 144 ATA_DFLAG_CFG_MASK = (1 << 8) - 1,
144 145
145 ATA_DFLAG_PIO = (1 << 8), /* device limited to PIO mode */ 146 ATA_DFLAG_PIO = (1 << 8), /* device limited to PIO mode */