wifi: iwlwifi: mvm: track station mask for BAIDs
When we have MLO connections, a BAID applies to multiple firmware stations. Track the station mask instead of the station ID, getting rid of a few more deflink cases and preparing for handling link switching for BAIDs. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Link: https://lore.kernel.org/r/20230416154301.c08523808c34.I719b7bba499648d1495ed3e3a90889d4732ef15d@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
ef3ed33dfc
commit
9aa3856d9b
|
@ -680,7 +680,7 @@ __aligned(roundup_pow_of_two(sizeof(struct _iwl_mvm_reorder_buf_entry)))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct iwl_mvm_baid_data - BA session data
|
* struct iwl_mvm_baid_data - BA session data
|
||||||
* @sta_id: station id
|
* @sta_mask: current station mask for the BAID
|
||||||
* @tid: tid of the session
|
* @tid: tid of the session
|
||||||
* @baid baid of the session
|
* @baid baid of the session
|
||||||
* @timeout: the timeout set in the addba request
|
* @timeout: the timeout set in the addba request
|
||||||
|
@ -694,7 +694,7 @@ __aligned(roundup_pow_of_two(sizeof(struct _iwl_mvm_reorder_buf_entry)))
|
||||||
*/
|
*/
|
||||||
struct iwl_mvm_baid_data {
|
struct iwl_mvm_baid_data {
|
||||||
struct rcu_head rcu_head;
|
struct rcu_head rcu_head;
|
||||||
u8 sta_id;
|
u32 sta_mask;
|
||||||
u8 tid;
|
u8 tid;
|
||||||
u8 baid;
|
u8 baid;
|
||||||
u16 timeout;
|
u16 timeout;
|
||||||
|
|
|
@ -705,7 +705,7 @@ void iwl_mvm_reorder_timer_expired(struct timer_list *t)
|
||||||
if (expired) {
|
if (expired) {
|
||||||
struct ieee80211_sta *sta;
|
struct ieee80211_sta *sta;
|
||||||
struct iwl_mvm_sta *mvmsta;
|
struct iwl_mvm_sta *mvmsta;
|
||||||
u8 sta_id = baid_data->sta_id;
|
u8 sta_id = ffs(baid_data->sta_mask) - 1;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
sta = rcu_dereference(buf->mvm->fw_id_to_mac_id[sta_id]);
|
sta = rcu_dereference(buf->mvm->fw_id_to_mac_id[sta_id]);
|
||||||
|
@ -740,6 +740,7 @@ static void iwl_mvm_del_ba(struct iwl_mvm *mvm, int queue,
|
||||||
struct ieee80211_sta *sta;
|
struct ieee80211_sta *sta;
|
||||||
struct iwl_mvm_reorder_buffer *reorder_buf;
|
struct iwl_mvm_reorder_buffer *reorder_buf;
|
||||||
u8 baid = data->baid;
|
u8 baid = data->baid;
|
||||||
|
u32 sta_id;
|
||||||
|
|
||||||
if (WARN_ONCE(baid >= IWL_MAX_BAID, "invalid BAID: %x\n", baid))
|
if (WARN_ONCE(baid >= IWL_MAX_BAID, "invalid BAID: %x\n", baid))
|
||||||
return;
|
return;
|
||||||
|
@ -750,7 +751,9 @@ static void iwl_mvm_del_ba(struct iwl_mvm *mvm, int queue,
|
||||||
if (WARN_ON_ONCE(!ba_data))
|
if (WARN_ON_ONCE(!ba_data))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[ba_data->sta_id]);
|
/* pick any STA ID to find the pointer */
|
||||||
|
sta_id = ffs(ba_data->sta_mask) - 1;
|
||||||
|
sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
|
||||||
if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
|
if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -777,6 +780,7 @@ static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,
|
||||||
struct ieee80211_sta *sta;
|
struct ieee80211_sta *sta;
|
||||||
struct iwl_mvm_reorder_buffer *reorder_buf;
|
struct iwl_mvm_reorder_buffer *reorder_buf;
|
||||||
struct iwl_mvm_baid_data *ba_data;
|
struct iwl_mvm_baid_data *ba_data;
|
||||||
|
u32 sta_id;
|
||||||
|
|
||||||
IWL_DEBUG_HT(mvm, "Frame release notification for BAID %u, NSSN %d\n",
|
IWL_DEBUG_HT(mvm, "Frame release notification for BAID %u, NSSN %d\n",
|
||||||
baid, nssn);
|
baid, nssn);
|
||||||
|
@ -794,7 +798,9 @@ static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[ba_data->sta_id]);
|
/* pick any STA ID to find the pointer */
|
||||||
|
sta_id = ffs(ba_data->sta_mask) - 1;
|
||||||
|
sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
|
||||||
if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
|
if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -935,7 +941,6 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
||||||
{
|
{
|
||||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||||
struct ieee80211_hdr *hdr = (void *)skb_mac_header(skb);
|
struct ieee80211_hdr *hdr = (void *)skb_mac_header(skb);
|
||||||
struct iwl_mvm_sta *mvm_sta;
|
|
||||||
struct iwl_mvm_baid_data *baid_data;
|
struct iwl_mvm_baid_data *baid_data;
|
||||||
struct iwl_mvm_reorder_buffer *buffer;
|
struct iwl_mvm_reorder_buffer *buffer;
|
||||||
struct sk_buff *tail;
|
struct sk_buff *tail;
|
||||||
|
@ -947,6 +952,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
||||||
u8 sub_frame_idx = desc->amsdu_info &
|
u8 sub_frame_idx = desc->amsdu_info &
|
||||||
IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;
|
IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;
|
||||||
struct iwl_mvm_reorder_buf_entry *entries;
|
struct iwl_mvm_reorder_buf_entry *entries;
|
||||||
|
u32 sta_mask;
|
||||||
int index;
|
int index;
|
||||||
u16 nssn, sn;
|
u16 nssn, sn;
|
||||||
u8 baid;
|
u8 baid;
|
||||||
|
@ -969,8 +975,6 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
||||||
"Got valid BAID without a valid station assigned\n"))
|
"Got valid BAID without a valid station assigned\n"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
|
||||||
|
|
||||||
/* not a data packet or a bar */
|
/* not a data packet or a bar */
|
||||||
if (!ieee80211_is_back_req(hdr->frame_control) &&
|
if (!ieee80211_is_back_req(hdr->frame_control) &&
|
||||||
(!ieee80211_is_data_qos(hdr->frame_control) ||
|
(!ieee80211_is_data_qos(hdr->frame_control) ||
|
||||||
|
@ -988,11 +992,14 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
sta_mask = iwl_mvm_sta_fw_id_mask(mvm, sta, -1);
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (WARN(tid != baid_data->tid ||
|
if (WARN(tid != baid_data->tid ||
|
||||||
mvm_sta->deflink.sta_id != baid_data->sta_id,
|
!(sta_mask & baid_data->sta_mask),
|
||||||
"baid 0x%x is mapped to sta:%d tid:%d, but was received for sta:%d tid:%d\n",
|
"baid 0x%x is mapped to sta_mask:0x%x tid:%d, but was received for sta_mask:0x%x tid:%d\n",
|
||||||
baid, baid_data->sta_id, baid_data->tid, mvm_sta->deflink.sta_id,
|
baid, baid_data->sta_mask, baid_data->tid, sta_mask, tid))
|
||||||
tid))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
nssn = reorder & IWL_RX_MPDU_REORDER_NSSN_MASK;
|
nssn = reorder & IWL_RX_MPDU_REORDER_NSSN_MASK;
|
||||||
|
@ -2776,9 +2783,10 @@ void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WARN(tid != baid_data->tid || sta_id != baid_data->sta_id,
|
if (WARN(tid != baid_data->tid || sta_id > IWL_MVM_STATION_COUNT_MAX ||
|
||||||
"baid 0x%x is mapped to sta:%d tid:%d, but BAR release received for sta:%d tid:%d\n",
|
!(baid_data->sta_mask & BIT(sta_id)),
|
||||||
baid, baid_data->sta_id, baid_data->tid, sta_id,
|
"baid 0x%x is mapped to sta_mask:0x%x tid:%d, but BAR release received for sta:%d tid:%d\n",
|
||||||
|
baid, baid_data->sta_mask, baid_data->tid, sta_id,
|
||||||
tid))
|
tid))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
|
@ -251,6 +251,7 @@ static void iwl_mvm_rx_agg_session_expired(struct timer_list *t)
|
||||||
struct ieee80211_sta *sta;
|
struct ieee80211_sta *sta;
|
||||||
struct iwl_mvm_sta *mvm_sta;
|
struct iwl_mvm_sta *mvm_sta;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
|
unsigned int sta_id;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
|
||||||
|
@ -269,7 +270,8 @@ static void iwl_mvm_rx_agg_session_expired(struct timer_list *t)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Timer expired */
|
/* Timer expired */
|
||||||
sta = rcu_dereference(ba_data->mvm->fw_id_to_mac_id[ba_data->sta_id]);
|
sta_id = ffs(ba_data->sta_mask) - 1; /* don't care which one */
|
||||||
|
sta = rcu_dereference(ba_data->mvm->fw_id_to_mac_id[sta_id]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sta should be valid unless the following happens:
|
* sta should be valid unless the following happens:
|
||||||
|
@ -2756,10 +2758,11 @@ static void iwl_mvm_init_reorder_buffer(struct iwl_mvm *mvm,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iwl_mvm_fw_baid_op_sta(struct iwl_mvm *mvm,
|
static int iwl_mvm_fw_baid_op_sta(struct iwl_mvm *mvm,
|
||||||
struct iwl_mvm_sta *mvm_sta,
|
struct ieee80211_sta *sta,
|
||||||
bool start, int tid, u16 ssn,
|
bool start, int tid, u16 ssn,
|
||||||
u16 buf_size)
|
u16 buf_size)
|
||||||
{
|
{
|
||||||
|
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
||||||
struct iwl_mvm_add_sta_cmd cmd = {
|
struct iwl_mvm_add_sta_cmd cmd = {
|
||||||
.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color),
|
.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color),
|
||||||
.sta_id = mvm_sta->deflink.sta_id,
|
.sta_id = mvm_sta->deflink.sta_id,
|
||||||
|
@ -2804,7 +2807,7 @@ static int iwl_mvm_fw_baid_op_sta(struct iwl_mvm *mvm,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm,
|
static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm,
|
||||||
struct iwl_mvm_sta *mvm_sta,
|
struct ieee80211_sta *sta,
|
||||||
bool start, int tid, u16 ssn,
|
bool start, int tid, u16 ssn,
|
||||||
u16 buf_size, int baid)
|
u16 buf_size, int baid)
|
||||||
{
|
{
|
||||||
|
@ -2819,7 +2822,7 @@ static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm,
|
||||||
|
|
||||||
if (start) {
|
if (start) {
|
||||||
cmd.alloc.sta_id_mask =
|
cmd.alloc.sta_id_mask =
|
||||||
cpu_to_le32(BIT(mvm_sta->deflink.sta_id));
|
cpu_to_le32(iwl_mvm_sta_fw_id_mask(mvm, sta, -1));
|
||||||
cmd.alloc.tid = tid;
|
cmd.alloc.tid = tid;
|
||||||
cmd.alloc.ssn = cpu_to_le16(ssn);
|
cmd.alloc.ssn = cpu_to_le16(ssn);
|
||||||
cmd.alloc.win_size = cpu_to_le16(buf_size);
|
cmd.alloc.win_size = cpu_to_le16(buf_size);
|
||||||
|
@ -2829,7 +2832,7 @@ static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm,
|
||||||
BUILD_BUG_ON(sizeof(cmd.remove_v1) > sizeof(cmd.remove));
|
BUILD_BUG_ON(sizeof(cmd.remove_v1) > sizeof(cmd.remove));
|
||||||
} else {
|
} else {
|
||||||
cmd.remove.sta_id_mask =
|
cmd.remove.sta_id_mask =
|
||||||
cpu_to_le32(BIT(mvm_sta->deflink.sta_id));
|
cpu_to_le32(iwl_mvm_sta_fw_id_mask(mvm, sta, -1));
|
||||||
cmd.remove.tid = cpu_to_le32(tid);
|
cmd.remove.tid = cpu_to_le32(tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2852,16 +2855,16 @@ static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm,
|
||||||
return baid;
|
return baid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iwl_mvm_fw_baid_op(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvm_sta,
|
static int iwl_mvm_fw_baid_op(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||||
bool start, int tid, u16 ssn, u16 buf_size,
|
bool start, int tid, u16 ssn, u16 buf_size,
|
||||||
int baid)
|
int baid)
|
||||||
{
|
{
|
||||||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||||
IWL_UCODE_TLV_CAPA_BAID_ML_SUPPORT))
|
IWL_UCODE_TLV_CAPA_BAID_ML_SUPPORT))
|
||||||
return iwl_mvm_fw_baid_op_cmd(mvm, mvm_sta, start,
|
return iwl_mvm_fw_baid_op_cmd(mvm, sta, start,
|
||||||
tid, ssn, buf_size, baid);
|
tid, ssn, buf_size, baid);
|
||||||
|
|
||||||
return iwl_mvm_fw_baid_op_sta(mvm, mvm_sta, start,
|
return iwl_mvm_fw_baid_op_sta(mvm, sta, start,
|
||||||
tid, ssn, buf_size);
|
tid, ssn, buf_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2931,7 +2934,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||||
|
|
||||||
/* Don't send command to remove (start=0) BAID during restart */
|
/* Don't send command to remove (start=0) BAID during restart */
|
||||||
if (start || !test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
|
if (start || !test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
|
||||||
baid = iwl_mvm_fw_baid_op(mvm, mvm_sta, start, tid, ssn, buf_size,
|
baid = iwl_mvm_fw_baid_op(mvm, sta, start, tid, ssn, buf_size,
|
||||||
baid);
|
baid);
|
||||||
|
|
||||||
if (baid < 0) {
|
if (baid < 0) {
|
||||||
|
@ -2953,7 +2956,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||||
iwl_mvm_rx_agg_session_expired, 0);
|
iwl_mvm_rx_agg_session_expired, 0);
|
||||||
baid_data->mvm = mvm;
|
baid_data->mvm = mvm;
|
||||||
baid_data->tid = tid;
|
baid_data->tid = tid;
|
||||||
baid_data->sta_id = mvm_sta->deflink.sta_id;
|
baid_data->sta_mask = iwl_mvm_sta_fw_id_mask(mvm, sta, -1);
|
||||||
|
|
||||||
mvm_sta->tid_to_baid[tid] = baid;
|
mvm_sta->tid_to_baid[tid] = baid;
|
||||||
if (timeout)
|
if (timeout)
|
||||||
|
|
Loading…
Reference in New Issue