diff options
author | Nicolas Pitre <nicolas.pitre@linaro.org> | 2011-01-09 23:24:16 -0500 |
---|---|---|
committer | Nicolas Pitre <nicolas.pitre@linaro.org> | 2011-01-09 23:24:16 -0500 |
commit | a12fc999485eb5d9ecad74554f0baac9688d28e2 (patch) | |
tree | c2ef18a92cb72512ee340ff02298403c6368043b /net/mac80211 | |
parent | b1d76b202e451fcb8909b7686a6bc54127c2411a (diff) | |
parent | d77cf23f1befd3922d81b91cb01fd3da619e0206 (diff) |
Merge commit 'v2.6.36.3' into linaro-2.6.36
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/rx.c | 5 | ||||
-rw-r--r-- | net/mac80211/tx.c | 21 |
2 files changed, 22 insertions, 4 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 28624282c5f..a09196afafa 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1712,9 +1712,11 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) fwd_skb = skb_copy(skb, GFP_ATOMIC); - if (!fwd_skb && net_ratelimit()) + if (!fwd_skb && net_ratelimit()) { printk(KERN_DEBUG "%s: failed to clone mesh frame\n", sdata->name); + goto out; + } fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); @@ -1752,6 +1754,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) } } + out: if (is_multicast_ether_addr(hdr->addr1) || sdata->dev->flags & IFF_PROMISC) return RX_CONTINUE; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c54db966926..ab6355dd4ac 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1705,15 +1705,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, int nh_pos, h_pos; struct sta_info *sta = NULL; u32 sta_flags = 0; + struct sk_buff *tmp_skb; if (unlikely(skb->len < ETH_HLEN)) { ret = NETDEV_TX_OK; goto fail; } - nh_pos = skb_network_header(skb) - skb->data; - h_pos = skb_transport_header(skb) - skb->data; - /* convert Ethernet header to proper 802.11 header (based on * operation mode) */ ethertype = (skb->data[12] << 8) | skb->data[13]; @@ -1885,6 +1883,20 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, goto fail; } + /* + * If the skb is shared we need to obtain our own copy. + */ + if (skb_shared(skb)) { + tmp_skb = skb; + skb = skb_copy(skb, GFP_ATOMIC); + kfree_skb(tmp_skb); + + if (!skb) { + ret = NETDEV_TX_OK; + goto fail; + } + } + hdr.frame_control = fc; hdr.duration_id = 0; hdr.seq_ctrl = 0; @@ -1903,6 +1915,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, encaps_len = 0; } + nh_pos = skb_network_header(skb) - skb->data; + h_pos = skb_transport_header(skb) - skb->data; + skb_pull(skb, skip_header_bytes); nh_pos -= skip_header_bytes; h_pos -= skip_header_bytes; |