| From 651d207a15f2bc281edf3c92236b88853fc41006 Mon Sep 17 00:00:00 2001 |
| From: Peter Chiu <chui-hao.chiu@mediatek.com> |
| Date: Wed, 8 Nov 2023 10:17:10 +0800 |
| Subject: [PATCH 05/23] mtk: wifi: mt76: mt7996: fix some twt issues |
| |
| 1. Reject twt flows with the same parameters to prevent potential issues |
| causing by duplicated establishment. |
| 2. mt7996 can support 16 twt stations so modify the table_mask to u16. |
| 3. The minimum twt duration supported by mt7996 is 64 according to hardware |
| design. Reply station with TWT_SETUP_CMD_DICTATE if the min_twt_dur smaller |
| than 64. |
| 4. Fix possible unaligned pointer. |
| 5. Remove TWT_CONTROL_WAKE_DUR_UNIT flag because mt7996 does not support it. |
| |
| --- |
| mt7996/mac.c | 53 +++++++++++++++++++++++++++++++++++++++++-------- |
| mt7996/mt7996.h | 3 ++- |
| 2 files changed, 47 insertions(+), 9 deletions(-) |
| |
| diff --git a/mt7996/mac.c b/mt7996/mac.c |
| index ff7e0753..e6583427 100644 |
| --- a/mt7996/mac.c |
| +++ b/mt7996/mac.c |
| @@ -2534,6 +2534,34 @@ static int mt7996_mac_check_twt_req(struct ieee80211_twt_setup *twt) |
| return 0; |
| } |
| |
| +static bool |
| +mt7996_mac_twt_param_equal(struct mt7996_sta *msta, |
| + struct ieee80211_twt_params *twt_agrt) |
| +{ |
| + u16 type = le16_to_cpu(twt_agrt->req_type); |
| + u8 exp; |
| + int i; |
| + |
| + exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, type); |
| + for (i = 0; i < MT7996_MAX_STA_TWT_AGRT; i++) { |
| + struct mt7996_twt_flow *f; |
| + |
| + if (!(msta->twt.flowid_mask & BIT(i))) |
| + continue; |
| + |
| + f = &msta->twt.flow[i]; |
| + if (f->duration == twt_agrt->min_twt_dur && |
| + f->mantissa == twt_agrt->mantissa && |
| + f->exp == exp && |
| + f->protection == !!(type & IEEE80211_TWT_REQTYPE_PROTECTION) && |
| + f->flowtype == !!(type & IEEE80211_TWT_REQTYPE_FLOWTYPE) && |
| + f->trigger == !!(type & IEEE80211_TWT_REQTYPE_TRIGGER)) |
| + return true; |
| + } |
| + |
| + return false; |
| +} |
| + |
| void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, |
| struct ieee80211_sta *sta, |
| struct ieee80211_twt_setup *twt) |
| @@ -2545,8 +2573,7 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, |
| enum ieee80211_twt_setup_cmd sta_setup_cmd; |
| struct mt7996_dev *dev = mt7996_hw_dev(hw); |
| struct mt7996_twt_flow *flow; |
| - int flowid, table_id; |
| - u8 exp; |
| + u8 flowid, table_id, exp; |
| |
| if (mt7996_mac_check_twt_req(twt)) |
| goto out; |
| @@ -2559,9 +2586,19 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, |
| if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow)) |
| goto unlock; |
| |
| + if (twt_agrt->min_twt_dur < MT7996_MIN_TWT_DUR) { |
| + setup_cmd = TWT_SETUP_CMD_DICTATE; |
| + twt_agrt->min_twt_dur = MT7996_MIN_TWT_DUR; |
| + goto unlock; |
| + } |
| + |
| + if (mt7996_mac_twt_param_equal(msta, twt_agrt)) |
| + goto unlock; |
| + |
| flowid = ffs(~msta->twt.flowid_mask) - 1; |
| - le16p_replace_bits(&twt_agrt->req_type, flowid, |
| - IEEE80211_TWT_REQTYPE_FLOWID); |
| + twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_FLOWID); |
| + twt_agrt->req_type |= le16_encode_bits(flowid, |
| + IEEE80211_TWT_REQTYPE_FLOWID); |
| |
| table_id = ffs(~dev->twt.table_mask) - 1; |
| exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type); |
| @@ -2608,10 +2645,10 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, |
| unlock: |
| mutex_unlock(&dev->mt76.mutex); |
| out: |
| - le16p_replace_bits(&twt_agrt->req_type, setup_cmd, |
| - IEEE80211_TWT_REQTYPE_SETUP_CMD); |
| - twt->control = (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT) | |
| - (twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED); |
| + twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_SETUP_CMD); |
| + twt_agrt->req_type |= |
| + le16_encode_bits(setup_cmd, IEEE80211_TWT_REQTYPE_SETUP_CMD); |
| + twt->control = twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED; |
| } |
| |
| void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev, |
| diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h |
| index bc73bcb4..8154ad37 100644 |
| --- a/mt7996/mt7996.h |
| +++ b/mt7996/mt7996.h |
| @@ -53,6 +53,7 @@ |
| |
| #define MT7996_MAX_TWT_AGRT 16 |
| #define MT7996_MAX_STA_TWT_AGRT 8 |
| +#define MT7996_MIN_TWT_DUR 64 |
| #define MT7996_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 3) |
| |
| /* NOTE: used to map mt76_rates. idx may change if firmware expands table */ |
| @@ -320,7 +321,7 @@ struct mt7996_dev { |
| struct rchan *relay_fwlog; |
| |
| struct { |
| - u8 table_mask; |
| + u16 table_mask; |
| u8 n_agrt; |
| } twt; |
| |
| -- |
| 2.18.0 |
| |