1 From: http://xenbits.xensource.com/linux-2.6.18-xen.hg?rev/3a4410c4504e
2 # HG changeset 849 patch
3 # User Keir Fraser <keir.fraser@citrix.com>
4 # Date 1238497253 -3600
5 # Node ID 3a4410c4504ea64f2c1e873df3234938366050ad
6 # Parent ab1d4fbbe4bf93f203e0c4d62c18bd248e4f1d4a
7 Subject: sfc_netfront: Only clear tx_skb when ready for netif_wake_queue
8 (doing otherwise could result in a lost packet) and document use of
9 locks to protect tx_skb
10 References: bnc#489721
11 Patch-mainline: obsolete
13 Signed-off-by: Kieran Mansley <kmansley@solarflare.com>
14 Acked-by: jbeulich@novell.com
16 --- sle11-2009-04-09.orig/drivers/xen/sfc_netfront/accel.h 2009-04-09 14:23:18.000000000 +0200
17 +++ sle11-2009-04-09/drivers/xen/sfc_netfront/accel.h 2009-04-09 14:41:38.000000000 +0200
18 @@ -261,8 +261,10 @@ typedef struct netfront_accel_vnic {
22 - /** A spare slot for a TX packet. This is treated as an extension
23 - * of the DMA queue. */
24 + /** A spare slot for a TX packet. This is treated as an
25 + * extension of the DMA queue. Reads require either
26 + * netfront's tx_lock or the vnic tx_lock; writes require both
28 struct sk_buff *tx_skb;
30 /** Keep track of fragments of SSR packets */
31 --- sle11-2009-04-09.orig/drivers/xen/sfc_netfront/accel_netfront.c 2009-03-30 16:16:28.000000000 +0200
32 +++ sle11-2009-04-09/drivers/xen/sfc_netfront/accel_netfront.c 2009-04-09 14:42:13.000000000 +0200
33 @@ -65,7 +65,7 @@ static int netfront_accel_netdev_start_x
34 BUG_ON(vnic->net_dev != net_dev);
35 DPRINTK("%s stopping queue\n", __FUNCTION__);
37 - /* Netfront's lock protects tx_skb */
38 + /* Need netfront's tx_lock and vnic tx_lock to write tx_skb */
39 spin_lock_irqsave(&np->tx_lock, flags2);
40 BUG_ON(vnic->tx_skb != NULL);
42 @@ -183,7 +183,7 @@ static int netfront_accel_check_ready(st
46 - /* This is protected by netfront's lock */
47 + /* Read of tx_skb is protected by netfront's tx_lock */
48 return vnic->tx_skb == NULL;
51 --- sle11-2009-04-09.orig/drivers/xen/sfc_netfront/accel_vi.c 2009-04-09 14:23:18.000000000 +0200
52 +++ sle11-2009-04-09/drivers/xen/sfc_netfront/accel_vi.c 2009-04-09 14:41:38.000000000 +0200
53 @@ -980,39 +980,35 @@ static void netfront_accel_vi_not_busy(n
55 struct netfront_info *np = ((struct netfront_info *)
56 netdev_priv(vnic->net_dev));
57 - struct sk_buff *skb;
63 - * TODO if we could safely check tx_skb == NULL and return
64 - * early without taking the lock, that would obviously help
66 + * We hold the vnic tx_lock which is sufficient to exclude
70 - /* Take the netfront lock which protects tx_skb. */
71 - spin_lock_irqsave(&np->tx_lock, flags);
72 if (vnic->tx_skb != NULL) {
73 DPRINTK("%s trying to send spare buffer\n", __FUNCTION__);
76 - vnic->tx_skb = NULL;
78 - spin_unlock_irqrestore(&np->tx_lock, flags);
80 - handled = netfront_accel_vi_tx_post(vnic, skb);
81 + handled = netfront_accel_vi_tx_post(vnic, vnic->tx_skb);
83 - spin_lock_irqsave(&np->tx_lock, flags);
85 if (handled != NETFRONT_ACCEL_STATUS_BUSY) {
86 DPRINTK("%s restarting tx\n", __FUNCTION__);
88 + /* Need netfront tx_lock and vnic tx_lock to
90 + spin_lock_irqsave(&np->tx_lock, flags);
92 + vnic->tx_skb = NULL;
94 if (netfront_check_queue_ready(vnic->net_dev)) {
95 netif_wake_queue(vnic->net_dev);
96 NETFRONT_ACCEL_STATS_OP
97 (vnic->stats.queue_wakes++);
100 - vnic->tx_skb = skb;
101 + spin_unlock_irqrestore(&np->tx_lock, flags);
106 @@ -1021,7 +1017,6 @@ static void netfront_accel_vi_not_busy(n
108 BUG_ON(handled == NETFRONT_ACCEL_STATUS_CANT);
110 - spin_unlock_irqrestore(&np->tx_lock, flags);