developer | d243af0 | 2023-12-21 14:49:33 +0800 | [diff] [blame^] | 1 | From 651d207a15f2bc281edf3c92236b88853fc41006 Mon Sep 17 00:00:00 2001 |
| 2 | From: Peter Chiu <chui-hao.chiu@mediatek.com> |
| 3 | Date: Wed, 8 Nov 2023 10:17:10 +0800 |
| 4 | Subject: [PATCH 05/23] mtk: wifi: mt76: mt7996: fix some twt issues |
| 5 | |
| 6 | 1. Reject twt flows with the same parameters to prevent potential issues |
| 7 | causing by duplicated establishment. |
| 8 | 2. mt7996 can support 16 twt stations so modify the table_mask to u16. |
| 9 | 3. The minimum twt duration supported by mt7996 is 64 according to hardware |
| 10 | design. Reply station with TWT_SETUP_CMD_DICTATE if the min_twt_dur smaller |
| 11 | than 64. |
| 12 | 4. Fix possible unaligned pointer. |
| 13 | 5. Remove TWT_CONTROL_WAKE_DUR_UNIT flag because mt7996 does not support it. |
| 14 | |
| 15 | --- |
| 16 | mt7996/mac.c | 53 +++++++++++++++++++++++++++++++++++++++++-------- |
| 17 | mt7996/mt7996.h | 3 ++- |
| 18 | 2 files changed, 47 insertions(+), 9 deletions(-) |
| 19 | |
| 20 | diff --git a/mt7996/mac.c b/mt7996/mac.c |
| 21 | index ff7e0753..e6583427 100644 |
| 22 | --- a/mt7996/mac.c |
| 23 | +++ b/mt7996/mac.c |
| 24 | @@ -2534,6 +2534,34 @@ static int mt7996_mac_check_twt_req(struct ieee80211_twt_setup *twt) |
| 25 | return 0; |
| 26 | } |
| 27 | |
| 28 | +static bool |
| 29 | +mt7996_mac_twt_param_equal(struct mt7996_sta *msta, |
| 30 | + struct ieee80211_twt_params *twt_agrt) |
| 31 | +{ |
| 32 | + u16 type = le16_to_cpu(twt_agrt->req_type); |
| 33 | + u8 exp; |
| 34 | + int i; |
| 35 | + |
| 36 | + exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, type); |
| 37 | + for (i = 0; i < MT7996_MAX_STA_TWT_AGRT; i++) { |
| 38 | + struct mt7996_twt_flow *f; |
| 39 | + |
| 40 | + if (!(msta->twt.flowid_mask & BIT(i))) |
| 41 | + continue; |
| 42 | + |
| 43 | + f = &msta->twt.flow[i]; |
| 44 | + if (f->duration == twt_agrt->min_twt_dur && |
| 45 | + f->mantissa == twt_agrt->mantissa && |
| 46 | + f->exp == exp && |
| 47 | + f->protection == !!(type & IEEE80211_TWT_REQTYPE_PROTECTION) && |
| 48 | + f->flowtype == !!(type & IEEE80211_TWT_REQTYPE_FLOWTYPE) && |
| 49 | + f->trigger == !!(type & IEEE80211_TWT_REQTYPE_TRIGGER)) |
| 50 | + return true; |
| 51 | + } |
| 52 | + |
| 53 | + return false; |
| 54 | +} |
| 55 | + |
| 56 | void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, |
| 57 | struct ieee80211_sta *sta, |
| 58 | struct ieee80211_twt_setup *twt) |
| 59 | @@ -2545,8 +2573,7 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, |
| 60 | enum ieee80211_twt_setup_cmd sta_setup_cmd; |
| 61 | struct mt7996_dev *dev = mt7996_hw_dev(hw); |
| 62 | struct mt7996_twt_flow *flow; |
| 63 | - int flowid, table_id; |
| 64 | - u8 exp; |
| 65 | + u8 flowid, table_id, exp; |
| 66 | |
| 67 | if (mt7996_mac_check_twt_req(twt)) |
| 68 | goto out; |
| 69 | @@ -2559,9 +2586,19 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, |
| 70 | if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow)) |
| 71 | goto unlock; |
| 72 | |
| 73 | + if (twt_agrt->min_twt_dur < MT7996_MIN_TWT_DUR) { |
| 74 | + setup_cmd = TWT_SETUP_CMD_DICTATE; |
| 75 | + twt_agrt->min_twt_dur = MT7996_MIN_TWT_DUR; |
| 76 | + goto unlock; |
| 77 | + } |
| 78 | + |
| 79 | + if (mt7996_mac_twt_param_equal(msta, twt_agrt)) |
| 80 | + goto unlock; |
| 81 | + |
| 82 | flowid = ffs(~msta->twt.flowid_mask) - 1; |
| 83 | - le16p_replace_bits(&twt_agrt->req_type, flowid, |
| 84 | - IEEE80211_TWT_REQTYPE_FLOWID); |
| 85 | + twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_FLOWID); |
| 86 | + twt_agrt->req_type |= le16_encode_bits(flowid, |
| 87 | + IEEE80211_TWT_REQTYPE_FLOWID); |
| 88 | |
| 89 | table_id = ffs(~dev->twt.table_mask) - 1; |
| 90 | exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type); |
| 91 | @@ -2608,10 +2645,10 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, |
| 92 | unlock: |
| 93 | mutex_unlock(&dev->mt76.mutex); |
| 94 | out: |
| 95 | - le16p_replace_bits(&twt_agrt->req_type, setup_cmd, |
| 96 | - IEEE80211_TWT_REQTYPE_SETUP_CMD); |
| 97 | - twt->control = (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT) | |
| 98 | - (twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED); |
| 99 | + twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_SETUP_CMD); |
| 100 | + twt_agrt->req_type |= |
| 101 | + le16_encode_bits(setup_cmd, IEEE80211_TWT_REQTYPE_SETUP_CMD); |
| 102 | + twt->control = twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED; |
| 103 | } |
| 104 | |
| 105 | void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev, |
| 106 | diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h |
| 107 | index bc73bcb4..8154ad37 100644 |
| 108 | --- a/mt7996/mt7996.h |
| 109 | +++ b/mt7996/mt7996.h |
| 110 | @@ -53,6 +53,7 @@ |
| 111 | |
| 112 | #define MT7996_MAX_TWT_AGRT 16 |
| 113 | #define MT7996_MAX_STA_TWT_AGRT 8 |
| 114 | +#define MT7996_MIN_TWT_DUR 64 |
| 115 | #define MT7996_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 3) |
| 116 | |
| 117 | /* NOTE: used to map mt76_rates. idx may change if firmware expands table */ |
| 118 | @@ -320,7 +321,7 @@ struct mt7996_dev { |
| 119 | struct rchan *relay_fwlog; |
| 120 | |
| 121 | struct { |
| 122 | - u8 table_mask; |
| 123 | + u16 table_mask; |
| 124 | u8 n_agrt; |
| 125 | } twt; |
| 126 | |
| 127 | -- |
| 128 | 2.18.0 |
| 129 | |