aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFinn Thain <fthain@telegraphics.com.au>2016-12-05 01:07:20 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2016-12-08 16:57:58 -0500
commit145c3ae4c1933d0dceb11d19a36de3458d1872cb (patch)
treec47c5d1f19042afb9f56fce1ac61809452c8b553
parent906e4a3c7e03701008d343daec8952d6cf49f82b (diff)
scsi: g_NCR5380: Fix automatic IRQ on HP C2502 cards
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@rainbow-software.org> Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Tested-by: Ondrej Zary <linux@rainbow-software.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/g_NCR5380.c70
1 files changed, 57 insertions, 13 deletions
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 6d245a7b9363..58a0b826eb51 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[])
131 outb(magic[3], 0x379); 131 outb(magic[3], 0x379);
132 outb(magic[4], 0x379); 132 outb(magic[4], 0x379);
133 133
134 /* allowed IRQs for HP C2502 */ 134 if (irq == 9)
135 if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7) 135 irq = 2;
136 irq = 0; 136
137 if (idx >= 0 && idx <= 7) 137 if (idx >= 0 && idx <= 7)
138 cfg = 0x80 | idx | (irq << 4); 138 cfg = 0x80 | idx | (irq << 4);
139 outb(cfg, 0x379); 139 outb(cfg, 0x379);
140} 140}
141 141
142static irqreturn_t legacy_empty_irq_handler(int irq, void *dev_id)
143{
144 return IRQ_HANDLED;
145}
146
147static int legacy_find_free_irq(int *irq_table)
148{
149 while (*irq_table != -1) {
150 if (!request_irq(*irq_table, legacy_empty_irq_handler,
151 IRQF_PROBE_SHARED, "Test IRQ",
152 (void *)irq_table)) {
153 free_irq(*irq_table, (void *) irq_table);
154 return *irq_table;
155 }
156 irq_table++;
157 }
158 return -1;
159}
160
142static unsigned int ncr_53c400a_ports[] = { 161static unsigned int ncr_53c400a_ports[] = {
143 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0 162 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0
144}; 163};
@@ -151,6 +170,9 @@ static u8 ncr_53c400a_magic[] = { /* 53C400A & DTC436 */
151static u8 hp_c2502_magic[] = { /* HP C2502 */ 170static u8 hp_c2502_magic[] = { /* HP C2502 */
152 0x0f, 0x22, 0xf0, 0x20, 0x80 171 0x0f, 0x22, 0xf0, 0x20, 0x80
153}; 172};
173static int hp_c2502_irqs[] = {
174 9, 5, 7, 3, 4, -1
175};
154 176
155static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, 177static int generic_NCR5380_init_one(struct scsi_host_template *tpnt,
156 struct device *pdev, int base, int irq, int board) 178 struct device *pdev, int base, int irq, int board)
@@ -319,19 +341,41 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt,
319 341
320 NCR5380_maybe_reset_bus(instance); 342 NCR5380_maybe_reset_bus(instance);
321 343
322 if (irq != IRQ_AUTO)
323 instance->irq = irq;
324 else
325 instance->irq = g_NCR5380_probe_irq(instance);
326
327 /* Compatibility with documented NCR5380 kernel parameters */ 344 /* Compatibility with documented NCR5380 kernel parameters */
328 if (instance->irq == 255) 345 if (irq == 255 || irq == 0)
329 instance->irq = NO_IRQ; 346 irq = NO_IRQ;
347
348 if (board == BOARD_HP_C2502) {
349 int *irq_table = hp_c2502_irqs;
350 int board_irq = -1;
351
352 switch (irq) {
353 case NO_IRQ:
354 board_irq = 0;
355 break;
356 case IRQ_AUTO:
357 board_irq = legacy_find_free_irq(irq_table);
358 break;
359 default:
360 while (*irq_table != -1)
361 if (*irq_table++ == irq)
362 board_irq = irq;
363 }
364
365 if (board_irq <= 0) {
366 board_irq = 0;
367 irq = NO_IRQ;
368 }
369
370 magic_configure(port_idx, board_irq, magic);
371 }
372
373 if (irq == IRQ_AUTO)
374 instance->irq = g_NCR5380_probe_irq(instance);
375 else
376 instance->irq = irq;
330 377
331 if (instance->irq != NO_IRQ) { 378 if (instance->irq != NO_IRQ) {
332 /* set IRQ for HP C2502 */
333 if (board == BOARD_HP_C2502)
334 magic_configure(port_idx, instance->irq, magic);
335 if (request_irq(instance->irq, generic_NCR5380_intr, 379 if (request_irq(instance->irq, generic_NCR5380_intr,
336 0, "NCR5380", instance)) { 380 0, "NCR5380", instance)) {
337 printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); 381 printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);