提交 eddcbb94 编写于 作者: J Johannes Berg 提交者: John W. Linville

mac80211: introduce ieee80211_beacon_get_tim()

Compared to ieee80211_beacon_get(), the new function
ieee80211_beacon_get_tim() returns information on the
location and length of the TIM IE, which some drivers
need in order to generate the TIM on the device. The
old function, ieee80211_beacon_get(), becomes a small
static inline wrapper around the new one to not break
all drivers.
Signed-off-by: NJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: NJohn W. Linville <linville@tuxdriver.com>
上级 75026664
...@@ -1743,19 +1743,45 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, ...@@ -1743,19 +1743,45 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
struct sk_buff *skb); struct sk_buff *skb);
/** /**
* ieee80211_beacon_get - beacon generation function * ieee80211_beacon_get_tim - beacon generation function
* @hw: pointer obtained from ieee80211_alloc_hw(). * @hw: pointer obtained from ieee80211_alloc_hw().
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
* @tim_offset: pointer to variable that will receive the TIM IE offset.
* Set to 0 if invalid (in non-AP modes).
* @tim_length: pointer to variable that will receive the TIM IE length,
* (including the ID and length bytes!).
* Set to 0 if invalid (in non-AP modes).
*
* If the driver implements beaconing modes, it must use this function to
* obtain the beacon frame/template.
* *
* If the beacon frames are generated by the host system (i.e., not in * If the beacon frames are generated by the host system (i.e., not in
* hardware/firmware), the low-level driver uses this function to receive * hardware/firmware), the driver uses this function to get each beacon
* the next beacon frame from the 802.11 code. The low-level is responsible * frame from mac80211 -- it is responsible for calling this function
* for calling this function before beacon data is needed (e.g., based on * before the beacon is needed (e.g. based on hardware interrupt).
* hardware interrupt). Returned skb is used only once and low-level driver *
* is responsible for freeing it. * If the beacon frames are generated by the device, then the driver
* must use the returned beacon as the template and change the TIM IE
* according to the current DTIM parameters/TIM bitmap.
*
* The driver is responsible for freeing the returned skb.
*/
struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u16 *tim_offset, u16 *tim_length);
/**
* ieee80211_beacon_get - beacon generation function
* @hw: pointer obtained from ieee80211_alloc_hw().
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
*
* See ieee80211_beacon_get_tim().
*/ */
struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
struct ieee80211_vif *vif); struct ieee80211_vif *vif)
{
return ieee80211_beacon_get_tim(hw, vif, NULL, NULL);
}
/** /**
* ieee80211_rts_get - RTS frame generation function * ieee80211_rts_get - RTS frame generation function
......
...@@ -2012,8 +2012,9 @@ static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss, ...@@ -2012,8 +2012,9 @@ static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss,
} }
} }
struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
struct ieee80211_vif *vif) struct ieee80211_vif *vif,
u16 *tim_offset, u16 *tim_length)
{ {
struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_local *local = hw_to_local(hw);
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
...@@ -2030,6 +2031,11 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, ...@@ -2030,6 +2031,11 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
sdata = vif_to_sdata(vif); sdata = vif_to_sdata(vif);
if (tim_offset)
*tim_offset = 0;
if (tim_length)
*tim_length = 0;
if (sdata->vif.type == NL80211_IFTYPE_AP) { if (sdata->vif.type == NL80211_IFTYPE_AP) {
ap = &sdata->u.ap; ap = &sdata->u.ap;
beacon = rcu_dereference(ap->beacon); beacon = rcu_dereference(ap->beacon);
...@@ -2065,6 +2071,11 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, ...@@ -2065,6 +2071,11 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
spin_unlock_irqrestore(&local->sta_lock, flags); spin_unlock_irqrestore(&local->sta_lock, flags);
} }
if (tim_offset)
*tim_offset = beacon->head_len;
if (tim_length)
*tim_length = skb->len - beacon->head_len;
if (beacon->tail) if (beacon->tail)
memcpy(skb_put(skb, beacon->tail_len), memcpy(skb_put(skb, beacon->tail_len),
beacon->tail, beacon->tail_len); beacon->tail, beacon->tail_len);
...@@ -2141,7 +2152,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, ...@@ -2141,7 +2152,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
rcu_read_unlock(); rcu_read_unlock();
return skb; return skb;
} }
EXPORT_SYMBOL(ieee80211_beacon_get); EXPORT_SYMBOL(ieee80211_beacon_get_tim);
void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
const void *frame, size_t frame_len, const void *frame, size_t frame_len,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册