aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>2014-05-09 07:11:49 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-05-15 09:01:00 -0400
commit6ec8c332a0f93959e615158cc212b3abfd52abe7 (patch)
tree6141a73915924c13192fd5075bd4d0233219246f /net/mac80211
parent0d06d9ba93ad4272dc3cd2865deb18c9e9885fd5 (diff)
mac80211: Provide ieee80211_beacon_get_template API
Add a new API ieee80211_beacon_get_template, which doesn't affect DTIM counter and should be used if the device generates beacon frames, and new beacon template is needed. In addition set the offsets to TIM IE for MESH interface. Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com> Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/tx.c80
1 files changed, 58 insertions, 22 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 0d1a42d4b6de..509456e5722d 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2328,7 +2328,8 @@ void ieee80211_tx_pending(unsigned long data)
2328/* functions for drivers to get certain frames */ 2328/* functions for drivers to get certain frames */
2329 2329
2330static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, 2330static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
2331 struct ps_data *ps, struct sk_buff *skb) 2331 struct ps_data *ps, struct sk_buff *skb,
2332 bool is_template)
2332{ 2333{
2333 u8 *pos, *tim; 2334 u8 *pos, *tim;
2334 int aid0 = 0; 2335 int aid0 = 0;
@@ -2341,11 +2342,12 @@ static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
2341 * checking byte-for-byte */ 2342 * checking byte-for-byte */
2342 have_bits = !bitmap_empty((unsigned long *)ps->tim, 2343 have_bits = !bitmap_empty((unsigned long *)ps->tim,
2343 IEEE80211_MAX_AID+1); 2344 IEEE80211_MAX_AID+1);
2344 2345 if (!is_template) {
2345 if (ps->dtim_count == 0) 2346 if (ps->dtim_count == 0)
2346 ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1; 2347 ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1;
2347 else 2348 else
2348 ps->dtim_count--; 2349 ps->dtim_count--;
2350 }
2349 2351
2350 tim = pos = (u8 *) skb_put(skb, 6); 2352 tim = pos = (u8 *) skb_put(skb, 6);
2351 *pos++ = WLAN_EID_TIM; 2353 *pos++ = WLAN_EID_TIM;
@@ -2391,7 +2393,8 @@ static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
2391} 2393}
2392 2394
2393static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, 2395static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
2394 struct ps_data *ps, struct sk_buff *skb) 2396 struct ps_data *ps, struct sk_buff *skb,
2397 bool is_template)
2395{ 2398{
2396 struct ieee80211_local *local = sdata->local; 2399 struct ieee80211_local *local = sdata->local;
2397 2400
@@ -2403,10 +2406,10 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
2403 * of the tim bitmap in mac80211 and the driver. 2406 * of the tim bitmap in mac80211 and the driver.
2404 */ 2407 */
2405 if (local->tim_in_locked_section) { 2408 if (local->tim_in_locked_section) {
2406 __ieee80211_beacon_add_tim(sdata, ps, skb); 2409 __ieee80211_beacon_add_tim(sdata, ps, skb, is_template);
2407 } else { 2410 } else {
2408 spin_lock_bh(&local->tim_lock); 2411 spin_lock_bh(&local->tim_lock);
2409 __ieee80211_beacon_add_tim(sdata, ps, skb); 2412 __ieee80211_beacon_add_tim(sdata, ps, skb, is_template);
2410 spin_unlock_bh(&local->tim_lock); 2413 spin_unlock_bh(&local->tim_lock);
2411 } 2414 }
2412 2415
@@ -2536,9 +2539,11 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
2536} 2539}
2537EXPORT_SYMBOL(ieee80211_csa_is_complete); 2540EXPORT_SYMBOL(ieee80211_csa_is_complete);
2538 2541
2539struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, 2542static struct sk_buff *
2540 struct ieee80211_vif *vif, 2543__ieee80211_beacon_get(struct ieee80211_hw *hw,
2541 u16 *tim_offset, u16 *tim_length) 2544 struct ieee80211_vif *vif,
2545 struct ieee80211_mutable_offsets *offs,
2546 bool is_template)
2542{ 2547{
2543 struct ieee80211_local *local = hw_to_local(hw); 2548 struct ieee80211_local *local = hw_to_local(hw);
2544 struct sk_buff *skb = NULL; 2549 struct sk_buff *skb = NULL;
@@ -2556,10 +2561,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
2556 if (!ieee80211_sdata_running(sdata) || !chanctx_conf) 2561 if (!ieee80211_sdata_running(sdata) || !chanctx_conf)
2557 goto out; 2562 goto out;
2558 2563
2559 if (tim_offset) 2564 if (offs)
2560 *tim_offset = 0; 2565 memset(offs, 0, sizeof(*offs));
2561 if (tim_length)
2562 *tim_length = 0;
2563 2566
2564 if (sdata->vif.type == NL80211_IFTYPE_AP) { 2567 if (sdata->vif.type == NL80211_IFTYPE_AP) {
2565 struct ieee80211_if_ap *ap = &sdata->u.ap; 2568 struct ieee80211_if_ap *ap = &sdata->u.ap;
@@ -2584,12 +2587,13 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
2584 memcpy(skb_put(skb, beacon->head_len), beacon->head, 2587 memcpy(skb_put(skb, beacon->head_len), beacon->head,
2585 beacon->head_len); 2588 beacon->head_len);
2586 2589
2587 ieee80211_beacon_add_tim(sdata, &ap->ps, skb); 2590 ieee80211_beacon_add_tim(sdata, &ap->ps, skb,
2591 is_template);
2588 2592
2589 if (tim_offset) 2593 if (offs) {
2590 *tim_offset = beacon->head_len; 2594 offs->tim_offset = beacon->head_len;
2591 if (tim_length) 2595 offs->tim_length = skb->len - beacon->head_len;
2592 *tim_length = skb->len - beacon->head_len; 2596 }
2593 2597
2594 if (beacon->tail) 2598 if (beacon->tail)
2595 memcpy(skb_put(skb, beacon->tail_len), 2599 memcpy(skb_put(skb, beacon->tail_len),
@@ -2641,7 +2645,13 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
2641 goto out; 2645 goto out;
2642 skb_reserve(skb, local->tx_headroom); 2646 skb_reserve(skb, local->tx_headroom);
2643 memcpy(skb_put(skb, bcn->head_len), bcn->head, bcn->head_len); 2647 memcpy(skb_put(skb, bcn->head_len), bcn->head, bcn->head_len);
2644 ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb); 2648 ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb, is_template);
2649
2650 if (offs) {
2651 offs->tim_offset = bcn->head_len;
2652 offs->tim_length = skb->len - bcn->head_len;
2653 }
2654
2645 memcpy(skb_put(skb, bcn->tail_len), bcn->tail, bcn->tail_len); 2655 memcpy(skb_put(skb, bcn->tail_len), bcn->tail, bcn->tail_len);
2646 } else { 2656 } else {
2647 WARN_ON(1); 2657 WARN_ON(1);
@@ -2678,6 +2688,32 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
2678 out: 2688 out:
2679 rcu_read_unlock(); 2689 rcu_read_unlock();
2680 return skb; 2690 return skb;
2691
2692}
2693
2694struct sk_buff *
2695ieee80211_beacon_get_template(struct ieee80211_hw *hw,
2696 struct ieee80211_vif *vif,
2697 struct ieee80211_mutable_offsets *offs)
2698{
2699 return __ieee80211_beacon_get(hw, vif, offs, true);
2700}
2701EXPORT_SYMBOL(ieee80211_beacon_get_template);
2702
2703struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
2704 struct ieee80211_vif *vif,
2705 u16 *tim_offset, u16 *tim_length)
2706{
2707 struct ieee80211_mutable_offsets offs = {};
2708 struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false);
2709
2710 if (tim_offset)
2711 *tim_offset = offs.tim_offset;
2712
2713 if (tim_length)
2714 *tim_length = offs.tim_length;
2715
2716 return bcn;
2681} 2717}
2682EXPORT_SYMBOL(ieee80211_beacon_get_tim); 2718EXPORT_SYMBOL(ieee80211_beacon_get_tim);
2683 2719