diff options
author | Tony Zelenoff <antonz@parallels.com> | 2012-04-13 02:09:47 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-04-15 12:55:07 -0400 |
commit | 6294512bbe5288a29f146a3cd12921bda8bce4eb (patch) | |
tree | f6ecff9eee161330b2fc0953afa13ae2e0e795d5 /drivers/net/ethernet/atheros/atlx | |
parent | 3e1d83f711cda05e326d8a4baa6fa34ee18ad7b8 (diff) |
atl1: make driver napi compatible
This is first step, here there is no fine interrupt
disabling which cause TX/ERR interrupts stalling when
RX scheduled ints processed.
Signed-off-by: Tony Zelenoff <antonz@parallels.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/atheros/atlx')
-rw-r--r-- | drivers/net/ethernet/atheros/atlx/atl1.c | 46 | ||||
-rw-r--r-- | drivers/net/ethernet/atheros/atlx/atl1.h | 1 |
2 files changed, 41 insertions, 6 deletions
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c index c63152886b3e..b7a6484c5e05 100644 --- a/drivers/net/ethernet/atheros/atlx/atl1.c +++ b/drivers/net/ethernet/atheros/atlx/atl1.c | |||
@@ -1917,7 +1917,7 @@ next: | |||
1917 | return num_alloc; | 1917 | return num_alloc; |
1918 | } | 1918 | } |
1919 | 1919 | ||
1920 | static void atl1_intr_rx(struct atl1_adapter *adapter) | 1920 | static int atl1_intr_rx(struct atl1_adapter *adapter, int budget) |
1921 | { | 1921 | { |
1922 | int i, count; | 1922 | int i, count; |
1923 | u16 length; | 1923 | u16 length; |
@@ -1933,7 +1933,7 @@ static void atl1_intr_rx(struct atl1_adapter *adapter) | |||
1933 | 1933 | ||
1934 | rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean); | 1934 | rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean); |
1935 | 1935 | ||
1936 | while (1) { | 1936 | while (count < budget) { |
1937 | rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean); | 1937 | rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean); |
1938 | i = 1; | 1938 | i = 1; |
1939 | if (likely(rrd->xsz.valid)) { /* packet valid */ | 1939 | if (likely(rrd->xsz.valid)) { /* packet valid */ |
@@ -2032,7 +2032,7 @@ rrd_ok: | |||
2032 | 2032 | ||
2033 | __vlan_hwaccel_put_tag(skb, vlan_tag); | 2033 | __vlan_hwaccel_put_tag(skb, vlan_tag); |
2034 | } | 2034 | } |
2035 | netif_rx(skb); | 2035 | netif_receive_skb(skb); |
2036 | 2036 | ||
2037 | /* let protocol layer free skb */ | 2037 | /* let protocol layer free skb */ |
2038 | buffer_info->skb = NULL; | 2038 | buffer_info->skb = NULL; |
@@ -2065,6 +2065,8 @@ rrd_ok: | |||
2065 | iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX); | 2065 | iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX); |
2066 | spin_unlock(&adapter->mb_lock); | 2066 | spin_unlock(&adapter->mb_lock); |
2067 | } | 2067 | } |
2068 | |||
2069 | return count; | ||
2068 | } | 2070 | } |
2069 | 2071 | ||
2070 | static void atl1_intr_tx(struct atl1_adapter *adapter) | 2072 | static void atl1_intr_tx(struct atl1_adapter *adapter) |
@@ -2439,6 +2441,33 @@ static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb, | |||
2439 | return NETDEV_TX_OK; | 2441 | return NETDEV_TX_OK; |
2440 | } | 2442 | } |
2441 | 2443 | ||
2444 | static int atl1_rx_clean(struct napi_struct *napi, int budget) | ||
2445 | { | ||
2446 | struct atl1_adapter *adapter = container_of(napi, struct atl1_adapter, napi); | ||
2447 | int work_done = atl1_intr_rx(adapter, budget); | ||
2448 | |||
2449 | /* Let's come again to process some more packets */ | ||
2450 | if (work_done >= budget) | ||
2451 | return work_done; | ||
2452 | |||
2453 | napi_complete(napi); | ||
2454 | /* re-enable Interrupt */ | ||
2455 | iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR); | ||
2456 | return work_done; | ||
2457 | } | ||
2458 | |||
2459 | static inline int atl1_sched_rx(struct atl1_adapter* adapter) | ||
2460 | { | ||
2461 | if (likely(napi_schedule_prep(&adapter->napi))) { | ||
2462 | __napi_schedule(&adapter->napi); | ||
2463 | return 1; | ||
2464 | } | ||
2465 | |||
2466 | dev_printk(KERN_ERR, &adapter->pdev->dev, | ||
2467 | "rx: INTs must be disabled!"); | ||
2468 | return 0; | ||
2469 | } | ||
2470 | |||
2442 | /* | 2471 | /* |
2443 | * atl1_intr - Interrupt Handler | 2472 | * atl1_intr - Interrupt Handler |
2444 | * @irq: interrupt number | 2473 | * @irq: interrupt number |
@@ -2503,8 +2532,9 @@ static irqreturn_t atl1_intr(int irq, void *data) | |||
2503 | atl1_intr_tx(adapter); | 2532 | atl1_intr_tx(adapter); |
2504 | 2533 | ||
2505 | /* rx event */ | 2534 | /* rx event */ |
2506 | if (status & ISR_CMB_RX) | 2535 | if (status & ISR_CMB_RX && atl1_sched_rx(adapter)) |
2507 | alt1_intr_rx(adapter); | 2536 | /* Go away with INTs disabled */ |
2537 | return IRQ_HANDLED; | ||
2508 | 2538 | ||
2509 | /* rx exception */ | 2539 | /* rx exception */ |
2510 | if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN | | 2540 | if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN | |
@@ -2515,7 +2545,8 @@ static irqreturn_t atl1_intr(int irq, void *data) | |||
2515 | &adapter->pdev->dev, | 2545 | &adapter->pdev->dev, |
2516 | "rx exception, ISR = 0x%x\n", | 2546 | "rx exception, ISR = 0x%x\n", |
2517 | status); | 2547 | status); |
2518 | atl1_intr_rx(adapter); | 2548 | if (atl1_sched_rx(adapter)) |
2549 | return IRQ_HANDLED; | ||
2519 | } | 2550 | } |
2520 | 2551 | ||
2521 | if (--max_ints < 0) | 2552 | if (--max_ints < 0) |
@@ -2600,6 +2631,7 @@ static s32 atl1_up(struct atl1_adapter *adapter) | |||
2600 | if (unlikely(err)) | 2631 | if (unlikely(err)) |
2601 | goto err_up; | 2632 | goto err_up; |
2602 | 2633 | ||
2634 | napi_enable(&adapter->napi); | ||
2603 | atlx_irq_enable(adapter); | 2635 | atlx_irq_enable(adapter); |
2604 | atl1_check_link(adapter); | 2636 | atl1_check_link(adapter); |
2605 | netif_start_queue(netdev); | 2637 | netif_start_queue(netdev); |
@@ -2616,6 +2648,7 @@ static void atl1_down(struct atl1_adapter *adapter) | |||
2616 | { | 2648 | { |
2617 | struct net_device *netdev = adapter->netdev; | 2649 | struct net_device *netdev = adapter->netdev; |
2618 | 2650 | ||
2651 | napi_disable(&adapter->napi); | ||
2619 | netif_stop_queue(netdev); | 2652 | netif_stop_queue(netdev); |
2620 | del_timer_sync(&adapter->phy_config_timer); | 2653 | del_timer_sync(&adapter->phy_config_timer); |
2621 | adapter->phy_timer_pending = false; | 2654 | adapter->phy_timer_pending = false; |
@@ -2972,6 +3005,7 @@ static int __devinit atl1_probe(struct pci_dev *pdev, | |||
2972 | 3005 | ||
2973 | netdev->netdev_ops = &atl1_netdev_ops; | 3006 | netdev->netdev_ops = &atl1_netdev_ops; |
2974 | netdev->watchdog_timeo = 5 * HZ; | 3007 | netdev->watchdog_timeo = 5 * HZ; |
3008 | netif_napi_add(netdev, &adapter->napi, atl1_rx_clean, 64); | ||
2975 | 3009 | ||
2976 | netdev->ethtool_ops = &atl1_ethtool_ops; | 3010 | netdev->ethtool_ops = &atl1_ethtool_ops; |
2977 | adapter->bd_number = cards_found; | 3011 | adapter->bd_number = cards_found; |
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.h b/drivers/net/ethernet/atheros/atlx/atl1.h index 109d6da8be97..71bb50dfc5fa 100644 --- a/drivers/net/ethernet/atheros/atlx/atl1.h +++ b/drivers/net/ethernet/atheros/atlx/atl1.h | |||
@@ -758,6 +758,7 @@ struct atl1_adapter { | |||
758 | u16 link_speed; | 758 | u16 link_speed; |
759 | u16 link_duplex; | 759 | u16 link_duplex; |
760 | spinlock_t lock; | 760 | spinlock_t lock; |
761 | struct napi_struct napi; | ||
761 | struct work_struct tx_timeout_task; | 762 | struct work_struct tx_timeout_task; |
762 | struct work_struct link_chg_task; | 763 | struct work_struct link_chg_task; |
763 | struct work_struct pcie_dma_to_rst_task; | 764 | struct work_struct pcie_dma_to_rst_task; |