mac80211: don't resize skbs needlessly
authorIdo Yariv <ido@wizery.com>
Tue, 29 Jul 2014 12:39:14 +0000 (15:39 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 26 Aug 2014 09:16:00 +0000 (11:16 +0200)
Header-less cloned skbs with sufficient headroom need not be cloned
unless the tailroom is going to be modified.

Fix ieee80211_skb_resize so it would only resize cloned skbs if either
the header isn't released or the tailroom is going to be modified.

Some drivers might have assumed that skbs are never cloned, so add a HW
flag that explicitly permits cloned TX skbs. Drivers which do not modify
TX skbs should set this flag to avoid copying skbs.

Signed-off-by: Ido Yariv <idox.yariv@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/mac80211.h
net/mac80211/tx.c

index 1fbed0a6d556b1aa688e71f15b5a4ca9ae9ce1fe..c9b2bec8db47bc5fa661772f6891fe7e4a21f960 100644 (file)
@@ -1609,6 +1609,9 @@ struct ieee80211_tx_control {
  *     is not enabled the default action is to disconnect when getting the
  *     CSA frame.
  *
+ * @IEEE80211_HW_SUPPORTS_CLONED_SKBS: The driver will never modify the payload
+ *     or tailroom of TX skbs without copying them first.
+ *
  * @IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS: The HW supports scanning on all bands
  *     in one command, mac80211 doesn't have to run separate scans per band.
  */
@@ -1642,7 +1645,7 @@ enum ieee80211_hw_flags {
        IEEE80211_HW_TIMING_BEACON_ONLY                 = 1<<26,
        IEEE80211_HW_SUPPORTS_HT_CCK_RATES              = 1<<27,
        IEEE80211_HW_CHANCTX_STA_CSA                    = 1<<28,
-       /* bit 29 unused */
+       IEEE80211_HW_SUPPORTS_CLONED_SKBS               = 1<<29,
        IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS           = 1<<30,
 };
 
index 2051cc60f8ce0a9bddd7fedc94d69a4b271e3495..925c39f4099eadfa4744263d1485fe0611a16e69 100644 (file)
@@ -1478,7 +1478,10 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
                tail_need = max_t(int, tail_need, 0);
        }
 
-       if (skb_cloned(skb))
+       if (skb_cloned(skb) &&
+           (!(local->hw.flags & IEEE80211_HW_SUPPORTS_CLONED_SKBS) ||
+            !skb_clone_writable(skb, ETH_HLEN) ||
+            sdata->crypto_tx_tailroom_needed_cnt))
                I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
        else if (head_need || tail_need)
                I802_DEBUG_INC(local->tx_expand_skb_head);