diff options
Diffstat (limited to 'drivers/net/forcedeth.c')
-rw-r--r-- | drivers/net/forcedeth.c | 252 |
1 files changed, 105 insertions, 147 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 07e245dab680..2c3a7f851f20 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
@@ -3423,99 +3423,78 @@ static irqreturn_t nv_nic_irq(int foo, void *data) | |||
3423 | struct net_device *dev = (struct net_device *) data; | 3423 | struct net_device *dev = (struct net_device *) data; |
3424 | struct fe_priv *np = netdev_priv(dev); | 3424 | struct fe_priv *np = netdev_priv(dev); |
3425 | u8 __iomem *base = get_hwbase(dev); | 3425 | u8 __iomem *base = get_hwbase(dev); |
3426 | int i; | ||
3427 | 3426 | ||
3428 | dprintk(KERN_DEBUG "%s: nv_nic_irq\n", dev->name); | 3427 | dprintk(KERN_DEBUG "%s: nv_nic_irq\n", dev->name); |
3429 | 3428 | ||
3430 | for (i=0; ; i++) { | 3429 | if (!(np->msi_flags & NV_MSI_X_ENABLED)) { |
3431 | if (!(np->msi_flags & NV_MSI_X_ENABLED)) { | 3430 | np->events = readl(base + NvRegIrqStatus); |
3432 | np->events = readl(base + NvRegIrqStatus); | 3431 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); |
3433 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); | 3432 | } else { |
3434 | } else { | 3433 | np->events = readl(base + NvRegMSIXIrqStatus); |
3435 | np->events = readl(base + NvRegMSIXIrqStatus); | 3434 | writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); |
3436 | writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); | 3435 | } |
3437 | } | 3436 | dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events); |
3438 | dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events); | 3437 | if (!(np->events & np->irqmask)) |
3439 | if (!(np->events & np->irqmask)) | 3438 | return IRQ_NONE; |
3440 | break; | ||
3441 | 3439 | ||
3442 | nv_msi_workaround(np); | 3440 | nv_msi_workaround(np); |
3443 | 3441 | ||
3444 | #ifdef CONFIG_FORCEDETH_NAPI | 3442 | #ifdef CONFIG_FORCEDETH_NAPI |
3445 | spin_lock(&np->lock); | 3443 | spin_lock(&np->lock); |
3446 | napi_schedule(&np->napi); | 3444 | napi_schedule(&np->napi); |
3447 | 3445 | ||
3448 | /* Disable furthur irq's | 3446 | /* Disable furthur irq's |
3449 | (msix not enabled with napi) */ | 3447 | (msix not enabled with napi) */ |
3450 | writel(0, base + NvRegIrqMask); | 3448 | writel(0, base + NvRegIrqMask); |
3451 | 3449 | ||
3452 | spin_unlock(&np->lock); | 3450 | spin_unlock(&np->lock); |
3453 | 3451 | ||
3454 | return IRQ_HANDLED; | 3452 | return IRQ_HANDLED; |
3455 | #else | 3453 | #else |
3456 | spin_lock(&np->lock); | 3454 | spin_lock(&np->lock); |
3457 | nv_tx_done(dev, np->tx_ring_size); | 3455 | nv_tx_done(dev, np->tx_ring_size); |
3458 | spin_unlock(&np->lock); | 3456 | spin_unlock(&np->lock); |
3459 | |||
3460 | if (nv_rx_process(dev, RX_WORK_PER_LOOP)) { | ||
3461 | if (unlikely(nv_alloc_rx(dev))) { | ||
3462 | spin_lock(&np->lock); | ||
3463 | if (!np->in_shutdown) | ||
3464 | mod_timer(&np->oom_kick, jiffies + OOM_REFILL); | ||
3465 | spin_unlock(&np->lock); | ||
3466 | } | ||
3467 | } | ||
3468 | 3457 | ||
3469 | if (unlikely(np->events & NVREG_IRQ_LINK)) { | 3458 | if (nv_rx_process(dev, RX_WORK_PER_LOOP)) { |
3459 | if (unlikely(nv_alloc_rx(dev))) { | ||
3470 | spin_lock(&np->lock); | 3460 | spin_lock(&np->lock); |
3471 | nv_link_irq(dev); | 3461 | if (!np->in_shutdown) |
3472 | spin_unlock(&np->lock); | 3462 | mod_timer(&np->oom_kick, jiffies + OOM_REFILL); |
3473 | } | ||
3474 | if (unlikely(np->need_linktimer && time_after(jiffies, np->link_timeout))) { | ||
3475 | spin_lock(&np->lock); | ||
3476 | nv_linkchange(dev); | ||
3477 | spin_unlock(&np->lock); | 3463 | spin_unlock(&np->lock); |
3478 | np->link_timeout = jiffies + LINK_TIMEOUT; | ||
3479 | } | 3464 | } |
3480 | if (unlikely(np->events & NVREG_IRQ_RECOVER_ERROR)) { | 3465 | } |
3481 | spin_lock(&np->lock); | ||
3482 | /* disable interrupts on the nic */ | ||
3483 | if (!(np->msi_flags & NV_MSI_X_ENABLED)) | ||
3484 | writel(0, base + NvRegIrqMask); | ||
3485 | else | ||
3486 | writel(np->irqmask, base + NvRegIrqMask); | ||
3487 | pci_push(base); | ||
3488 | 3466 | ||
3489 | if (!np->in_shutdown) { | 3467 | if (unlikely(np->events & NVREG_IRQ_LINK)) { |
3490 | np->nic_poll_irq = np->irqmask; | 3468 | spin_lock(&np->lock); |
3491 | np->recover_error = 1; | 3469 | nv_link_irq(dev); |
3492 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); | 3470 | spin_unlock(&np->lock); |
3493 | } | 3471 | } |
3494 | spin_unlock(&np->lock); | 3472 | if (unlikely(np->need_linktimer && time_after(jiffies, np->link_timeout))) { |
3495 | break; | 3473 | spin_lock(&np->lock); |
3496 | } | 3474 | nv_linkchange(dev); |
3497 | if (unlikely(i > max_interrupt_work)) { | 3475 | spin_unlock(&np->lock); |
3498 | spin_lock(&np->lock); | 3476 | np->link_timeout = jiffies + LINK_TIMEOUT; |
3499 | /* disable interrupts on the nic */ | 3477 | } |
3500 | if (!(np->msi_flags & NV_MSI_X_ENABLED)) | 3478 | if (unlikely(np->events & NVREG_IRQ_RECOVER_ERROR)) { |
3501 | writel(0, base + NvRegIrqMask); | 3479 | spin_lock(&np->lock); |
3502 | else | 3480 | /* disable interrupts on the nic */ |
3503 | writel(np->irqmask, base + NvRegIrqMask); | 3481 | if (!(np->msi_flags & NV_MSI_X_ENABLED)) |
3504 | pci_push(base); | 3482 | writel(0, base + NvRegIrqMask); |
3483 | else | ||
3484 | writel(np->irqmask, base + NvRegIrqMask); | ||
3485 | pci_push(base); | ||
3505 | 3486 | ||
3506 | if (!np->in_shutdown) { | 3487 | if (!np->in_shutdown) { |
3507 | np->nic_poll_irq = np->irqmask; | 3488 | np->nic_poll_irq = np->irqmask; |
3508 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); | 3489 | np->recover_error = 1; |
3509 | } | 3490 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); |
3510 | spin_unlock(&np->lock); | ||
3511 | printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i); | ||
3512 | break; | ||
3513 | } | 3491 | } |
3514 | #endif | 3492 | spin_unlock(&np->lock); |
3515 | } | 3493 | } |
3494 | #endif | ||
3516 | dprintk(KERN_DEBUG "%s: nv_nic_irq completed\n", dev->name); | 3495 | dprintk(KERN_DEBUG "%s: nv_nic_irq completed\n", dev->name); |
3517 | 3496 | ||
3518 | return IRQ_RETVAL(i); | 3497 | return IRQ_HANDLED; |
3519 | } | 3498 | } |
3520 | 3499 | ||
3521 | /** | 3500 | /** |
@@ -3528,100 +3507,79 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) | |||
3528 | struct net_device *dev = (struct net_device *) data; | 3507 | struct net_device *dev = (struct net_device *) data; |
3529 | struct fe_priv *np = netdev_priv(dev); | 3508 | struct fe_priv *np = netdev_priv(dev); |
3530 | u8 __iomem *base = get_hwbase(dev); | 3509 | u8 __iomem *base = get_hwbase(dev); |
3531 | int i; | ||
3532 | 3510 | ||
3533 | dprintk(KERN_DEBUG "%s: nv_nic_irq_optimized\n", dev->name); | 3511 | dprintk(KERN_DEBUG "%s: nv_nic_irq_optimized\n", dev->name); |
3534 | 3512 | ||
3535 | for (i=0; ; i++) { | 3513 | if (!(np->msi_flags & NV_MSI_X_ENABLED)) { |
3536 | if (!(np->msi_flags & NV_MSI_X_ENABLED)) { | 3514 | np->events = readl(base + NvRegIrqStatus); |
3537 | np->events = readl(base + NvRegIrqStatus); | 3515 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); |
3538 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); | 3516 | } else { |
3539 | } else { | 3517 | np->events = readl(base + NvRegMSIXIrqStatus); |
3540 | np->events = readl(base + NvRegMSIXIrqStatus); | 3518 | writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); |
3541 | writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); | 3519 | } |
3542 | } | 3520 | dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events); |
3543 | dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events); | 3521 | if (!(np->events & np->irqmask)) |
3544 | if (!(np->events & np->irqmask)) | 3522 | return IRQ_NONE; |
3545 | break; | ||
3546 | 3523 | ||
3547 | nv_msi_workaround(np); | 3524 | nv_msi_workaround(np); |
3548 | 3525 | ||
3549 | #ifdef CONFIG_FORCEDETH_NAPI | 3526 | #ifdef CONFIG_FORCEDETH_NAPI |
3550 | spin_lock(&np->lock); | 3527 | spin_lock(&np->lock); |
3551 | napi_schedule(&np->napi); | 3528 | napi_schedule(&np->napi); |
3552 | 3529 | ||
3553 | /* Disable furthur irq's | 3530 | /* Disable furthur irq's |
3554 | (msix not enabled with napi) */ | 3531 | (msix not enabled with napi) */ |
3555 | writel(0, base + NvRegIrqMask); | 3532 | writel(0, base + NvRegIrqMask); |
3556 | 3533 | ||
3557 | spin_unlock(&np->lock); | 3534 | spin_unlock(&np->lock); |
3558 | 3535 | ||
3559 | return IRQ_HANDLED; | 3536 | return IRQ_HANDLED; |
3560 | #else | 3537 | #else |
3561 | spin_lock(&np->lock); | 3538 | spin_lock(&np->lock); |
3562 | nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); | 3539 | nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); |
3563 | spin_unlock(&np->lock); | 3540 | spin_unlock(&np->lock); |
3564 | |||
3565 | if (nv_rx_process_optimized(dev, RX_WORK_PER_LOOP)) { | ||
3566 | if (unlikely(nv_alloc_rx_optimized(dev))) { | ||
3567 | spin_lock(&np->lock); | ||
3568 | if (!np->in_shutdown) | ||
3569 | mod_timer(&np->oom_kick, jiffies + OOM_REFILL); | ||
3570 | spin_unlock(&np->lock); | ||
3571 | } | ||
3572 | } | ||
3573 | 3541 | ||
3574 | if (unlikely(np->events & NVREG_IRQ_LINK)) { | 3542 | if (nv_rx_process_optimized(dev, RX_WORK_PER_LOOP)) { |
3543 | if (unlikely(nv_alloc_rx_optimized(dev))) { | ||
3575 | spin_lock(&np->lock); | 3544 | spin_lock(&np->lock); |
3576 | nv_link_irq(dev); | 3545 | if (!np->in_shutdown) |
3577 | spin_unlock(&np->lock); | 3546 | mod_timer(&np->oom_kick, jiffies + OOM_REFILL); |
3578 | } | ||
3579 | if (unlikely(np->need_linktimer && time_after(jiffies, np->link_timeout))) { | ||
3580 | spin_lock(&np->lock); | ||
3581 | nv_linkchange(dev); | ||
3582 | spin_unlock(&np->lock); | ||
3583 | np->link_timeout = jiffies + LINK_TIMEOUT; | ||
3584 | } | ||
3585 | if (unlikely(np->events & NVREG_IRQ_RECOVER_ERROR)) { | ||
3586 | spin_lock(&np->lock); | ||
3587 | /* disable interrupts on the nic */ | ||
3588 | if (!(np->msi_flags & NV_MSI_X_ENABLED)) | ||
3589 | writel(0, base + NvRegIrqMask); | ||
3590 | else | ||
3591 | writel(np->irqmask, base + NvRegIrqMask); | ||
3592 | pci_push(base); | ||
3593 | |||
3594 | if (!np->in_shutdown) { | ||
3595 | np->nic_poll_irq = np->irqmask; | ||
3596 | np->recover_error = 1; | ||
3597 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); | ||
3598 | } | ||
3599 | spin_unlock(&np->lock); | 3547 | spin_unlock(&np->lock); |
3600 | break; | ||
3601 | } | 3548 | } |
3549 | } | ||
3602 | 3550 | ||
3603 | if (unlikely(i > max_interrupt_work)) { | 3551 | if (unlikely(np->events & NVREG_IRQ_LINK)) { |
3604 | spin_lock(&np->lock); | 3552 | spin_lock(&np->lock); |
3605 | /* disable interrupts on the nic */ | 3553 | nv_link_irq(dev); |
3606 | if (!(np->msi_flags & NV_MSI_X_ENABLED)) | 3554 | spin_unlock(&np->lock); |
3607 | writel(0, base + NvRegIrqMask); | 3555 | } |
3608 | else | 3556 | if (unlikely(np->need_linktimer && time_after(jiffies, np->link_timeout))) { |
3609 | writel(np->irqmask, base + NvRegIrqMask); | 3557 | spin_lock(&np->lock); |
3610 | pci_push(base); | 3558 | nv_linkchange(dev); |
3559 | spin_unlock(&np->lock); | ||
3560 | np->link_timeout = jiffies + LINK_TIMEOUT; | ||
3561 | } | ||
3562 | if (unlikely(np->events & NVREG_IRQ_RECOVER_ERROR)) { | ||
3563 | spin_lock(&np->lock); | ||
3564 | /* disable interrupts on the nic */ | ||
3565 | if (!(np->msi_flags & NV_MSI_X_ENABLED)) | ||
3566 | writel(0, base + NvRegIrqMask); | ||
3567 | else | ||
3568 | writel(np->irqmask, base + NvRegIrqMask); | ||
3569 | pci_push(base); | ||
3611 | 3570 | ||
3612 | if (!np->in_shutdown) { | 3571 | if (!np->in_shutdown) { |
3613 | np->nic_poll_irq = np->irqmask; | 3572 | np->nic_poll_irq = np->irqmask; |
3614 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); | 3573 | np->recover_error = 1; |
3615 | } | 3574 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); |
3616 | spin_unlock(&np->lock); | ||
3617 | printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i); | ||
3618 | break; | ||
3619 | } | 3575 | } |
3620 | #endif | 3576 | spin_unlock(&np->lock); |
3621 | } | 3577 | } |
3578 | |||
3579 | #endif | ||
3622 | dprintk(KERN_DEBUG "%s: nv_nic_irq_optimized completed\n", dev->name); | 3580 | dprintk(KERN_DEBUG "%s: nv_nic_irq_optimized completed\n", dev->name); |
3623 | 3581 | ||
3624 | return IRQ_RETVAL(i); | 3582 | return IRQ_HANDLED; |
3625 | } | 3583 | } |
3626 | 3584 | ||
3627 | static irqreturn_t nv_nic_irq_tx(int foo, void *data) | 3585 | static irqreturn_t nv_nic_irq_tx(int foo, void *data) |