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

Reply via email to