mac80211: add ieee80211_tx_prepare_skb() helper function
authorFelix Fietkau <nbd@openwrt.org>
Mon, 14 Oct 2013 16:01:00 +0000 (18:01 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 28 Oct 2013 14:05:27 +0000 (15:05 +0100)
This can be used by a driver to prepare skbs for transmission, which were
obtained via functions such as ieee80211_probereq_get or
ieee80211_nullfunc_get.

This is useful for drivers that want to send those frames directly, but
need rate control information to be prepared first.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/mac80211.h
net/mac80211/tx.c

index ecba8a1..7ceed99 100644 (file)
@@ -4571,4 +4571,18 @@ void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif,
                                    struct cfg80211_wowlan_wakeup *wakeup,
                                    gfp_t gfp);
 
+/**
+ * ieee80211_tx_prepare_skb - prepare an 802.11 skb for transmission
+ * @hw: pointer as obtained from ieee80211_alloc_hw()
+ * @vif: virtual interface
+ * @skb: frame to be sent from within the driver
+ * @band: the band to transmit on
+ * @sta: optional pointer to get the station to send the frame to
+ *
+ * Note: must be called under RCU lock
+ */
+bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
+                             struct ieee80211_vif *vif, struct sk_buff *skb,
+                             int band, struct ieee80211_sta **sta);
+
 #endif /* MAC80211_H */
index 4fcbf63..acd9b61 100644 (file)
@@ -1366,6 +1366,35 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
        return 0;
 }
 
+bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
+                             struct ieee80211_vif *vif, struct sk_buff *skb,
+                             int band, struct ieee80211_sta **sta)
+{
+       struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_tx_data tx;
+
+       if (ieee80211_tx_prepare(sdata, &tx, skb) == TX_DROP)
+               return false;
+
+       info->band = band;
+       info->control.vif = vif;
+       info->hw_queue = vif->hw_queue[skb_get_queue_mapping(skb)];
+
+       if (invoke_tx_handlers(&tx))
+               return false;
+
+       if (sta) {
+               if (tx.sta)
+                       *sta = &tx.sta->sta;
+               else
+                       *sta = NULL;
+       }
+
+       return true;
+}
+EXPORT_SYMBOL(ieee80211_tx_prepare_skb);
+
 /*
  * Returns false if the frame couldn't be transmitted but was queued instead.
  */