[PATCH 3/4] g_NCR5380: Fix automatic IRQ on HP C2502 cards

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When IRQ_AUTO is used, the interrupt for HP C2502 cards gets disabled.
Fix this by programming the card for a suitable free irq. The code for
the free irq search comes from ALSA.

Also allow IRQ 9 to work (it aliases to IRQ 2 on the card), as per
Ondrej Zary's patch.

Suggested-by: Ondrej Zary <linux@xxxxxxxxxxxxxxxxxxxx>
Signed-off-by: Finn Thain <fthain@xxxxxxxxxxxxxxxxxxx>
---
 drivers/scsi/g_NCR5380.c | 70 +++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 57 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 6d245a7..58a0b82 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -131,14 +131,33 @@ static void magic_configure(int idx, u8 irq, u8 magic[])
 	outb(magic[3], 0x379);
 	outb(magic[4], 0x379);
 
-	/* allowed IRQs for HP C2502 */
-	if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7)
-		irq = 0;
+	if (irq == 9)
+		irq = 2;
+
 	if (idx >= 0 && idx <= 7)
 		cfg = 0x80 | idx | (irq << 4);
 	outb(cfg, 0x379);
 }
 
+static irqreturn_t legacy_empty_irq_handler(int irq, void *dev_id)
+{
+	return IRQ_HANDLED;
+}
+
+static int legacy_find_free_irq(int *irq_table)
+{
+	while (*irq_table != -1) {
+		if (!request_irq(*irq_table, legacy_empty_irq_handler,
+		                 IRQF_PROBE_SHARED, "Test IRQ",
+		                 (void *)irq_table)) {
+			free_irq(*irq_table, (void *) irq_table);
+			return *irq_table;
+		}
+		irq_table++;
+	}
+	return -1;
+}
+
 static unsigned int ncr_53c400a_ports[] = {
 	0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0
 };
@@ -151,6 +170,9 @@ static u8 ncr_53c400a_magic[] = {	/* 53C400A & DTC436 */
 static u8 hp_c2502_magic[] = {	/* HP C2502 */
 	0x0f, 0x22, 0xf0, 0x20, 0x80
 };
+static int hp_c2502_irqs[] = {
+	9, 5, 7, 3, 4, -1
+};
 
 static int generic_NCR5380_init_one(struct scsi_host_template *tpnt,
 			struct device *pdev, int base, int irq, int board)
@@ -319,19 +341,41 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt,
 
 	NCR5380_maybe_reset_bus(instance);
 
-	if (irq != IRQ_AUTO)
-		instance->irq = irq;
-	else
-		instance->irq = g_NCR5380_probe_irq(instance);
-
 	/* Compatibility with documented NCR5380 kernel parameters */
-	if (instance->irq == 255)
-		instance->irq = NO_IRQ;
+	if (irq == 255 || irq == 0)
+		irq = NO_IRQ;
+
+	if (board == BOARD_HP_C2502) {
+		int *irq_table = hp_c2502_irqs;
+		int board_irq = -1;
+
+		switch (irq) {
+		case NO_IRQ:
+			board_irq = 0;
+			break;
+		case IRQ_AUTO:
+			board_irq = legacy_find_free_irq(irq_table);
+			break;
+		default:
+			while (*irq_table != -1)
+				if (*irq_table++ == irq)
+					board_irq = irq;
+		}
+
+		if (board_irq <= 0) {
+			board_irq = 0;
+			irq = NO_IRQ;
+		}
+
+		magic_configure(port_idx, board_irq, magic);
+	}
+
+	if (irq == IRQ_AUTO)
+		instance->irq = g_NCR5380_probe_irq(instance);
+	else
+		instance->irq = irq;
 
 	if (instance->irq != NO_IRQ) {
-		/* set IRQ for HP C2502 */
-		if (board == BOARD_HP_C2502)
-			magic_configure(port_idx, instance->irq, magic);
 		if (request_irq(instance->irq, generic_NCR5380_intr,
 				0, "NCR5380", instance)) {
 			printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
-- 
2.7.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux