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 | } | 
