aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/3c503.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/3c503.c')
-rw-r--r--drivers/net/3c503.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index 66e0323c1839..baac246561b9 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -380,6 +380,12 @@ out:
380 return retval; 380 return retval;
381} 381}
382 382
383static irqreturn_t el2_probe_interrupt(int irq, void *seen)
384{
385 *(bool *)seen = true;
386 return IRQ_HANDLED;
387}
388
383static int 389static int
384el2_open(struct net_device *dev) 390el2_open(struct net_device *dev)
385{ 391{
@@ -391,23 +397,35 @@ el2_open(struct net_device *dev)
391 397
392 outb(EGACFR_NORM, E33G_GACFR); /* Enable RAM and interrupts. */ 398 outb(EGACFR_NORM, E33G_GACFR); /* Enable RAM and interrupts. */
393 do { 399 do {
394 retval = request_irq(*irqp, NULL, 0, "bogus", dev); 400 bool seen;
395 if (retval >= 0) { 401
402 retval = request_irq(*irqp, el2_probe_interrupt, 0,
403 dev->name, &seen);
404 if (retval == -EBUSY)
405 continue;
406 if (retval < 0)
407 goto err_disable;
408
396 /* Twinkle the interrupt, and check if it's seen. */ 409 /* Twinkle the interrupt, and check if it's seen. */
397 unsigned long cookie = probe_irq_on(); 410 seen = false;
411 smp_wmb();
398 outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR); 412 outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR);
399 outb_p(0x00, E33G_IDCFR); 413 outb_p(0x00, E33G_IDCFR);
400 if (*irqp == probe_irq_off(cookie) && /* It's a good IRQ line! */ 414 msleep(1);
401 ((retval = request_irq(dev->irq = *irqp, 415 free_irq(*irqp, el2_probe_interrupt);
402 eip_interrupt, 0, 416 if (!seen)
403 dev->name, dev)) == 0)) 417 continue;
404 break; 418
405 } else { 419 retval = request_irq(dev->irq = *irqp, eip_interrupt, 0,
406 if (retval != -EBUSY) 420 dev->name, dev);
407 return retval; 421 if (retval == -EBUSY)
408 } 422 continue;
423 if (retval < 0)
424 goto err_disable;
409 } while (*++irqp); 425 } while (*++irqp);
426
410 if (*irqp == 0) { 427 if (*irqp == 0) {
428 err_disable:
411 outb(EGACFR_IRQOFF, E33G_GACFR); /* disable interrupts. */ 429 outb(EGACFR_IRQOFF, E33G_GACFR); /* disable interrupts. */
412 return -EAGAIN; 430 return -EAGAIN;
413 } 431 }
@@ -555,7 +573,6 @@ el2_block_output(struct net_device *dev, int count,
555 } 573 }
556 blocked:; 574 blocked:;
557 outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL); 575 outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
558 return;
559} 576}
560 577
561/* Read the 4 byte, page aligned 8390 specific header. */ 578/* Read the 4 byte, page aligned 8390 specific header. */
@@ -671,7 +688,6 @@ el2_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring
671 } 688 }
672 blocked:; 689 blocked:;
673 outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL); 690 outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
674 return;
675} 691}
676 692
677 693