mac80211: allow easier multicast/broadcast buffering in hardware
There are various decisions influencing the decision whether to buffer a frame for after the next DTIM beacon. The "do we have stations in PS mode" condition cannot be tested by the driver so mac80211 has to do that. To ease driver writing for hardware that can buffer frames until after the next DTIM beacon, introduce a new txctl flag telling the driver to buffer a specific frame. While at it, restructure and comment the code for multicast buffering and remove spurious "inline" directives. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Cc: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
4e20cb293c
commit
7d54d0ddd6
|
@ -308,6 +308,8 @@ struct ieee80211_tx_control {
|
||||||
* set_retry_limit configured
|
* set_retry_limit configured
|
||||||
* long retry value */
|
* long retry value */
|
||||||
#define IEEE80211_TXCTL_EAPOL_FRAME (1<<11) /* internal to mac80211 */
|
#define IEEE80211_TXCTL_EAPOL_FRAME (1<<11) /* internal to mac80211 */
|
||||||
|
#define IEEE80211_TXCTL_SEND_AFTER_DTIM (1<<12) /* send this frame after DTIM
|
||||||
|
* beacon */
|
||||||
u32 flags; /* tx control flags defined
|
u32 flags; /* tx control flags defined
|
||||||
* above */
|
* above */
|
||||||
u8 key_idx; /* keyidx from hw->set_key(), undefined if
|
u8 key_idx; /* keyidx from hw->set_key(), undefined if
|
||||||
|
|
|
@ -322,16 +322,27 @@ static void purge_old_ps_buffers(struct ieee80211_local *local)
|
||||||
wiphy_name(local->hw.wiphy), purged);
|
wiphy_name(local->hw.wiphy), purged);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline ieee80211_txrx_result
|
static ieee80211_txrx_result
|
||||||
ieee80211_tx_h_multicast_ps_buf(struct ieee80211_txrx_data *tx)
|
ieee80211_tx_h_multicast_ps_buf(struct ieee80211_txrx_data *tx)
|
||||||
{
|
{
|
||||||
/* broadcast/multicast frame */
|
/*
|
||||||
/* If any of the associated stations is in power save mode,
|
* broadcast/multicast frame
|
||||||
* the frame is buffered to be sent after DTIM beacon frame */
|
*
|
||||||
if ((tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) &&
|
* If any of the associated stations is in power save mode,
|
||||||
tx->sdata->type != IEEE80211_IF_TYPE_WDS &&
|
* the frame is buffered to be sent after DTIM beacon frame.
|
||||||
tx->sdata->bss && atomic_read(&tx->sdata->bss->num_sta_ps) &&
|
* This is done either by the hardware or us.
|
||||||
!(tx->fc & IEEE80211_FCTL_ORDER)) {
|
*/
|
||||||
|
|
||||||
|
/* not AP/IBSS or ordered frame */
|
||||||
|
if (!tx->sdata->bss || (tx->fc & IEEE80211_FCTL_ORDER))
|
||||||
|
return TXRX_CONTINUE;
|
||||||
|
|
||||||
|
/* no stations in PS mode */
|
||||||
|
if (!atomic_read(&tx->sdata->bss->num_sta_ps))
|
||||||
|
return TXRX_CONTINUE;
|
||||||
|
|
||||||
|
/* buffered in mac80211 */
|
||||||
|
if (tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) {
|
||||||
if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
|
if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
|
||||||
purge_old_ps_buffers(tx->local);
|
purge_old_ps_buffers(tx->local);
|
||||||
if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >=
|
if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >=
|
||||||
|
@ -348,10 +359,13 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_txrx_data *tx)
|
||||||
return TXRX_QUEUED;
|
return TXRX_QUEUED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* buffered in hardware */
|
||||||
|
tx->u.tx.control->flags |= IEEE80211_TXCTL_SEND_AFTER_DTIM;
|
||||||
|
|
||||||
return TXRX_CONTINUE;
|
return TXRX_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline ieee80211_txrx_result
|
static ieee80211_txrx_result
|
||||||
ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
|
ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
|
||||||
{
|
{
|
||||||
struct sta_info *sta = tx->sta;
|
struct sta_info *sta = tx->sta;
|
||||||
|
|
Loading…
Reference in a new issue