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: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
committed by
John W. Linville
parent
750266646b
commit
eddcbb94f7
@@ -1742,20 +1742,46 @@ void ieee80211_tx_status(struct ieee80211_hw *hw,
|
|||||||
void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
|
void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
|
||||||
struct sk_buff *skb);
|
struct sk_buff *skb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ieee80211_beacon_get_tim - beacon generation function
|
||||||
|
* @hw: pointer obtained from ieee80211_alloc_hw().
|
||||||
|
* @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
|
||||||
|
* hardware/firmware), the driver uses this function to get each beacon
|
||||||
|
* frame from mac80211 -- it is responsible for calling this function
|
||||||
|
* before the beacon is needed (e.g. based on hardware interrupt).
|
||||||
|
*
|
||||||
|
* 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
|
* ieee80211_beacon_get - 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.
|
||||||
*
|
*
|
||||||
* If the beacon frames are generated by the host system (i.e., not in
|
* See ieee80211_beacon_get_tim().
|
||||||
* hardware/firmware), the low-level driver uses this function to receive
|
|
||||||
* the next beacon frame from the 802.11 code. The low-level is responsible
|
|
||||||
* for calling this function before beacon data is needed (e.g., based on
|
|
||||||
* hardware interrupt). Returned skb is used only once and low-level driver
|
|
||||||
* is responsible for freeing it.
|
|
||||||
*/
|
*/
|
||||||
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,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
||||||
|
Reference in New Issue
Block a user