97 lines
3.3 KiB
Diff
97 lines
3.3 KiB
Diff
|
--- a/include/net/mac80211.h
|
||
|
+++ b/include/net/mac80211.h
|
||
|
@@ -2370,6 +2370,25 @@ static inline int ieee80211_sta_ps_trans
|
||
|
void ieee80211_sta_set_tim(struct ieee80211_sta *sta);
|
||
|
|
||
|
/**
|
||
|
+ * ieee80211_tx_status_sta - transmit status callback
|
||
|
+ *
|
||
|
+ * Call this function for all transmitted frames after they have been
|
||
|
+ * transmitted. It is permissible to not call this function for
|
||
|
+ * multicast frames but this can affect statistics.
|
||
|
+ *
|
||
|
+ * This function may not be called in IRQ context. Calls to this function
|
||
|
+ * for a single hardware must be synchronized against each other. Calls
|
||
|
+ * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe()
|
||
|
+ * may not be mixed for a single hardware.
|
||
|
+ *
|
||
|
+ * @hw: the hardware the frame was transmitted by
|
||
|
+ * @skb: the frame that was transmitted, owned by mac80211 after this call
|
||
|
+ * @sta: station for which the tx status is provided
|
||
|
+ */
|
||
|
+void ieee80211_tx_status_sta(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||
|
+ struct ieee80211_sta *sta);
|
||
|
+
|
||
|
+/**
|
||
|
* ieee80211_tx_status - transmit status callback
|
||
|
*
|
||
|
* Call this function for all transmitted frames after they have been
|
||
|
@@ -2384,8 +2403,11 @@ void ieee80211_sta_set_tim(struct ieee80
|
||
|
* @hw: the hardware the frame was transmitted by
|
||
|
* @skb: the frame that was transmitted, owned by mac80211 after this call
|
||
|
*/
|
||
|
-void ieee80211_tx_status(struct ieee80211_hw *hw,
|
||
|
- struct sk_buff *skb);
|
||
|
+static inline void ieee80211_tx_status(struct ieee80211_hw *hw,
|
||
|
+ struct sk_buff *skb)
|
||
|
+{
|
||
|
+ ieee80211_tx_status_sta(hw, skb, NULL);
|
||
|
+}
|
||
|
|
||
|
/**
|
||
|
* ieee80211_tx_status_ni - transmit status callback (in process context)
|
||
|
--- a/net/mac80211/status.c
|
||
|
+++ b/net/mac80211/status.c
|
||
|
@@ -202,7 +202,8 @@ static void ieee80211_set_bar_pending(st
|
||
|
*/
|
||
|
#define STA_LOST_PKT_THRESHOLD 50
|
||
|
|
||
|
-void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||
|
+void ieee80211_tx_status_sta(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||
|
+ struct ieee80211_sta *pubsta)
|
||
|
{
|
||
|
struct sk_buff *skb2;
|
||
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||
|
@@ -214,7 +215,7 @@ void ieee80211_tx_status(struct ieee8021
|
||
|
struct ieee80211_tx_status_rtap_hdr *rthdr;
|
||
|
struct ieee80211_sub_if_data *sdata;
|
||
|
struct net_device *prev_dev = NULL;
|
||
|
- struct sta_info *sta, *tmp;
|
||
|
+ struct sta_info *sta = NULL, *tmp, *tmp2;
|
||
|
int retry_count = -1, i;
|
||
|
int rates_idx = -1;
|
||
|
bool send_to_cooked;
|
||
|
@@ -244,11 +245,19 @@ void ieee80211_tx_status(struct ieee8021
|
||
|
sband = local->hw.wiphy->bands[info->band];
|
||
|
fc = hdr->frame_control;
|
||
|
|
||
|
- for_each_sta_info(local, hdr->addr1, sta, tmp) {
|
||
|
- /* skip wrong virtual interface */
|
||
|
- if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN))
|
||
|
- continue;
|
||
|
+ if (!pubsta) {
|
||
|
+ for_each_sta_info(local, hdr->addr1, tmp, tmp2) {
|
||
|
+ /* skip wrong virtual interface */
|
||
|
+ if (memcmp(hdr->addr2, tmp->sdata->vif.addr, ETH_ALEN))
|
||
|
+ continue;
|
||
|
+
|
||
|
+ sta = tmp;
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ sta = container_of(pubsta, struct sta_info, sta);
|
||
|
+ }
|
||
|
|
||
|
+ if (sta) {
|
||
|
acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
|
||
|
if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) {
|
||
|
/*
|
||
|
@@ -497,7 +506,7 @@ void ieee80211_tx_status(struct ieee8021
|
||
|
rcu_read_unlock();
|
||
|
dev_kfree_skb(skb);
|
||
|
}
|
||
|
-EXPORT_SYMBOL(ieee80211_tx_status);
|
||
|
+EXPORT_SYMBOL(ieee80211_tx_status_sta);
|
||
|
|
||
|
void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)
|
||
|
{
|