Hi Barry,

I think this issue is caused by a Pull-Up resistor on the INTRQ line on
the CF-IDE-NAND Card.

Read this:
http://www.mail-archive.com/[email protected]/msg00418.html

On the CF Card socket we also have that pull-up - but there we had no
choice since in PC-Card IO mode the Interrupt is asserted Low. So this
was a tradeoff, and at the time doing the card - it worked without
errors. 

The problem here is that the INTRQ signal output line has a high
impedance when no devices are
selected or interruption is disabled.

Like you noticed, recent Linux libata assumes the INTRQ staying inactive
the time between the IRQ is requested and the device is configured.

If this fix isn't acceptable to mainline we should revert - and fix the
HW.

-Michael
  

________________________________________
From: [email protected]
[mailto:[email protected]] On Behalf Of
[email protected]
Sent: Friday, July 10, 2009 6:31 AM
To: [email protected]
Subject: [Linux-kernel-commits] [6960] trunk/drivers/ata/libata-core.c:
1.

Revision
6960
Author
bhsong
Date
2009-07-09 23:31:19 -0500 (Thu, 09 Jul 2009)
Log Message
1. Fix bug [#4607], since irq is enabled after probe, we can use polling
in probe;
That also fixed the problem "qc timeout (cmd 0x27) failed to read native
max address (err_mask=0x4)
" for ATA       
2. Change IRQF_DISABLED flag to IRQ_NOAUTOEN since only IRQ_NOAUTOEN
cares about whether irq is 
enabled with request
Modified Paths
* trunk/drivers/ata/libata-core.c
Diff
Modified: trunk/drivers/ata/libata-core.c (6959 => 6960)

--- trunk/drivers/ata/libata-core.c     2009-07-10 02:49:11 UTC (rev
6959)
+++ trunk/drivers/ata/libata-core.c     2009-07-10 04:31:19 UTC (rev
6960)
@@ -64,6 +64,7 @@
 #include <linux/libata.h>
 #include <asm/byteorder.h>
 #include <linux/cdrom.h>
+#include <linux/irq.h>
 
 #include "libata.h"
 
@@ -5993,21 +5994,34 @@
        host->ops = ops;
 }
 
-void async_irq_enable(void *data, async_cookie_t cookie)
+void async_scsi_scan_with_irq(void *data, async_cookie_t cookie)
 {
        struct ata_host *host = data;
+       int i;
 
        /* in order to make irq enabled after probing, we need to
synchronize at this point */
        async_synchronize_cookie(cookie);
 
        enable_irq(host->irq);
+
+       /* perform scsi scan orderly to keep device order */
+       for (i = 0; i < host->n_ports; i++) {
+               struct ata_port *ap = host->ports[i];
+               ata_scsi_scan_host(ap, 1);
+       }
 }
 
 static void async_port_probe(void *data, async_cookie_t cookie)
 {
        int rc;
        struct ata_port *ap = data;
+       struct irq_desc *desc;
 
+       /* to workaround the hardware interrupt issue, use polling for
probe */
+       desc = (ap->host->irq > 0) ? irq_to_desc(ap->host->irq) : NULL;
+       if (ap->host->irq && (desc->status & IRQ_NOAUTOEN))
+               ap->flags |= ATA_FLAG_PIO_POLLING;
+
        /*
         * If we're not allowed to scan this host in parallel,
         * we need to wait until all previous scans have completed
@@ -6055,12 +6069,19 @@
                }
        }
 
+       /* restore to irq mode for data transfer */
+       if (ap->host->irq && (desc->status & IRQ_NOAUTOEN)) {
+               ap->flags &= ~ATA_FLAG_PIO_POLLING;
+               /* ata_scsi_scan_host can happen after irq is enabled */
+               return;
+       }
+
        /* in order to keep device order, we need to synchronize at this
point */
        async_synchronize_cookie(cookie);
 
        ata_scsi_scan_host(ap, 1);
+}
 
-}
 /**
  *     ata_host_register - register initialized ATA host
  *     @host: ATA host to register
@@ -6080,7 +6101,10 @@
 int ata_host_register(struct ata_host *host, struct scsi_host_template
*sht)
 {
        int i, rc;
+       struct irq_desc *desc;
 
+       desc = (host->irq > 0) ? irq_to_desc(host->irq) : NULL;
+
        /* host must have been started */
        if (!(host->flags & ATA_HOST_STARTED)) {
                dev_printk(KERN_ERR, host->dev,
@@ -6143,8 +6167,8 @@
        }
 
        /* enable irq after probe if it is asked to be disabled when
request */
-       if (host->irq_flags & IRQF_DISABLED)
-               async_schedule(async_irq_enable, host);
+       if (host->irq && (desc->status & IRQ_NOAUTOEN))
+               async_schedule(async_scsi_scan_with_irq, host);
 
        return 0;
 }

_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to