static int brcms_ops_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size) { struct brcms_info *wl = hw->priv; struct scb *scb = &wl->wlc->pri_scb; int status; if (WARN_ON(scb->magic != SCB_MAGIC)) return -EIDRM; switch (action) { case IEEE80211_AMPDU_RX_START: break; case IEEE80211_AMPDU_RX_STOP: break; case IEEE80211_AMPDU_TX_START: spin_lock_bh(&wl->lock); status = brcms_c_aggregatable(wl->wlc, tid); spin_unlock_bh(&wl->lock); if (!status) { brcms_err(wl->wlc->hw->d11core, "START: tid %d is not agg\'able\n", tid); return -EINVAL; } ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; case IEEE80211_AMPDU_TX_STOP_CONT: case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: spin_lock_bh(&wl->lock); brcms_c_ampdu_flush(wl->wlc, sta, tid); spin_unlock_bh(&wl->lock); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; case IEEE80211_AMPDU_TX_OPERATIONAL: /* * BA window size from ADDBA response ('buf_size') defines how * many outstanding MPDUs are allowed for the BA stream by * recipient and traffic class. 'ampdu_factor' gives maximum * AMPDU size. */ spin_lock_bh(&wl->lock); brcms_c_ampdu_tx_operational(wl->wlc, tid, buf_size, (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + sta->ht_cap.ampdu_factor)) - 1); spin_unlock_bh(&wl->lock); /* Power save wakeup */ break; default: brcms_err(wl->wlc->hw->d11core, "%s: Invalid command, ignoring\n", __func__); } return 0; }
static int brcms_ops_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size) { struct scb *scb = (struct scb *)sta->drv_priv; struct brcms_info *wl = hw->priv; int status; if (WARN_ON(scb->magic != SCB_MAGIC)) return -EIDRM; switch (action) { case IEEE80211_AMPDU_RX_START: break; case IEEE80211_AMPDU_RX_STOP: break; case IEEE80211_AMPDU_TX_START: LOCK(wl); status = brcms_c_aggregatable(wl->wlc, tid); UNLOCK(wl); if (!status) { wiphy_err(wl->wiphy, "START: tid %d is not agg\'able\n", tid); return -EINVAL; } /* Future improvement: Use the starting sequence number provided ... */ *ssn = 0; ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; case IEEE80211_AMPDU_TX_STOP: LOCK(wl); brcms_c_ampdu_flush(wl->wlc, sta, tid); UNLOCK(wl); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; case IEEE80211_AMPDU_TX_OPERATIONAL: /* * BA window size from ADDBA response ('buf_size') defines how * many outstanding MPDUs are allowed for the BA stream by * recipient and traffic class. 'ampdu_factor' gives maximum * AMPDU size. */ LOCK(wl); brcms_c_ampdu_tx_operational(wl->wlc, tid, buf_size, (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + sta->ht_cap.ampdu_factor)) - 1); UNLOCK(wl); /* Power save wakeup */ break; default: wiphy_err(wl->wiphy, "%s: Invalid command, ignoring\n", __func__); } return 0; }