mac80211: fix TX status cookie in HW offload case
Johannes Berg
maintainerPATCH 1/1 mac80211: fix TX status cookie in HW offload case
From: Johannes Berg <[email protected]>
When the off-channel TX is done with remain-on-channel offloaded to hardware, the reported cookie is wrong as in that case we shouldn't use the SKB as the cookie but need to instead use the corresponding r-o-c cookie (XOR'ed with 2 to prevent API mismatches).
Fix this by keeping track of the hw_roc_skb pointer just for the status processing and use the correct cookie to report in this case. We can't use the hw_roc_skb pointer itself because it is NULL'ed when the frame is transmitted to prevent it being used twice.
This fixes a bug where the P2P state machine in the supplicant gets stuck because it never gets a correct result for its transmitted frame.
--- net/mac80211/cfg.c | 2 ++ net/mac80211/ieee80211_i.h | 2 +- net/mac80211/status.c | 7 ++++++- 3 files changed, 9 insertions(+), 2 deletions(-)
net/mac80211/status.c +6 -1
@@ -323,6 +323,7 @@ void ieee80211_tx_status(struct ieee8021if (info->flags &IEEE80211_TX_INTFL_NL80211_FRAME_TX ) {struct ieee80211_work *wk; +u64 cookie = (unsigned long )skb;rcu_read_lock ();list_for_each_entry_rcu (wk, &local->work_list, list) {
@@ -334,8 +335,12 @@ void ieee80211_tx_status(struct ieee8021break ; }rcu_read_unlock (); +if (local->hw_roc_skb_for_status == skb) { + cookie = local->hw_roc_cookie ^2 ; + local->hw_roc_skb_for_status =NULL ; + }cfg80211_mgmt_tx_status ( - skb->dev, (unsigned long ) skb, skb->data, skb->len, + skb->dev, cookie, skb->data, skb->len, !!(info->flags &IEEE80211_TX_STAT_ACK ),GFP_ATOMIC ); }
net/mac80211/cfg.c +2 -0
@@ -1852,6 +1852,7 @@ static int ieee80211_mgmt_tx(struct wiph *cookie ^=2 ;IEEE80211_SKB_CB (skb)->flags |=IEEE80211_TX_CTL_TX_OFFCHAN ; local->hw_roc_skb = skb; + local->hw_roc_skb_for_status = skb;mutex_unlock (&local->mtx);return 0 ;
@@ -1917,6 +1918,7 @@ static int ieee80211_mgmt_tx_cancel_waitif (ret ==0 ) {kfree_skb (local->hw_roc_skb); local->hw_roc_skb =NULL ; + local->hw_roc_skb_for_status =NULL ; }mutex_unlock (&local->mtx);
net/mac80211/ieee80211_i.h +1 -1
@@ -953,7 +953,7 @@ struct ieee80211_local {struct ieee80211_channel *hw_roc_channel;struct net_device *hw_roc_dev; -struct sk_buff *hw_roc_skb; +struct sk_buff *hw_roc_skb, *hw_roc_skb_for_status;struct work_struct hw_roc_start, hw_roc_done;enum nl80211_channel_type hw_roc_channel_type;unsigned int hw_roc_duration;