diff options
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r-- | net/mac80211/tx.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c54db966926b..9d5af5dd0d98 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1694,7 +1694,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1694 | { | 1694 | { |
1695 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1695 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1696 | struct ieee80211_local *local = sdata->local; | 1696 | struct ieee80211_local *local = sdata->local; |
1697 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1697 | struct ieee80211_tx_info *info; |
1698 | int ret = NETDEV_TX_BUSY, head_need; | 1698 | int ret = NETDEV_TX_BUSY, head_need; |
1699 | u16 ethertype, hdrlen, meshhdrlen = 0; | 1699 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1700 | __le16 fc; | 1700 | __le16 fc; |
@@ -1705,15 +1705,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1705 | int nh_pos, h_pos; | 1705 | int nh_pos, h_pos; |
1706 | struct sta_info *sta = NULL; | 1706 | struct sta_info *sta = NULL; |
1707 | u32 sta_flags = 0; | 1707 | u32 sta_flags = 0; |
1708 | struct sk_buff *tmp_skb; | ||
1708 | 1709 | ||
1709 | if (unlikely(skb->len < ETH_HLEN)) { | 1710 | if (unlikely(skb->len < ETH_HLEN)) { |
1710 | ret = NETDEV_TX_OK; | 1711 | ret = NETDEV_TX_OK; |
1711 | goto fail; | 1712 | goto fail; |
1712 | } | 1713 | } |
1713 | 1714 | ||
1714 | nh_pos = skb_network_header(skb) - skb->data; | ||
1715 | h_pos = skb_transport_header(skb) - skb->data; | ||
1716 | |||
1717 | /* convert Ethernet header to proper 802.11 header (based on | 1715 | /* convert Ethernet header to proper 802.11 header (based on |
1718 | * operation mode) */ | 1716 | * operation mode) */ |
1719 | ethertype = (skb->data[12] << 8) | skb->data[13]; | 1717 | ethertype = (skb->data[12] << 8) | skb->data[13]; |
@@ -1885,6 +1883,20 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1885 | goto fail; | 1883 | goto fail; |
1886 | } | 1884 | } |
1887 | 1885 | ||
1886 | /* | ||
1887 | * If the skb is shared we need to obtain our own copy. | ||
1888 | */ | ||
1889 | if (skb_shared(skb)) { | ||
1890 | tmp_skb = skb; | ||
1891 | skb = skb_copy(skb, GFP_ATOMIC); | ||
1892 | kfree_skb(tmp_skb); | ||
1893 | |||
1894 | if (!skb) { | ||
1895 | ret = NETDEV_TX_OK; | ||
1896 | goto fail; | ||
1897 | } | ||
1898 | } | ||
1899 | |||
1888 | hdr.frame_control = fc; | 1900 | hdr.frame_control = fc; |
1889 | hdr.duration_id = 0; | 1901 | hdr.duration_id = 0; |
1890 | hdr.seq_ctrl = 0; | 1902 | hdr.seq_ctrl = 0; |
@@ -1903,6 +1915,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1903 | encaps_len = 0; | 1915 | encaps_len = 0; |
1904 | } | 1916 | } |
1905 | 1917 | ||
1918 | nh_pos = skb_network_header(skb) - skb->data; | ||
1919 | h_pos = skb_transport_header(skb) - skb->data; | ||
1920 | |||
1906 | skb_pull(skb, skip_header_bytes); | 1921 | skb_pull(skb, skip_header_bytes); |
1907 | nh_pos -= skip_header_bytes; | 1922 | nh_pos -= skip_header_bytes; |
1908 | h_pos -= skip_header_bytes; | 1923 | h_pos -= skip_header_bytes; |
@@ -1969,6 +1984,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1969 | skb_set_network_header(skb, nh_pos); | 1984 | skb_set_network_header(skb, nh_pos); |
1970 | skb_set_transport_header(skb, h_pos); | 1985 | skb_set_transport_header(skb, h_pos); |
1971 | 1986 | ||
1987 | info = IEEE80211_SKB_CB(skb); | ||
1972 | memset(info, 0, sizeof(*info)); | 1988 | memset(info, 0, sizeof(*info)); |
1973 | 1989 | ||
1974 | dev->trans_start = jiffies; | 1990 | dev->trans_start = jiffies; |
@@ -2160,6 +2176,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2160 | 2176 | ||
2161 | sdata = vif_to_sdata(vif); | 2177 | sdata = vif_to_sdata(vif); |
2162 | 2178 | ||
2179 | if (!ieee80211_sdata_running(sdata)) | ||
2180 | goto out; | ||
2181 | |||
2163 | if (tim_offset) | 2182 | if (tim_offset) |
2164 | *tim_offset = 0; | 2183 | *tim_offset = 0; |
2165 | if (tim_length) | 2184 | if (tim_length) |