From 6fc49adb9417b9c793e8f88d485387bb89ceb733 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 11 Nov 2006 20:10:45 +0900 Subject: [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 Cc: Danny Kukawka Cc: Stefan Seyfried Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 6 +++++- drivers/ata/libata-scsi.c | 3 +-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') 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) if (ata_id_has_lba48(id)) { dev->flags |= ATA_DFLAG_LBA48; lba_desc = "LBA48"; + + if (dev->n_sectors >= (1UL << 28) && + ata_id_has_flush_ext(id)) + dev->flags |= ATA_DFLAG_FLUSH_EXT; } /* config NCQ */ @@ -5128,7 +5132,7 @@ int ata_flush_cache(struct ata_device *dev) if (!ata_try_flush_cache(dev)) return 0; - if (ata_id_has_flush_ext(dev->id)) + if (dev->flags & ATA_DFLAG_FLUSH_EXT) cmd = ATA_CMD_FLUSH_EXT; else 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 tf->flags |= ATA_TFLAG_DEVICE; tf->protocol = ATA_PROT_NODATA; - if ((qc->dev->flags & ATA_DFLAG_LBA48) && - (ata_id_has_flush_ext(qc->dev->id))) + if (qc->dev->flags & ATA_DFLAG_FLUSH_EXT) tf->command = ATA_CMD_FLUSH_EXT; else tf->command = ATA_CMD_FLUSH; -- cgit v1.2.2