Title: [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
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