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
