diff options
author | Johannes Berg <johannes.berg@intel.com> | 2011-09-29 10:04:39 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-09-30 15:57:23 -0400 |
commit | 37fbd9080088f5f98ab81a6f2ad456857971a089 (patch) | |
tree | ea0d90d7d05056abd662e69b096d1d0628126115 /net/mac80211/main.c | |
parent | 40b96408831f038b1a6b45e8b22cd050f82a3896 (diff) |
mac80211: allow out-of-band EOSP notification
iwlwifi has a separate EOSP notification from
the device, and to make use of that properly
it needs to be passed to mac80211. To be able
to mix with tx_status_irqsafe and rx_irqsafe
it also needs to be an "_irqsafe" version in
the sense that it goes through the tasklet,
the actual flag clearing would be IRQ-safe
but doing it directly would cause reordering
issues.
This is needed in the case of a P2P GO going
into an absence period without transmitting
any frames that should be driver-released as
in this case there's no other way to inform
mac80211 that the service period ended. Note
that for drivers that don't use the _irqsafe
functions another version of this function
will be required.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r-- | net/mac80211/main.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 336ceb9d2462..17b038aeac9b 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -325,6 +325,8 @@ u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) | |||
325 | static void ieee80211_tasklet_handler(unsigned long data) | 325 | static void ieee80211_tasklet_handler(unsigned long data) |
326 | { | 326 | { |
327 | struct ieee80211_local *local = (struct ieee80211_local *) data; | 327 | struct ieee80211_local *local = (struct ieee80211_local *) data; |
328 | struct sta_info *sta, *tmp; | ||
329 | struct skb_eosp_msg_data *eosp_data; | ||
328 | struct sk_buff *skb; | 330 | struct sk_buff *skb; |
329 | 331 | ||
330 | while ((skb = skb_dequeue(&local->skb_queue)) || | 332 | while ((skb = skb_dequeue(&local->skb_queue)) || |
@@ -340,6 +342,18 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
340 | skb->pkt_type = 0; | 342 | skb->pkt_type = 0; |
341 | ieee80211_tx_status(local_to_hw(local), skb); | 343 | ieee80211_tx_status(local_to_hw(local), skb); |
342 | break; | 344 | break; |
345 | case IEEE80211_EOSP_MSG: | ||
346 | eosp_data = (void *)skb->cb; | ||
347 | for_each_sta_info(local, eosp_data->sta, sta, tmp) { | ||
348 | /* skip wrong virtual interface */ | ||
349 | if (memcmp(eosp_data->iface, | ||
350 | sta->sdata->vif.addr, ETH_ALEN)) | ||
351 | continue; | ||
352 | clear_sta_flag(sta, WLAN_STA_SP); | ||
353 | break; | ||
354 | } | ||
355 | dev_kfree_skb(skb); | ||
356 | break; | ||
343 | default: | 357 | default: |
344 | WARN(1, "mac80211: Packet is of unknown type %d\n", | 358 | WARN(1, "mac80211: Packet is of unknown type %d\n", |
345 | skb->pkt_type); | 359 | skb->pkt_type); |