aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2006-09-01 18:53:49 -0400
committerJeff Garzik <jeff@garzik.org>2006-09-06 11:19:23 -0400
commit513f533e3f161c5a59555677d35e8ae28037bd89 (patch)
tree84d8d7355f8c14f3abd57e8e313ce39ed09e3d05 /drivers
parent29365c900963d4986b74a0dadea46872bf283d76 (diff)
[PATCH] skge: use NAPI for transmit complete
The skge driver has much better performance if transmit done is handled in NAPI softirq. Change from doing transmit locking in driver (LLTX) and use device lock. Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/skge.c82
-rw-r--r--drivers/net/skge.h1
2 files changed, 28 insertions, 55 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 8a321be24835..34a4b87819bd 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -91,7 +91,7 @@ MODULE_DEVICE_TABLE(pci, skge_id_table);
91static int skge_up(struct net_device *dev); 91static int skge_up(struct net_device *dev);
92static int skge_down(struct net_device *dev); 92static int skge_down(struct net_device *dev);
93static void skge_phy_reset(struct skge_port *skge); 93static void skge_phy_reset(struct skge_port *skge);
94static void skge_tx_clean(struct skge_port *skge); 94static void skge_tx_clean(struct net_device *dev);
95static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); 95static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
96static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); 96static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
97static void genesis_get_stats(struct skge_port *skge, u64 *data); 97static void genesis_get_stats(struct skge_port *skge, u64 *data);
@@ -105,6 +105,7 @@ static const int txqaddr[] = { Q_XA1, Q_XA2 };
105static const int rxqaddr[] = { Q_R1, Q_R2 }; 105static const int rxqaddr[] = { Q_R1, Q_R2 };
106static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F }; 106static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F };
107static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F }; 107static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F };
108static const u32 irqmask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F };
108 109
109static int skge_get_regs_len(struct net_device *dev) 110static int skge_get_regs_len(struct net_device *dev)
110{ 111{
@@ -2283,7 +2284,7 @@ static int skge_down(struct net_device *dev)
2283 skge_led(skge, LED_MODE_OFF); 2284 skge_led(skge, LED_MODE_OFF);
2284 2285
2285 netif_poll_disable(dev); 2286 netif_poll_disable(dev);
2286 skge_tx_clean(skge); 2287 skge_tx_clean(dev);
2287 skge_rx_clean(skge); 2288 skge_rx_clean(skge);
2288 2289
2289 kfree(skge->rx_ring.start); 2290 kfree(skge->rx_ring.start);
@@ -2308,25 +2309,12 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
2308 int i; 2309 int i;
2309 u32 control, len; 2310 u32 control, len;
2310 u64 map; 2311 u64 map;
2311 unsigned long flags;
2312 2312
2313 if (skb_padto(skb, ETH_ZLEN)) 2313 if (skb_padto(skb, ETH_ZLEN))
2314 return NETDEV_TX_OK; 2314 return NETDEV_TX_OK;
2315 2315
2316 if (!spin_trylock_irqsave(&skge->tx_lock, flags)) 2316 if (unlikely(skge_avail(&skge->tx_ring) < skb_shinfo(skb)->nr_frags + 1))
2317 /* Collision - tell upper layer to requeue */
2318 return NETDEV_TX_LOCKED;
2319
2320 if (unlikely(skge_avail(&skge->tx_ring) < skb_shinfo(skb)->nr_frags + 1)) {
2321 if (!netif_queue_stopped(dev)) {
2322 netif_stop_queue(dev);
2323
2324 printk(KERN_WARNING PFX "%s: ring full when queue awake!\n",
2325 dev->name);
2326 }
2327 spin_unlock_irqrestore(&skge->tx_lock, flags);
2328 return NETDEV_TX_BUSY; 2317 return NETDEV_TX_BUSY;
2329 }
2330 2318
2331 e = skge->tx_ring.to_use; 2319 e = skge->tx_ring.to_use;
2332 td = e->desc; 2320 td = e->desc;
@@ -2401,8 +2389,6 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
2401 netif_stop_queue(dev); 2389 netif_stop_queue(dev);
2402 } 2390 }
2403 2391
2404 spin_unlock_irqrestore(&skge->tx_lock, flags);
2405
2406 dev->trans_start = jiffies; 2392 dev->trans_start = jiffies;
2407 2393
2408 return NETDEV_TX_OK; 2394 return NETDEV_TX_OK;
@@ -2432,18 +2418,18 @@ static void skge_tx_free(struct skge_port *skge, struct skge_element *e,
2432 printk(KERN_DEBUG PFX "%s: tx done slot %td\n", 2418 printk(KERN_DEBUG PFX "%s: tx done slot %td\n",
2433 skge->netdev->name, e - skge->tx_ring.start); 2419 skge->netdev->name, e - skge->tx_ring.start);
2434 2420
2435 dev_kfree_skb_any(e->skb); 2421 dev_kfree_skb(e->skb);
2436 } 2422 }
2437 e->skb = NULL; 2423 e->skb = NULL;
2438} 2424}
2439 2425
2440/* Free all buffers in transmit ring */ 2426/* Free all buffers in transmit ring */
2441static void skge_tx_clean(struct skge_port *skge) 2427static void skge_tx_clean(struct net_device *dev)
2442{ 2428{
2429 struct skge_port *skge = netdev_priv(dev);
2443 struct skge_element *e; 2430 struct skge_element *e;
2444 unsigned long flags;
2445 2431
2446 spin_lock_irqsave(&skge->tx_lock, flags); 2432 netif_tx_lock_bh(dev);
2447 for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) { 2433 for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) {
2448 struct skge_tx_desc *td = e->desc; 2434 struct skge_tx_desc *td = e->desc;
2449 skge_tx_free(skge, e, td->control); 2435 skge_tx_free(skge, e, td->control);
@@ -2451,8 +2437,8 @@ static void skge_tx_clean(struct skge_port *skge)
2451 } 2437 }
2452 2438
2453 skge->tx_ring.to_clean = e; 2439 skge->tx_ring.to_clean = e;
2454 netif_wake_queue(skge->netdev); 2440 netif_wake_queue(dev);
2455 spin_unlock_irqrestore(&skge->tx_lock, flags); 2441 netif_tx_unlock_bh(dev);
2456} 2442}
2457 2443
2458static void skge_tx_timeout(struct net_device *dev) 2444static void skge_tx_timeout(struct net_device *dev)
@@ -2463,7 +2449,7 @@ static void skge_tx_timeout(struct net_device *dev)
2463 printk(KERN_DEBUG PFX "%s: tx timeout\n", dev->name); 2449 printk(KERN_DEBUG PFX "%s: tx timeout\n", dev->name);
2464 2450
2465 skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_STOP); 2451 skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_STOP);
2466 skge_tx_clean(skge); 2452 skge_tx_clean(dev);
2467} 2453}
2468 2454
2469static int skge_change_mtu(struct net_device *dev, int new_mtu) 2455static int skge_change_mtu(struct net_device *dev, int new_mtu)
@@ -2679,15 +2665,15 @@ resubmit:
2679} 2665}
2680 2666
2681/* Free all buffers in Tx ring which are no longer owned by device */ 2667/* Free all buffers in Tx ring which are no longer owned by device */
2682static void skge_txirq(struct net_device *dev) 2668static void skge_tx_done(struct net_device *dev)
2683{ 2669{
2684 struct skge_port *skge = netdev_priv(dev); 2670 struct skge_port *skge = netdev_priv(dev);
2685 struct skge_ring *ring = &skge->tx_ring; 2671 struct skge_ring *ring = &skge->tx_ring;
2686 struct skge_element *e; 2672 struct skge_element *e;
2687 2673
2688 rmb(); 2674 skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F);
2689 2675
2690 spin_lock(&skge->tx_lock); 2676 netif_tx_lock(dev);
2691 for (e = ring->to_clean; e != ring->to_use; e = e->next) { 2677 for (e = ring->to_clean; e != ring->to_use; e = e->next) {
2692 struct skge_tx_desc *td = e->desc; 2678 struct skge_tx_desc *td = e->desc;
2693 2679
@@ -2698,11 +2684,10 @@ static void skge_txirq(struct net_device *dev)
2698 } 2684 }
2699 skge->tx_ring.to_clean = e; 2685 skge->tx_ring.to_clean = e;
2700 2686
2701 if (netif_queue_stopped(skge->netdev) 2687 if (skge_avail(&skge->tx_ring) > TX_LOW_WATER)
2702 && skge_avail(&skge->tx_ring) > TX_LOW_WATER) 2688 netif_wake_queue(dev);
2703 netif_wake_queue(skge->netdev);
2704 2689
2705 spin_unlock(&skge->tx_lock); 2690 netif_tx_unlock(dev);
2706} 2691}
2707 2692
2708static int skge_poll(struct net_device *dev, int *budget) 2693static int skge_poll(struct net_device *dev, int *budget)
@@ -2714,6 +2699,10 @@ static int skge_poll(struct net_device *dev, int *budget)
2714 int to_do = min(dev->quota, *budget); 2699 int to_do = min(dev->quota, *budget);
2715 int work_done = 0; 2700 int work_done = 0;
2716 2701
2702 skge_tx_done(dev);
2703
2704 skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F);
2705
2717 for (e = ring->to_clean; prefetch(e->next), work_done < to_do; e = e->next) { 2706 for (e = ring->to_clean; prefetch(e->next), work_done < to_do; e = e->next) {
2718 struct skge_rx_desc *rd = e->desc; 2707 struct skge_rx_desc *rd = e->desc;
2719 struct sk_buff *skb; 2708 struct sk_buff *skb;
@@ -2744,10 +2733,9 @@ static int skge_poll(struct net_device *dev, int *budget)
2744 if (work_done >= to_do) 2733 if (work_done >= to_do)
2745 return 1; /* not done */ 2734 return 1; /* not done */
2746 2735
2747 netif_rx_complete(dev);
2748
2749 spin_lock_irq(&hw->hw_lock); 2736 spin_lock_irq(&hw->hw_lock);
2750 hw->intr_mask |= rxirqmask[skge->port]; 2737 __netif_rx_complete(dev);
2738 hw->intr_mask |= irqmask[skge->port];
2751 skge_write32(hw, B0_IMSK, hw->intr_mask); 2739 skge_write32(hw, B0_IMSK, hw->intr_mask);
2752 skge_read32(hw, B0_IMSK); 2740 skge_read32(hw, B0_IMSK);
2753 spin_unlock_irq(&hw->hw_lock); 2741 spin_unlock_irq(&hw->hw_lock);
@@ -2906,14 +2894,8 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
2906 schedule_work(&hw->phy_work); 2894 schedule_work(&hw->phy_work);
2907 } 2895 }
2908 2896
2909 if (status & IS_XA1_F) { 2897 if (status & (IS_XA1_F|IS_R1_F)) {
2910 skge_write8(hw, Q_ADDR(Q_XA1, Q_CSR), CSR_IRQ_CL_F); 2898 hw->intr_mask &= ~(IS_XA1_F|IS_R1_F);
2911 skge_txirq(hw->dev[0]);
2912 }
2913
2914 if (status & IS_R1_F) {
2915 skge_write8(hw, Q_ADDR(Q_R1, Q_CSR), CSR_IRQ_CL_F);
2916 hw->intr_mask &= ~IS_R1_F;
2917 netif_rx_schedule(hw->dev[0]); 2899 netif_rx_schedule(hw->dev[0]);
2918 } 2900 }
2919 2901
@@ -2932,14 +2914,8 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
2932 skge_mac_intr(hw, 0); 2914 skge_mac_intr(hw, 0);
2933 2915
2934 if (hw->dev[1]) { 2916 if (hw->dev[1]) {
2935 if (status & IS_XA2_F) { 2917 if (status & (IS_XA2_F|IS_R2_F)) {
2936 skge_write8(hw, Q_ADDR(Q_XA2, Q_CSR), CSR_IRQ_CL_F); 2918 hw->intr_mask &= ~(IS_XA2_F|IS_R2_F);
2937 skge_txirq(hw->dev[1]);
2938 }
2939
2940 if (status & IS_R2_F) {
2941 skge_write8(hw, Q_ADDR(Q_R2, Q_CSR), CSR_IRQ_CL_F);
2942 hw->intr_mask &= ~IS_R2_F;
2943 netif_rx_schedule(hw->dev[1]); 2919 netif_rx_schedule(hw->dev[1]);
2944 } 2920 }
2945 2921
@@ -3228,7 +3204,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
3228 dev->poll_controller = skge_netpoll; 3204 dev->poll_controller = skge_netpoll;
3229#endif 3205#endif
3230 dev->irq = hw->pdev->irq; 3206 dev->irq = hw->pdev->irq;
3231 dev->features = NETIF_F_LLTX; 3207
3232 if (highmem) 3208 if (highmem)
3233 dev->features |= NETIF_F_HIGHDMA; 3209 dev->features |= NETIF_F_HIGHDMA;
3234 3210
@@ -3250,8 +3226,6 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
3250 3226
3251 skge->port = port; 3227 skge->port = port;
3252 3228
3253 spin_lock_init(&skge->tx_lock);
3254
3255 if (hw->chip_id != CHIP_ID_GENESIS) { 3229 if (hw->chip_id != CHIP_ID_GENESIS) {
3256 dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; 3230 dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
3257 skge->rx_csum = 1; 3231 skge->rx_csum = 1;
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index 593387b3c0dd..79e09271bcf9 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -2417,7 +2417,6 @@ struct skge_port {
2417 struct net_device *netdev; 2417 struct net_device *netdev;
2418 int port; 2418 int port;
2419 2419
2420 spinlock_t tx_lock;
2421 struct skge_ring tx_ring; 2420 struct skge_ring tx_ring;
2422 struct skge_ring rx_ring; 2421 struct skge_ring rx_ring;
2423 2422