|
@@ -322,16 +322,27 @@ static void purge_old_ps_buffers(struct ieee80211_local *local)
|
|
|
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)
|
|
|
{
|
|
|
- /* broadcast/multicast frame */
|
|
|
- /* If any of the associated stations is in power save mode,
|
|
|
- * the frame is buffered to be sent after DTIM beacon frame */
|
|
|
- if ((tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) &&
|
|
|
- tx->sdata->type != IEEE80211_IF_TYPE_WDS &&
|
|
|
- tx->sdata->bss && atomic_read(&tx->sdata->bss->num_sta_ps) &&
|
|
|
- !(tx->fc & IEEE80211_FCTL_ORDER)) {
|
|
|
+ /*
|
|
|
+ * broadcast/multicast frame
|
|
|
+ *
|
|
|
+ * If any of the associated stations is in power save mode,
|
|
|
+ * the frame is buffered to be sent after DTIM beacon frame.
|
|
|
+ * This is done either by the hardware or us.
|
|
|
+ */
|
|
|
+
|
|
|
+ /* 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)
|
|
|
purge_old_ps_buffers(tx->local);
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
+ /* buffered in hardware */
|
|
|
+ tx->u.tx.control->flags |= IEEE80211_TXCTL_SEND_AFTER_DTIM;
|
|
|
+
|
|
|
return TXRX_CONTINUE;
|
|
|
}
|
|
|
|
|
|
-static inline ieee80211_txrx_result
|
|
|
+static ieee80211_txrx_result
|
|
|
ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
|
|
|
{
|
|
|
struct sta_info *sta = tx->sta;
|