wl12xx: re-enable block ack session support
Incorporate interface changes for HT support. Add ba_bitmap field to the wl1271_link struct, to indicate activate RX BA sessions (for AP mode). Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Eliad Peller <eliad@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
This commit is contained in:
parent
e51ae9be2e
commit
0f9c8250e1
|
@ -1323,19 +1323,15 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* Allow HT Operation ? */
|
||||
if (allow_ht_operation) {
|
||||
ht_capabilites =
|
||||
WL1271_ACX_FW_CAP_HT_OPERATION;
|
||||
if (ht_cap->cap & IEEE80211_HT_CAP_GRN_FLD)
|
||||
ht_capabilites |=
|
||||
WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT;
|
||||
if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20)
|
||||
ht_capabilites |=
|
||||
WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS;
|
||||
if (ht_cap->cap & IEEE80211_HT_CAP_LSIG_TXOP_PROT)
|
||||
ht_capabilites |=
|
||||
WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION;
|
||||
/* no need to translate capabilities - use the spec values */
|
||||
ht_capabilites = ht_cap->cap;
|
||||
|
||||
/*
|
||||
* this bit is not employed by the spec but only by FW to
|
||||
* indicate peer HT support
|
||||
*/
|
||||
ht_capabilites |= WL12XX_HT_CAP_HT_OPERATION;
|
||||
|
||||
/* get data from A-MPDU parameters field */
|
||||
acx->ampdu_max_length = ht_cap->ampdu_factor;
|
||||
|
@ -1392,14 +1388,12 @@ out:
|
|||
}
|
||||
|
||||
/* Configure BA session initiator/receiver parameters setting in the FW. */
|
||||
int wl1271_acx_set_ba_session(struct wl1271 *wl,
|
||||
enum ieee80211_back_parties direction,
|
||||
u8 tid_index, u8 policy)
|
||||
int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271_acx_ba_session_policy *acx;
|
||||
struct wl1271_acx_ba_initiator_policy *acx;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx ba session setting");
|
||||
wl1271_debug(DEBUG_ACX, "acx ba initiator policy");
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx) {
|
||||
|
@ -1407,33 +1401,18 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl,
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* ANY role */
|
||||
acx->role_id = 0xff;
|
||||
acx->tid = tid_index;
|
||||
acx->enable = policy;
|
||||
acx->ba_direction = direction;
|
||||
|
||||
switch (direction) {
|
||||
case WLAN_BACK_INITIATOR:
|
||||
acx->win_size = wl->conf.ht.tx_ba_win_size;
|
||||
acx->inactivity_timeout = wl->conf.ht.inactivity_timeout;
|
||||
break;
|
||||
case WLAN_BACK_RECIPIENT:
|
||||
acx->win_size = RX_BA_WIN_SIZE;
|
||||
acx->inactivity_timeout = 0;
|
||||
break;
|
||||
default:
|
||||
wl1271_error("Incorrect acx command id=%x\n", direction);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
/* set for the current role */
|
||||
acx->role_id = wl->role_id;
|
||||
acx->tid_bitmap = wl->conf.ht.tx_ba_tid_bitmap;
|
||||
acx->win_size = wl->conf.ht.tx_ba_win_size;
|
||||
acx->inactivity_timeout = wl->conf.ht.inactivity_timeout;
|
||||
|
||||
ret = wl1271_cmd_configure(wl,
|
||||
ACX_BA_SESSION_POLICY_CFG,
|
||||
ACX_BA_SESSION_INIT_POLICY,
|
||||
acx,
|
||||
sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("acx ba session setting failed: %d", ret);
|
||||
wl1271_warning("acx ba initiator policy failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1443,8 +1422,8 @@ out:
|
|||
}
|
||||
|
||||
/* setup BA session receiver setting in the FW. */
|
||||
int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
|
||||
bool enable)
|
||||
int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
|
||||
u16 ssn, bool enable, u8 peer_hlid)
|
||||
{
|
||||
struct wl1271_acx_ba_receiver_setup *acx;
|
||||
int ret;
|
||||
|
@ -1457,11 +1436,10 @@ int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* Single link for now */
|
||||
acx->link_id = 1;
|
||||
acx->hlid = peer_hlid;
|
||||
acx->tid = tid_index;
|
||||
acx->enable = enable;
|
||||
acx->win_size = 0;
|
||||
acx->win_size = wl->conf.ht.rx_ba_win_size;
|
||||
acx->ssn = ssn;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_BA_SESSION_RX_SETUP, acx,
|
||||
|
|
|
@ -899,6 +899,10 @@ struct wl1271_acx_rssi_snr_avg_weights {
|
|||
u8 snr_data;
|
||||
};
|
||||
|
||||
|
||||
/* special capability bit (not employed by the 802.11n spec) */
|
||||
#define WL12XX_HT_CAP_HT_OPERATION BIT(16)
|
||||
|
||||
/*
|
||||
* ACX_PEER_HT_CAP
|
||||
* Configure HT capabilities - declare the capabilities of the peer
|
||||
|
@ -907,19 +911,7 @@ struct wl1271_acx_rssi_snr_avg_weights {
|
|||
struct wl1271_acx_ht_capabilities {
|
||||
struct acx_header header;
|
||||
|
||||
/*
|
||||
* bit 0 - Allow HT Operation
|
||||
* bit 1 - Allow Greenfield format in TX
|
||||
* bit 2 - Allow Short GI in TX
|
||||
* bit 3 - Allow L-SIG TXOP Protection in TX
|
||||
* bit 4 - Allow HT Control fields in TX.
|
||||
* Note, driver will still leave space for HT control in packets
|
||||
* regardless of the value of this field. FW will be responsible
|
||||
* to drop the HT field from any frame when this Bit set to 0.
|
||||
* bit 5 - Allow RD initiation in TXOP. FW is allowed to initate RD.
|
||||
* Exact policy setting for this feature is TBD.
|
||||
* Note, this bit can only be set to 1 if bit 3 is set to 1.
|
||||
*/
|
||||
/* bitmask of capability bits supported by the peer */
|
||||
__le32 ht_capabilites;
|
||||
|
||||
/* Indicates to which link these capabilities apply. */
|
||||
|
@ -937,15 +929,6 @@ struct wl1271_acx_ht_capabilities {
|
|||
u8 padding;
|
||||
} __packed;
|
||||
|
||||
/* HT Capabilites Fw Bit Mask Mapping */
|
||||
#define WL1271_ACX_FW_CAP_HT_OPERATION BIT(0)
|
||||
#define WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT BIT(1)
|
||||
#define WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS BIT(2)
|
||||
#define WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION BIT(3)
|
||||
#define WL1271_ACX_FW_CAP_HT_CONTROL_FIELDS BIT(4)
|
||||
#define WL1271_ACX_FW_CAP_RD_INITIATION BIT(5)
|
||||
|
||||
|
||||
/*
|
||||
* ACX_HT_BSS_OPERATION
|
||||
* Configure HT capabilities - AP rules for behavior in the BSS.
|
||||
|
@ -979,57 +962,48 @@ struct wl1271_acx_ht_information {
|
|||
u8 padding[2];
|
||||
} __packed;
|
||||
|
||||
#define RX_BA_WIN_SIZE 8
|
||||
#define RX_BA_MAX_SESSIONS 2
|
||||
|
||||
struct wl1271_acx_ba_session_policy {
|
||||
struct wl1271_acx_ba_initiator_policy {
|
||||
struct acx_header header;
|
||||
/*
|
||||
* Specifies role Id, Range 0-7, 0xFF means ANY role.
|
||||
* Future use. For now this field is irrelevant
|
||||
*/
|
||||
|
||||
/* Specifies role Id, Range 0-7, 0xFF means ANY role. */
|
||||
u8 role_id;
|
||||
|
||||
/*
|
||||
* Specifies Link Id, Range 0-31, 0xFF means ANY Link Id.
|
||||
* Not applicable if Role Id is set to ANY.
|
||||
* Per TID setting for allowing TX BA. Set a bit to 1 to allow
|
||||
* TX BA sessions for the corresponding TID.
|
||||
*/
|
||||
u8 link_id;
|
||||
|
||||
u8 tid;
|
||||
|
||||
u8 enable;
|
||||
u8 tid_bitmap;
|
||||
|
||||
/* Windows size in number of packets */
|
||||
u16 win_size;
|
||||
u8 win_size;
|
||||
|
||||
/*
|
||||
* As initiator inactivity timeout in time units(TU) of 1024us.
|
||||
* As receiver reserved
|
||||
*/
|
||||
u8 padding1[1];
|
||||
|
||||
/* As initiator inactivity timeout in time units(TU) of 1024us */
|
||||
u16 inactivity_timeout;
|
||||
|
||||
/* Initiator = 1/Receiver = 0 */
|
||||
u8 ba_direction;
|
||||
|
||||
u8 padding[3];
|
||||
u8 padding[2];
|
||||
} __packed;
|
||||
|
||||
struct wl1271_acx_ba_receiver_setup {
|
||||
struct acx_header header;
|
||||
|
||||
/* Specifies Link Id, Range 0-31, 0xFF means ANY Link Id */
|
||||
u8 link_id;
|
||||
/* Specifies link id, range 0-31 */
|
||||
u8 hlid;
|
||||
|
||||
u8 tid;
|
||||
|
||||
u8 enable;
|
||||
|
||||
u8 padding[1];
|
||||
|
||||
/* Windows size in number of packets */
|
||||
u16 win_size;
|
||||
u8 win_size;
|
||||
|
||||
/* BA session starting sequence number. RANGE 0-FFF */
|
||||
u16 ssn;
|
||||
|
||||
u8 padding[2];
|
||||
} __packed;
|
||||
|
||||
struct wl1271_acx_fw_tsf_information {
|
||||
|
@ -1218,7 +1192,7 @@ enum {
|
|||
ACX_RSSI_SNR_WEIGHTS = 0x0052,
|
||||
ACX_KEEP_ALIVE_MODE = 0x0053,
|
||||
ACX_SET_KEEP_ALIVE_CONFIG = 0x0054,
|
||||
ACX_BA_SESSION_POLICY_CFG = 0x0055,
|
||||
ACX_BA_SESSION_INIT_POLICY = 0x0055,
|
||||
ACX_BA_SESSION_RX_SETUP = 0x0056,
|
||||
ACX_PEER_HT_CAP = 0x0057,
|
||||
ACX_HT_BSS_OPERATION = 0x0058,
|
||||
|
@ -1297,11 +1271,9 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
|
|||
bool allow_ht_operation);
|
||||
int wl1271_acx_set_ht_information(struct wl1271 *wl,
|
||||
u16 ht_operation_mode);
|
||||
int wl1271_acx_set_ba_session(struct wl1271 *wl,
|
||||
enum ieee80211_back_parties direction,
|
||||
u8 tid_index, u8 policy);
|
||||
int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
|
||||
bool enable);
|
||||
int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl);
|
||||
int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
|
||||
u16 ssn, bool enable, u8 peer_hlid);
|
||||
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
|
||||
int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable);
|
||||
int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl);
|
||||
|
|
|
@ -208,6 +208,7 @@ enum {
|
|||
CMD_STATUS_TIMEOUT = 21, /* Driver internal use.*/
|
||||
CMD_STATUS_FW_RESET = 22, /* Driver internal use.*/
|
||||
CMD_STATUS_TEMPLATE_OOM = 23,
|
||||
CMD_STATUS_NO_RX_BA_SESSION = 24,
|
||||
MAX_COMMAND_STATUS = 0xff
|
||||
};
|
||||
|
||||
|
|
|
@ -557,6 +557,9 @@ struct conf_tx_ac_category {
|
|||
|
||||
#define CONF_TX_MAX_TID_COUNT 8
|
||||
|
||||
/* Allow TX BA on all TIDs but 6,7. These are currently reserved in the FW */
|
||||
#define CONF_TX_BA_ENABLED_TID_BITMAP 0x3F
|
||||
|
||||
enum {
|
||||
CONF_CHANNEL_TYPE_DCF = 0, /* DC/LEGACY*/
|
||||
CONF_CHANNEL_TYPE_EDCF = 1, /* EDCA*/
|
||||
|
@ -1095,8 +1098,12 @@ struct conf_rf_settings {
|
|||
};
|
||||
|
||||
struct conf_ht_setting {
|
||||
u16 tx_ba_win_size;
|
||||
u8 rx_ba_win_size;
|
||||
u8 tx_ba_win_size;
|
||||
u16 inactivity_timeout;
|
||||
|
||||
/* bitmap of enabled TIDs for TX BA sessions */
|
||||
u8 tx_ba_tid_bitmap;
|
||||
};
|
||||
|
||||
struct conf_memory_settings {
|
||||
|
|
|
@ -529,41 +529,24 @@ int wl1271_init_ap_rates(struct wl1271 *wl)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void wl1271_check_ba_support(struct wl1271 *wl)
|
||||
{
|
||||
/* validate FW cose ver x.x.x.50-60.x */
|
||||
if ((wl->chip.fw_ver[3] >= WL12XX_BA_SUPPORT_FW_COST_VER2_START) &&
|
||||
(wl->chip.fw_ver[3] < WL12XX_BA_SUPPORT_FW_COST_VER2_END)) {
|
||||
wl->ba_support = true;
|
||||
return;
|
||||
}
|
||||
|
||||
wl->ba_support = false;
|
||||
}
|
||||
|
||||
static int wl1271_set_ba_policies(struct wl1271 *wl)
|
||||
{
|
||||
u8 tid_index;
|
||||
int ret = 0;
|
||||
|
||||
/* Reset the BA RX indicators */
|
||||
wl->ba_rx_bitmap = 0;
|
||||
wl->ba_allowed = true;
|
||||
wl->ba_rx_session_count = 0;
|
||||
|
||||
/* validate that FW support BA */
|
||||
wl1271_check_ba_support(wl);
|
||||
/* BA is supported in STA/AP modes */
|
||||
if (wl->bss_type != BSS_TYPE_AP_BSS &&
|
||||
wl->bss_type != BSS_TYPE_STA_BSS) {
|
||||
wl->ba_support = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wl->ba_support)
|
||||
/* 802.11n initiator BA session setting */
|
||||
for (tid_index = 0; tid_index < CONF_TX_MAX_TID_COUNT;
|
||||
++tid_index) {
|
||||
ret = wl1271_acx_set_ba_session(wl, WLAN_BACK_INITIATOR,
|
||||
tid_index, true);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
wl->ba_support = true;
|
||||
|
||||
return ret;
|
||||
/* 802.11n initiator BA session setting */
|
||||
return wl12xx_acx_set_ba_initiator_policy(wl);
|
||||
}
|
||||
|
||||
int wl1271_chip_specific_init(struct wl1271 *wl)
|
||||
|
|
|
@ -286,8 +286,10 @@ static struct conf_drv_settings default_conf = {
|
|||
},
|
||||
},
|
||||
.ht = {
|
||||
.rx_ba_win_size = 8,
|
||||
.tx_ba_win_size = 64,
|
||||
.inactivity_timeout = 10000,
|
||||
.tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP,
|
||||
},
|
||||
.mem_wl127x = {
|
||||
.num_stations = 1,
|
||||
|
@ -3191,9 +3193,12 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
|
|||
}
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(vif, bss_conf->bssid);
|
||||
if (sta) {
|
||||
if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) {
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(vif, bss_conf->bssid);
|
||||
if (!sta)
|
||||
goto sta_not_found;
|
||||
|
||||
/* save the supp_rates of the ap */
|
||||
sta_rate_set = sta->supp_rates[wl->hw->conf.channel->band];
|
||||
if (sta->ht_cap.ht_supported)
|
||||
|
@ -3201,38 +3206,9 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
|
|||
(sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET);
|
||||
sta_ht_cap = sta->ht_cap;
|
||||
sta_exists = true;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (sta_exists) {
|
||||
/* handle new association with HT and HT information change */
|
||||
if ((changed & BSS_CHANGED_HT) &&
|
||||
(bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
|
||||
ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
|
||||
true);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("Set ht cap true failed %d",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
ret = wl1271_acx_set_ht_information(wl,
|
||||
bss_conf->ht_operation_mode);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("Set ht information failed %d",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/* handle new association without HT and disassociation */
|
||||
else if (changed & BSS_CHANGED_ASSOC) {
|
||||
ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
|
||||
false);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("Set ht cap false failed %d",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
sta_not_found:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
if ((changed & BSS_CHANGED_ASSOC)) {
|
||||
|
@ -3440,6 +3416,41 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
|
|||
}
|
||||
}
|
||||
|
||||
/* Handle new association with HT. Do this only after join. */
|
||||
if (sta_exists) {
|
||||
if ((changed & BSS_CHANGED_HT) &&
|
||||
(bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
|
||||
ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
|
||||
true);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("Set ht cap true failed %d",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/* handle new association without HT and disassociation */
|
||||
else if (changed & BSS_CHANGED_ASSOC) {
|
||||
ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
|
||||
false);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("Set ht cap false failed %d",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle HT information change. Only after join. */
|
||||
if (sta_exists && (changed & BSS_CHANGED_HT) &&
|
||||
(bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
|
||||
ret = wl1271_acx_set_ht_information(wl,
|
||||
bss_conf->ht_operation_mode);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("Set ht information failed %d", ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
@ -3623,6 +3634,7 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
|
|||
|
||||
__clear_bit(id, wl->ap_hlid_map);
|
||||
memset(wl->links[hlid].addr, 0, ETH_ALEN);
|
||||
wl->links[hlid].ba_bitmap = 0;
|
||||
wl1271_tx_reset_link_queues(wl, hlid);
|
||||
__clear_bit(hlid, &wl->ap_ps_map);
|
||||
__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
|
||||
|
@ -3725,6 +3737,14 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
int ret;
|
||||
u8 hlid, *ba_bitmap;
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu action %d tid %d", action,
|
||||
tid);
|
||||
|
||||
/* sanity check - the fields in FW are only 8bits wide */
|
||||
if (WARN_ON(tid > 0xFF))
|
||||
return -ENOTSUPP;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
|
@ -3733,6 +3753,20 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (wl->bss_type == BSS_TYPE_STA_BSS) {
|
||||
hlid = wl->sta_hlid;
|
||||
ba_bitmap = &wl->ba_rx_bitmap;
|
||||
} else if (wl->bss_type == BSS_TYPE_AP_BSS) {
|
||||
struct wl1271_station *wl_sta;
|
||||
|
||||
wl_sta = (struct wl1271_station *)sta->drv_priv;
|
||||
hlid = wl_sta->hlid;
|
||||
ba_bitmap = &wl->links[hlid].ba_bitmap;
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
@ -3742,20 +3776,46 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
|
|||
|
||||
switch (action) {
|
||||
case IEEE80211_AMPDU_RX_START:
|
||||
if ((wl->ba_support) && (wl->ba_allowed)) {
|
||||
ret = wl1271_acx_set_ba_receiver_session(wl, tid, *ssn,
|
||||
true);
|
||||
if (!ret)
|
||||
wl->ba_rx_bitmap |= BIT(tid);
|
||||
} else {
|
||||
if (!wl->ba_support || !wl->ba_allowed) {
|
||||
ret = -ENOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (wl->ba_rx_session_count >= RX_BA_MAX_SESSIONS) {
|
||||
ret = -EBUSY;
|
||||
wl1271_error("exceeded max RX BA sessions");
|
||||
break;
|
||||
}
|
||||
|
||||
if (*ba_bitmap & BIT(tid)) {
|
||||
ret = -EINVAL;
|
||||
wl1271_error("cannot enable RX BA session on active "
|
||||
"tid: %d", tid);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = wl12xx_acx_set_ba_receiver_session(wl, tid, *ssn, true,
|
||||
hlid);
|
||||
if (!ret) {
|
||||
*ba_bitmap |= BIT(tid);
|
||||
wl->ba_rx_session_count++;
|
||||
}
|
||||
break;
|
||||
|
||||
case IEEE80211_AMPDU_RX_STOP:
|
||||
ret = wl1271_acx_set_ba_receiver_session(wl, tid, 0, false);
|
||||
if (!ret)
|
||||
wl->ba_rx_bitmap &= ~BIT(tid);
|
||||
if (!(*ba_bitmap & BIT(tid))) {
|
||||
ret = -EINVAL;
|
||||
wl1271_error("no active RX BA session on tid: %d",
|
||||
tid);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = wl12xx_acx_set_ba_receiver_session(wl, tid, 0, false,
|
||||
hlid);
|
||||
if (!ret) {
|
||||
*ba_bitmap &= ~BIT(tid);
|
||||
wl->ba_rx_session_count--;
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
|
|
|
@ -355,6 +355,9 @@ struct wl1271_link {
|
|||
u8 prev_freed_blks;
|
||||
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
/* bitmap of TIDs where RX BA sessions are active for this link */
|
||||
u8 ba_bitmap;
|
||||
};
|
||||
|
||||
struct wl1271 {
|
||||
|
@ -609,6 +612,9 @@ struct wl1271 {
|
|||
|
||||
/* Platform limitations */
|
||||
unsigned int platform_quirks;
|
||||
|
||||
/* number of currently active RX BA sessions */
|
||||
int ba_rx_session_count;
|
||||
};
|
||||
|
||||
struct wl1271_station {
|
||||
|
|
Loading…
Reference in New Issue