Some devices raise irq early before clearing the BSY.
This patch adds blacklist and waits up to 10 microseconds to workaround the
early irq problem.
Signed-off-by: Albert Lee <[EMAIL PROTECTED]>
---
Ok, we should not affect the good devices.
Patch revised for your review.
(against the libata-dev tree 6b78c0d20ffbc89acc3c2790f8d7eded05606813).
diff -Nrup 000_libata_dev/drivers/ata/libata-core.c
001_early_irq/drivers/ata/libata-core.c
--- 000_libata_dev/drivers/ata/libata-core.c 2006-11-30 15:53:08.000000000
+0800
+++ 001_early_irq/drivers/ata/libata-core.c 2006-11-30 16:41:23.000000000
+0800
@@ -1610,6 +1610,9 @@ int ata_dev_configure(struct ata_device
if (dev->flags & ATA_DFLAG_LBA48)
dev->max_sectors = ATA_MAX_SECTORS_LBA48;
+ if (ata_device_blacklisted(dev) & ATA_HORKAGE_EARLY_IRQ)
+ dev->horkage |= ATA_HORKAGE_EARLY_IRQ;
+
if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
/* Let the user know. We don't want to disallow opens for
rescue purposes, or in case the vendor is just a blithering
@@ -3184,6 +3187,9 @@ static const struct ata_blacklist_entry
/* Devices with NCQ limits */
+ /* Devices with early IRQ */
+ { "CD-ROM 36X/AKW", NULL, ATA_HORKAGE_EARLY_IRQ },
+
/* End Marker */
{ }
};
@@ -4989,6 +4995,11 @@ inline unsigned int ata_host_intr (struc
goto idle_irq;
}
+ /* some drives raise INTRQ early before clearing BSY */
+ if (unlikely(qc->dev->horkage & ATA_HORKAGE_EARLY_IRQ))
+ /* wait up to 10 microseconds for BSY to clear */
+ ata_busy_wait_alt(ap, ATA_BUSY, ATA_EARLY_IRQ_WAIT);
+
/* check altstatus */
status = ata_altstatus(ap);
if (status & ATA_BUSY)
diff -Nrup 000_libata_dev/include/linux/libata.h
001_early_irq/include/linux/libata.h
--- 000_libata_dev/include/linux/libata.h 2006-11-30 15:53:26.000000000
+0800
+++ 001_early_irq/include/linux/libata.h 2006-11-30 17:04:37.000000000
+0800
@@ -309,6 +309,9 @@ enum {
* most devices.
*/
ATA_SPINUP_WAIT = 8000,
+
+ /* early irq max wait time (for BSY to clear) in usecs */
+ ATA_EARLY_IRQ_WAIT = 10,
/* Horkage types. May be set by libata or controller on drives
(some horkage may be drive/controller pair dependant */
@@ -316,6 +319,7 @@ enum {
ATA_HORKAGE_DIAGNOSTIC = (1 << 0), /* Failed boot diag */
ATA_HORKAGE_NODMA = (1 << 1), /* DMA problems */
ATA_HORKAGE_NONCQ = (1 << 2), /* Don't use NCQ */
+ ATA_HORKAGE_EARLY_IRQ = (1 << 3), /* Early IRQ */
};
enum hsm_task_states {
@@ -1056,6 +1060,30 @@ static inline void ata_pause(struct ata_
ndelay(400);
}
+/**
+ * ata_busy_wait_alt - Wait for a port alt status register
+ * @ap: Port to wait for.
+ *
+ * Waits up to max microseconds for the selected bits in the port's
+ * alt status register to be cleared.
+ * Returns final value of alt status register.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static inline u8 ata_busy_wait_alt(struct ata_port *ap, unsigned int bits,
+ unsigned int max)
+{
+ u8 status = ata_altstatus(ap);
+
+ while ((status & bits) && (max > 0)) {
+ udelay(1);
+ status = ata_altstatus(ap);
+ max--;
+ };
+
+ return status;
+}
/**
* ata_busy_wait - Wait for a port status register
-
To unsubscribe from this list: send the line "unsubscribe linux-ide" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html