diff options
Diffstat (limited to 'drivers/net/3c503.c')
-rw-r--r-- | drivers/net/3c503.c | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c index 66e0323c1839..b74a0eadbd6c 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 | ||
383 | static irqreturn_t el2_probe_interrupt(int irq, void *seen) | ||
384 | { | ||
385 | *(bool *)seen = true; | ||
386 | return IRQ_HANDLED; | ||
387 | } | ||
388 | |||
383 | static int | 389 | static int |
384 | el2_open(struct net_device *dev) | 390 | el2_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 | } |