aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorInaky Perez-Gonzalez <inaky@linux.intel.com>2009-09-29 19:28:24 -0400
committerInaky Perez-Gonzalez <inaky@linux.intel.com>2009-10-19 02:56:12 -0400
commit9835fd84990ca253c5b625005717a9be492788c0 (patch)
tree9daa36006886eecf80fe5c715049ef8307aecc0a /drivers
parente1633fd636f3ed0379fcf08c47962205eadddb6b (diff)
wimax/i2400m: fix race condition with tcpdump et al
tcpdump and friends were not being able to decode packets sent via WiMAX; they had a zero ethernet type, even when the stack was properly sending them to the device with the right type. It happens that the driver was overwriting the (fake) ethernet header for creating the hardware header and that was bitting the cloning used by tcpdump (et al) to look into the packets. Use pkskb_expand_head() [method copied from the e1000 driver] to fix. Thanks to Herbert Xu and Andi Kleen for helping to diagnose and pointing to the right fix. Cc: Herbert Xu <gondor.apana.org.au> Cc: Andi Kleen <andi@firstfloor.org> Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wimax/i2400m/netdev.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c
index fefd794087ad..e7d1a51ee3fe 100644
--- a/drivers/net/wimax/i2400m/netdev.c
+++ b/drivers/net/wimax/i2400m/netdev.c
@@ -358,6 +358,20 @@ netdev_tx_t i2400m_hard_start_xmit(struct sk_buff *skb,
358 int result; 358 int result;
359 359
360 d_fnstart(3, dev, "(skb %p net_dev %p)\n", skb, net_dev); 360 d_fnstart(3, dev, "(skb %p net_dev %p)\n", skb, net_dev);
361 if (skb_header_cloned(skb)) {
362 /*
363 * Make tcpdump/wireshark happy -- if they are
364 * running, the skb is cloned and we will overwrite
365 * the mac fields in i2400m_tx_prep_header. Expand
366 * seems to fix this...
367 */
368 result = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
369 if (result) {
370 result = NETDEV_TX_BUSY;
371 goto error_expand;
372 }
373 }
374
361 if (i2400m->state == I2400M_SS_IDLE) 375 if (i2400m->state == I2400M_SS_IDLE)
362 result = i2400m_net_wake_tx(i2400m, net_dev, skb); 376 result = i2400m_net_wake_tx(i2400m, net_dev, skb);
363 else 377 else
@@ -368,10 +382,11 @@ netdev_tx_t i2400m_hard_start_xmit(struct sk_buff *skb,
368 net_dev->stats.tx_packets++; 382 net_dev->stats.tx_packets++;
369 net_dev->stats.tx_bytes += skb->len; 383 net_dev->stats.tx_bytes += skb->len;
370 } 384 }
385 result = NETDEV_TX_OK;
386error_expand:
371 kfree_skb(skb); 387 kfree_skb(skb);
372 388 d_fnend(3, dev, "(skb %p net_dev %p) = %d\n", skb, net_dev, result);
373 d_fnend(3, dev, "(skb %p net_dev %p)\n", skb, net_dev); 389 return result;
374 return NETDEV_TX_OK;
375} 390}
376 391
377 392