diff options
author | Johannes Berg <johannes.berg@intel.com> | 2022-01-28 15:34:32 +0200 |
---|---|---|
committer | Luca Coelho <luciano.coelho@intel.com> | 2022-02-18 10:40:50 +0200 |
commit | 97f70c56e6ca1e9bad1cbf6d3b0592f150bb95b1 (patch) | |
tree | 1aa2a31b740340e7d6a70b82ccbccb3defbd6027 /drivers/net/wireless/intel/iwlwifi/mvm/sta.c | |
parent | 0f3a4e480c6ab56435504fce5b57eb388f3b52fa (diff) | |
download | linux-97f70c56e6ca1e9bad1cbf6d3b0592f150bb95b1.tar.gz linux-97f70c56e6ca1e9bad1cbf6d3b0592f150bb95b1.tar.bz2 linux-97f70c56e6ca1e9bad1cbf6d3b0592f150bb95b1.zip |
iwlwifi: mvm: support new BAID allocation command
Due to some rearchitecting inside the firmware, a new BAID
allocation command is being introduced. Support it. Note
that with it the firmware no longer returns "no space" but
will crash instead, so check for that before sending the
command to the firmware.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20220128153014.a89fa3bd9d91.Ibe58c5d9e882dad43aa857aa1c8f54f3358c667b@changeid
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/sta.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 72 |
1 files changed, 69 insertions, 3 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index d35e97325d5f..05cd33bdbd31 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -2548,8 +2548,10 @@ static void iwl_mvm_init_reorder_buffer(struct iwl_mvm *mvm, } } -static int iwl_mvm_fw_baid_op(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvm_sta, - bool start, int tid, u16 ssn, u16 buf_size) +static int iwl_mvm_fw_baid_op_sta(struct iwl_mvm *mvm, + struct iwl_mvm_sta *mvm_sta, + bool start, int tid, u16 ssn, + u16 buf_size) { struct iwl_mvm_add_sta_cmd cmd = { .mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color), @@ -2594,6 +2596,62 @@ static int iwl_mvm_fw_baid_op(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvm_sta, } } +static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm, + struct iwl_mvm_sta *mvm_sta, + bool start, int tid, u16 ssn, + u16 buf_size, int baid) +{ + struct iwl_rx_baid_cfg_cmd cmd = { + .action = start ? cpu_to_le32(IWL_RX_BAID_ACTION_ADD) : + cpu_to_le32(IWL_RX_BAID_ACTION_REMOVE), + }; + u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, RX_BAID_ALLOCATION_CONFIG_CMD); + int ret; + + BUILD_BUG_ON(sizeof(struct iwl_rx_baid_cfg_resp) != sizeof(baid)); + + if (start) { + cmd.alloc.sta_id_mask = cpu_to_le32(BIT(mvm_sta->sta_id)); + cmd.alloc.tid = tid; + cmd.alloc.ssn = cpu_to_le16(ssn); + cmd.alloc.win_size = cpu_to_le16(buf_size); + baid = -EIO; + } else { + cmd.remove.baid = cpu_to_le32(baid); + } + + ret = iwl_mvm_send_cmd_pdu_status(mvm, cmd_id, sizeof(cmd), + &cmd, &baid); + if (ret) + return ret; + + if (!start) { + /* ignore firmware baid on remove */ + baid = 0; + } + + IWL_DEBUG_HT(mvm, "RX BA Session %sed in fw\n", + start ? "start" : "stopp"); + + if (baid < 0 || baid >= ARRAY_SIZE(mvm->baid_map)) + return -EINVAL; + + return baid; +} + +static int iwl_mvm_fw_baid_op(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvm_sta, + bool start, int tid, u16 ssn, u16 buf_size, + int baid) +{ + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_BAID_ML_SUPPORT)) + return iwl_mvm_fw_baid_op_cmd(mvm, mvm_sta, start, + tid, ssn, buf_size, baid); + + return iwl_mvm_fw_baid_op_sta(mvm, mvm_sta, start, + tid, ssn, buf_size); +} + int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, int tid, u16 ssn, bool start, u16 buf_size, u16 timeout) { @@ -2649,7 +2707,15 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, reorder_buf_size / sizeof(baid_data->entries[0]); } - baid = iwl_mvm_fw_baid_op(mvm, mvm_sta, start, tid, ssn, buf_size); + if (iwl_mvm_has_new_rx_api(mvm) && !start) { + baid = mvm_sta->tid_to_baid[tid]; + } else { + /* we don't really need it in this case */ + baid = -1; + } + + baid = iwl_mvm_fw_baid_op(mvm, mvm_sta, start, tid, ssn, buf_size, + baid); if (baid < 0) { ret = baid; goto out_free; |