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

Reply via email to