introduce individual TWT support in AP mode
Subsystems (4)
Lorenzo Bianconi
maintainerv2 cover introduce individual TWT support in AP mode
Introduce TWT action frames parsing support to mac80211. Currently just individual TWT agreement are support in AP mode. Whenever the AP receives a TWT action frame from an associated client, after performing sanity checks, it will notify the underlay driver with requested parameters in order to check if they are supported and if there is enough room for a new agreement. The hw is expected to set agreement result and report it to mac80211.
The two following drv callbacks have been added to mac80211:
- add_twt_setup (mandatory)
- twt_teardown_request (optional)
mac80211 will send an action frame reply according to the result reported by the driver/fw.
Add individual TWT support to mt7915 in AP mode.
Changes since v1:
- fix rcu unbalance in mt7915/debugfs.c
Changes since rfc:
- run ieee80211_s1g_status_h_twt only for failed twt action frames
- change add_twt_setup return value from int to void
Lorenzo Bianconi (7):
mac80211: add twt ie in ieee80211_mgmt structure
mac80211: introduce individual TWT support in AP mode.
mt76: mt7915: introduce __mt7915_get_tsf routine
mt76: mt7915: introduce mt7915_mcu_twt_agrt_update mcu command
mt76: mt7915: introduce mt7915_mac_add_twt_setup routine
mt76: mt7915: enable twt responder capability
mt76: mt7915: add twt_stats knob in debugfs
.../wireless/mediatek/mt76/mt7915/debugfs.c | 28 +++ .../net/wireless/mediatek/mt76/mt7915/init.c | 3 + .../net/wireless/mediatek/mt76/mt7915/mac.c | 185 ++++++++++++++++ .../net/wireless/mediatek/mt76/mt7915/main.c | 39 +++- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 50 +++++ .../net/wireless/mediatek/mt76/mt7915/mcu.h | 9 + .../wireless/mediatek/mt76/mt7915/mt7915.h | 39 +++- include/linux/ieee80211.h | 67 ++++++ include/net/mac80211.h | 13 ++ net/mac80211/driver-ops.h | 24 +++ net/mac80211/ieee80211_i.h | 5 + net/mac80211/iface.c | 13 ++ net/mac80211/rx.c | 54 +++++ net/mac80211/s1g.c | 198 ++++++++++++++++++ net/mac80211/status.c | 34 ++- 15 files changed, 754 insertions(+), 7 deletions(-)
Signature · 1 line
2.31.1
Lorenzo Bianconi
maintainerPATCH v2 1/7 mac80211: add twt ie in ieee80211_mgmt structure
Introduce TWT definitions and TWT Information element structure in ieee80211.h
--- include/linux/ieee80211.h | 67 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+)
include/linux/ieee80211.h +67 -0
@@ -1088,6 +1088,53 @@ struct ieee80211_ext { } u; } __packed__aligned(2) ; +#define IEEE80211_TWT_CONTROL_NDP BIT(0) +#define IEEE80211_TWT_CONTROL_RESP_MODE BIT(1) +#define IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST BIT(2) +#define IEEE80211_TWT_CONTROL_RX_DISABLED BIT(4) +#define IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT BIT(5) + +#define IEEE80211_TWT_REQTYPE_REQUEST BIT(0) +#define IEEE80211_TWT_REQTYPE_SETUP_CMD GENMASK(3, 1) +#define IEEE80211_TWT_REQTYPE_TRIGGER BIT(4) +#define IEEE80211_TWT_REQTYPE_IMPLICIT BIT(5) +#define IEEE80211_TWT_REQTYPE_FLOWTYPE BIT(6) +#define IEEE80211_TWT_REQTYPE_FLOWID GENMASK(9, 7) +#define IEEE80211_TWT_REQTYPE_WAKE_INT_EXP GENMASK(14, 10) +#define IEEE80211_TWT_REQTYPE_PROTECTION BIT(15) + +enum ieee80211_twt_setup_cmd { +TWT_SETUP_CMD_REQUEST , +TWT_SETUP_CMD_SUGGEST , +TWT_SETUP_CMD_DEMAND , +TWT_SETUP_CMD_GROUPING , +TWT_SETUP_CMD_ACCEPT , +TWT_SETUP_CMD_ALTERNATE , +TWT_SETUP_CMD_DICTATE , +TWT_SETUP_CMD_REJECT , +}; + +struct ieee80211_twt_params { +u8 control; +__le16 req_type; +__le64 twt; +u8 min_twt_dur; +__le16 mantissa; +u8 channel; +} __packed; + +struct ieee80211_twt_setup { +u8 dialog_token; +u8 element_id; +u8 length; +u8 params[0 ]; +} __packed; + +#define IEEE80211_TWT_IND_SETUP_SIZE \ + (IEEE80211_MIN_ACTION_SIZE + 1 + \ + sizeof(struct ieee80211_twt_setup) + \ + sizeof(struct ieee80211_twt_params)) +struct ieee80211_mgmt {__le16 frame_control;__le16 duration;
@@ -1252,6 +1299,10 @@ struct ieee80211_mgmt {__le16 toa_error;u8 variable[0 ]; }__packed ftm; +struct { +u8 action_code; +u8 variable[0 ]; + } __packed s1g; } u; }__packed action; } u;
@@ -2881,6 +2932,7 @@ enum ieee80211_eid {WLAN_EID_AID_RESPONSE =211 ,WLAN_EID_S1G_BCN_COMPAT =213 ,WLAN_EID_S1G_SHORT_BCN_INTERVAL =214 , +WLAN_EID_S1G_TWT =216 ,WLAN_EID_S1G_CAPABILITIES =217 ,WLAN_EID_VENDOR_SPECIFIC =221 , WLAN_EID_QOS_PARAMETER = 222,
@@ -2950,6 +3002,7 @@ enum ieee80211_category {WLAN_CATEGORY_FST =18 ,WLAN_CATEGORY_UNPROT_DMG =20 ,WLAN_CATEGORY_VHT =21 , +WLAN_CATEGORY_S1G =22 ,WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED =126 , WLAN_CATEGORY_VENDOR_SPECIFIC = 127, };
@@ -3023,6 +3076,20 @@ enum ieee80211_key_len { WLAN_KEY_LEN_BIP_GMAC_256 = 32, }; +enum ieee80211_s1g_actioncode { +WLAN_S1G_AID_SWITCH_REQUEST , +WLAN_S1G_AID_SWITCH_RESPONSE , +WLAN_S1G_SYNC_CONTROL , +WLAN_S1G_STA_INFO_ANNOUNCE , +WLAN_S1G_EDCA_PARAM_SET , +WLAN_S1G_EL_OPERATION , +WLAN_S1G_TWT_SETUP , +WLAN_S1G_TWT_TEARDOWN , +WLAN_S1G_SECT_GROUP_ID_LIST , +WLAN_S1G_SECT_ID_FEEDBACK , +WLAN_S1G_TWT_INFORMATION =11 , +}; +#define IEEE80211_WEP_IV_LEN 4#define IEEE80211_WEP_ICV_LEN 4#define IEEE80211_CCMP_HDR_LEN 8
Signature · 1 line
2.31.1
Lorenzo Bianconi
maintainerPATCH v2 2/7 mac80211: introduce individual TWT support in AP mode.
In reply to Lorenzo BianconiIntroduce TWT action frames parsing support to mac80211. Currently just individual TWT agreement are support in AP mode. Whenever the AP receives a TWT action frame from an associated client, after performing sanity checks, it will notify the underlay driver with requested parameters in order to check if they are supported and if there is enough room for a new agreement. The hw is expected to set agreement result and report it to mac80211.
The two following drv callbacks have been added to mac80211:
- add_twt_setup (mandatory)
- twt_teardown_request (optional)
mac80211 will send an action frame reply according to the result reported by the driver/fw.
--- include/net/mac80211.h | 13 +++ net/mac80211/driver-ops.h | 24 +++++ net/mac80211/ieee80211_i.h | 5 + net/mac80211/iface.c | 13 +++ net/mac80211/rx.c | 54 ++++++++++ net/mac80211/s1g.c | 198 +++++++++++++++++++++++++++++++++++++ net/mac80211/status.c | 34 ++++++- 7 files changed, 340 insertions(+), 1 deletion(-)
include/net/mac80211.h +13 -0
@@ -3919,6 +3919,13 @@ struct ieee80211_prep_tx_info {* @set_sar_specs: Update the SAR (TX power) settings. * @sta_set_decap_offload: Called to notify the driver when a station is allowed * to use rx decapsulation offload +* @add_twt_setup: Update hw with TWT agreement parameters received from the peer. +* This callback allows the hw to check if requested parameters +* are supported and if there is enough room for a new agreement. +* The hw is expected to set agreement result in the req_type field of +* agrt_resp structure. +* @twt_teardown_request: Update the hw with TWT teardown request received +* from the peer. */ struct ieee80211_ops { void (*tx)(struct ieee80211_hw *hw,
@@ -4242,6 +4249,12 @@ struct ieee80211_ops {void (*sta_set_decap_offload)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_sta *sta,bool enabled); +void (*add_twt_setup)(struct ieee80211_hw *hw, +struct ieee80211_sta *sta, +struct ieee80211_twt_params *agrt_req, +struct ieee80211_twt_params *agrt_resp); +void (*twt_teardown_request)(struct ieee80211_hw *hw, +struct ieee80211_sta *sta,u8 flowid); };/**
net/mac80211/driver-ops.h +24 -0
@@ -1447,4 +1447,28 @@ static inline void drv_sta_set_decap_offload(struct ieee80211_local *local, trace_drv_return_void(local); } +static inline void drv_add_twt_setup (struct ieee80211_local *local, +struct ieee80211_sub_if_data *sdata, +struct ieee80211_sta *sta, +struct ieee80211_twt_params *agrt_req, +struct ieee80211_twt_params *agrt_resp) +{ +might_sleep (); +check_sdata_in_driver (sdata); + + local->ops->add_twt_setup (&local->hw, sta, agrt_req, agrt_resp); +} + +static inline void drv_twt_teardown_request (struct ieee80211_local *local, +struct ieee80211_sub_if_data *sdata, +struct ieee80211_sta *sta, +u8 flowid) +{ +might_sleep (); +check_sdata_in_driver (sdata); + +if (local->ops->twt_teardown_request) + local->ops->twt_teardown_request (&local->hw, sta, flowid); +} +#endif /* __MAC80211_DRIVER_OPS */
net/mac80211/ieee80211_i.h +5 -0
@@ -2068,6 +2068,11 @@ ieee80211_he_op_ie_to_bss_conf(struct ieee80211_vif *vif,/* S1G */ void ieee80211_s1g_sta_rate_init (struct sta_info *sta); +bool ieee80211_s1g_is_twt_setup (struct sk_buff *skb); +void ieee80211_s1g_rx_h_twt (struct ieee80211_sub_if_data *sdata, +struct sk_buff *skb); +void ieee80211_s1g_status_h_twt (struct ieee80211_sub_if_data *sdata, +struct sk_buff *skb);/* Spectrum management */ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
net/mac80211/iface.c +13 -0
@@ -1381,6 +1381,19 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,WARN_ON (1 );break ; } + }else if (ieee80211_is_action (mgmt->frame_control) && + mgmt->u.action.category ==WLAN_CATEGORY_S1G ) { +switch (mgmt->u.action.u.s1g.action_code) { +case WLAN_S1G_TWT_TEARDOWN : +case WLAN_S1G_TWT_SETUP : +if (skb->pkt_type ==IEEE80211_TX_STATUS_MSG ) +ieee80211_s1g_status_h_twt (sdata, skb); +else +ieee80211_s1g_rx_h_twt (sdata, skb); +break ; +default : +break ; + } }else if (ieee80211_is_ext (mgmt->frame_control)) {if (sdata->vif.type ==NL80211_IFTYPE_STATION )ieee80211_sta_rx_queued_ext (sdata, skb);
net/mac80211/rx.c +54 -0
66 lines not on this page · raw message
net/mac80211/s1g.c +198 -0
207 lines not on this page · raw message
net/mac80211/status.c +33 -1
@@ -17,6 +17,33 @@#include "led.h" #include "wme.h" +static struct sk_buff * +ieee80211_tx_queue_skb (struct ieee80211_hw *hw, +struct ieee80211_tx_status *status, +bool monitor) +{ +struct ieee80211_tx_info *info =IEEE80211_SKB_CB (status->skb); +struct sk_buff *skb = status->skb; +struct sta_info *sta; + +if (!status->sta) + goto out; + +if (likely (!ieee80211_s1g_is_twt_setup (skb))) + goto out; + +if (info->flags &IEEE80211_TX_STAT_ACK ) + goto out;/* nothing to do */ + + sta = container_of(status->sta, struct sta_info, sta); + skb->pkt_type =IEEE80211_TX_STATUS_MSG ; +skb_queue_tail (&sta->sdata->skb_queue, skb); + skb = monitor ?skb_clone (skb,GFP_ATOMIC ) :NULL ; +ieee80211_queue_work (hw, &sta->sdata->work); + +out: +return skb; +}void ieee80211_tx_status_irqsafe (struct ieee80211_hw *hw,struct sk_buff *skb)
@@ -1046,13 +1073,18 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,* with this test... */ if (!local->monitors && (!send_to_cooked || !local->cooked_mntrs)) { -if (status->free_list) + skb =ieee80211_tx_queue_skb (hw, status, false); +if (skb && status->free_list)list_add_tail (&skb->list, status->free_list);else dev_kfree_skb (skb);return ; } + skb =ieee80211_tx_queue_skb (hw, status, true); +if (!skb) +return ; +/* send to monitor interfaces */ ieee80211_tx_monitor (local, skb, sband, retry_count, shift, send_to_cooked, status);
Signature · 1 line
2.31.1
Lorenzo Bianconi
maintainerPATCH v2 3/7 mt76: mt7915: introduce __mt7915_get_tsf routine
In reply to Lorenzo BianconiIntroduce an unlocked verion of mt7915_get_tsf routine. This is a preliminary patch to add TWT support to mt7915.
--- .../net/wireless/mediatek/mt76/mt7915/main.c | 20 ++++++++++++++----- .../wireless/mediatek/mt76/mt7915/mt7915.h | 2 +- 2 files changed, 16 insertions(+), 6 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7915/main.c +15 -5
@@ -789,10 +789,8 @@ mt7915_get_stats(struct ieee80211_hw *hw,return 0 ; } -static u64 -mt7915_get_tsf (struct ieee80211_hw *hw,struct ieee80211_vif *vif) +u64 __mt7915_get_tsf (struct ieee80211_hw *hw,struct mt7915_vif *mvif) { -struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;struct mt7915_dev *dev =mt7915_hw_dev (hw);struct mt7915_phy *phy =mt7915_hw_phy (hw);bool band = phy != &dev->phy;
@@ -802,7 +800,7 @@ mt7915_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) } tsf;u16 n; -mutex_lock (&dev->mt76.mutex); +lockdep_assert_held (&dev->mt76.mutex); n = mvif->omac_idx >HW_BSSID_MAX ?HW_BSSID_0 : mvif->omac_idx;/* TSF software read */
@@ -811,9 +809,21 @@ mt7915_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) tsf.t32[0 ] =mt76_rr (dev,MT_LPON_UTTR0 (band)); tsf.t32[1 ] =mt76_rr (dev,MT_LPON_UTTR1 (band)); +return tsf.t64; +} + +static u64 +mt7915_get_tsf (struct ieee80211_hw *hw,struct ieee80211_vif *vif) +{ +struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; +struct mt7915_dev *dev =mt7915_hw_dev (hw); +u64 ret; + +mutex_lock (&dev->mt76.mutex); + ret =__mt7915_get_tsf (hw, mvif);mutex_unlock (&dev->mt76.mutex); -return tsf.t64; +return ret; } static void
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +1 -1
@@ -271,7 +271,7 @@ extern const struct ieee80211_ops mt7915_ops;extern const struct mt76_testmode_ops mt7915_testmode_ops;u32 mt7915_reg_map (struct mt7915_dev *dev,u32 addr); - +u64 __mt7915_get_tsf (struct ieee80211_hw *hw,struct mt7915_vif *mvif);int mt7915_register_device (struct mt7915_dev *dev);void mt7915_unregister_device (struct mt7915_dev *dev);int mt7915_eeprom_init (struct mt7915_dev *dev);
Signature · 1 line
2.31.1
Lorenzo Bianconi
maintainerPATCH v2 4/7 mt76: mt7915: introduce mt7915_mcu_twt_agrt_update mcu command
In reply to Lorenzo BianconiThis is a preliminary patch to add TWT support to mt7915
--- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 50 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7915/mcu.h | 9 ++++ .../wireless/mediatek/mt76/mt7915/mt7915.h | 19 +++++++ 3 files changed, 78 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +50 -0
@@ -3904,3 +3904,53 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,return ret; } + +#define TWT_AGRT_TRIGGER BIT(0) +#define TWT_AGRT_ANNOUNCE BIT(1) +#define TWT_AGRT_PROTECT BIT(2) + +int mt7915_mcu_twt_agrt_update (struct mt7915_dev *dev, +struct mt7915_vif *mvif, +struct mt7915_twt_flow *flow, +int cmd) +{ +struct { +u8 tbl_idx; +u8 cmd; +u8 own_mac_idx; +u8 flowid;/* 0xff for group id */ +__le16 peer_id;/* specify the peer_id (msb=0) +* or group_id (msb=1) +*/ +u8 duration;/* 256 us */ +u8 bss_idx; +__le64 start_tsf; +__le16 mantissa; +u8 exponent; +u8 is_ap; +u8 agrt_params; +u8 rsv[23 ]; + } __packed req = { + .tbl_idx = flow->id, + .cmd = cmd, + .own_mac_idx = mvif->omac_idx, + .flowid = flow->id, + .peer_id =cpu_to_le16 (flow->wcid), + .duration = flow->duration, + .bss_idx = mvif->idx, + .start_tsf =cpu_to_le64 (flow->tsf), + .mantissa = flow->mantissa, + .exponent = flow->exp, + .is_ap = true, + }; + +if (flow->protection) + req.agrt_params |=TWT_AGRT_PROTECT ; +if (!flow->flowtype) + req.agrt_params |=TWT_AGRT_ANNOUNCE ; +if (flow->trigger) + req.agrt_params |=TWT_AGRT_TRIGGER ; + +return mt76_mcu_send_msg (&dev->mt76,MCU_EXT_CMD (TWT_AGRT_UPDATE ), + &req,sizeof (req), true); +}
drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +9 -0
@@ -276,6 +276,7 @@ enum {MCU_EXT_CMD_MWDS_SUPPORT =0x80 ,MCU_EXT_CMD_SET_SER_TRIGGER =0x81 ,MCU_EXT_CMD_SCS_CTRL =0x82 , +MCU_EXT_CMD_TWT_AGRT_UPDATE =0x94 ,MCU_EXT_CMD_FW_DBG_CTRL =0x95 ,MCU_EXT_CMD_SET_RDD_TH =0x9d , MCU_EXT_CMD_SET_SPR = 0xa8,
@@ -284,6 +285,14 @@ enum { MCU_EXT_CMD_PHY_STAT_INFO = 0xad, }; +enum { +MCU_TWT_AGRT_ADD , +MCU_TWT_AGRT_MODIFY , +MCU_TWT_AGRT_DELETE , +MCU_TWT_AGRT_TEARDOWN , +MCU_TWT_AGRT_GET_TSF , +}; +enum {MCU_WA_PARAM_CMD_QUERY ,MCU_WA_PARAM_CMD_SET ,
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +19 -0
@@ -67,6 +67,21 @@ struct mt7915_sta_key_conf {u8 key[16 ]; }; +struct mt7915_twt_flow { +struct list_head list; +u64 start_tsf; +u64 tsf; +u32 duration; +u16 wcid; +__le16 mantissa; +u8 exp; +u8 id; +u8 protection:1 ; +u8 flowtype:1 ; +u8 trigger:1 ; +u8 sched:1 ; +}; +struct mt7915_sta {struct mt76_wcid wcid;/* must be first */
@@ -284,6 +299,10 @@ int mt7915_dma_init(struct mt7915_dev *dev);void mt7915_dma_prefetch (struct mt7915_dev *dev);void mt7915_dma_cleanup (struct mt7915_dev *dev);int mt7915_mcu_init (struct mt7915_dev *dev); +int mt7915_mcu_twt_agrt_update (struct mt7915_dev *dev, +struct mt7915_vif *mvif, +struct mt7915_twt_flow *flow, +int cmd);int mt7915_mcu_add_dev_info (struct mt7915_phy *phy,struct ieee80211_vif *vif,bool enable); int mt7915_mcu_add_bss_info(struct mt7915_phy *phy,
Signature · 1 line
2.31.1
Lorenzo Bianconi
maintainerPATCH v2 5/7 mt76: mt7915: introduce mt7915_mac_add_twt_setup routine
In reply to Lorenzo BianconiIntroduce individual TWT support to mt7915 in AP mode. Implement the two following mac80211 callbacks:
- add_twt_setup
- twt_teardown_request
--- .../net/wireless/mediatek/mt76/mt7915/init.c | 1 + .../net/wireless/mediatek/mt76/mt7915/mac.c | 185 ++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7915/main.c | 19 ++ .../wireless/mediatek/mt76/mt7915/mt7915.h | 18 ++ 4 files changed, 223 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7915/init.c +1 -0
@@ -790,6 +790,7 @@ int mt7915_register_device(struct mt7915_dev *dev)INIT_DELAYED_WORK (&dev->mphy.mac_work, mt7915_mac_work);INIT_LIST_HEAD (&dev->sta_rc_list);INIT_LIST_HEAD (&dev->sta_poll_list); +INIT_LIST_HEAD (&dev->twt_list);spin_lock_init (&dev->sta_poll_lock);init_waitqueue_head (&dev->reset_wait);
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +185 -0
194 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7915/main.c +19 -0
@@ -640,6 +640,7 @@ void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, { struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; +int i;mt7915_mcu_add_sta_adv (dev, vif, sta, false);mt7915_mcu_add_sta (dev, vif, sta, false);
@@ -647,6 +648,9 @@ void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,mt7915_mac_wtbl_update (dev, msta->wcid.idx,MT_WTBL_UPDATE_ADM_COUNT_CLEAR ); +for (i =0 ; i <ARRAY_SIZE (msta->twt.flow); i++) +mt7915_mac_twt_teardown_flow (dev, msta, i); +spin_lock_bh (&dev->sta_poll_lock);if (!list_empty (&msta->poll_list))list_del_init (&msta->poll_list);
@@ -1038,6 +1042,19 @@ static void mt7915_sta_set_decap_offload(struct ieee80211_hw *hw,mt7915_mcu_sta_update_hdr_trans (dev, vif, sta); } +static void +mt7915_twt_teardown_request (struct ieee80211_hw *hw, +struct ieee80211_sta *sta, +u8 flowid) +{ +struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; +struct mt7915_dev *dev =mt7915_hw_dev (hw); + +mutex_lock (&dev->mt76.mutex); +mt7915_mac_twt_teardown_flow (dev, msta, flowid); +mutex_unlock (&dev->mt76.mutex); +} +const struct ieee80211_ops mt7915_ops = { .tx = mt7915_tx, .start = mt7915_start,
@@ -1073,6 +1090,8 @@ const struct ieee80211_ops mt7915_ops = { .sta_statistics = mt7915_sta_statistics, .sta_set_4addr = mt7915_sta_set_4addr, .sta_set_decap_offload = mt7915_sta_set_decap_offload, + .add_twt_setup = mt7915_mac_add_twt_setup, + .twt_teardown_request = mt7915_twt_teardown_request, CFG80211_TESTMODE_CMD(mt76_testmode_cmd) CFG80211_TESTMODE_DUMP(mt76_testmode_dump)#ifdef CONFIG_MAC80211_DEBUGFS
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +18 -0
@@ -41,6 +41,9 @@#define MT7915_SKU_RATE_NUM 161 +#define MT7915_MAX_TWT_AGRT 16 +#define MT7915_MAX_STA_TWT_AGRT 8 +struct mt7915_vif ;struct mt7915_sta ;struct mt7915_dfs_pulse ;
@@ -96,6 +99,11 @@ struct mt7915_sta {unsigned long ampdu_state;struct mt7915_sta_key_conf bip; + +struct { +u8 flowid_mask; +struct mt7915_twt_flow flow[MT7915_MAX_STA_TWT_AGRT ]; + } twt; };struct mt7915_vif {u16 idx;
@@ -192,6 +200,7 @@ struct mt7915_dev {struct list_head sta_rc_list;struct list_head sta_poll_list; +struct list_head twt_list;spinlock_t sta_poll_lock;u32 hw_pattern;
@@ -202,6 +211,8 @@ struct mt7915_dev {bool ibf;void *cal; + +u8 n_twt_agrt; };enum {
@@ -414,6 +425,13 @@ void mt7915_mac_work(struct work_struct *work);void mt7915_mac_reset_work (struct work_struct *work);void mt7915_mac_sta_rc_work (struct work_struct *work);int mt7915_mmio_init (struct mt76_dev *mdev,void __iomem *mem_base,int irq); +void mt7915_mac_twt_teardown_flow (struct mt7915_dev *dev, +struct mt7915_sta *msta, +u8 flowid); +void mt7915_mac_add_twt_setup (struct ieee80211_hw *hw, +struct ieee80211_sta *sta, +struct ieee80211_twt_params *agrt_req, +struct ieee80211_twt_params *agrt_resp); int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, struct ieee80211_sta *sta,
Signature · 1 line
2.31.1
Lorenzo Bianconi
maintainerPATCH v2 6/7 mt76: mt7915: enable twt responder capability
In reply to Lorenzo BianconiEnable TWT support in AP mode
--- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7915/init.c +2 -0
@@ -666,6 +666,8 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,switch (i) {case NL80211_IFTYPE_AP : + he_cap_elem->mac_cap_info[0 ] |= +IEEE80211_HE_MAC_CAP0_TWT_RES ; he_cap_elem->mac_cap_info[2 ] |=IEEE80211_HE_MAC_CAP2_BSR ; he_cap_elem->mac_cap_info[4] |=
Signature · 1 line
2.31.1
Lorenzo Bianconi
maintainerPATCH v2 7/7 mt76: mt7915: add twt_stats knob in debugfs
In reply to Lorenzo BianconiIntroduce twt_stats knob in debugfs in order to dump established agreements
--- .../wireless/mediatek/mt76/mt7915/debugfs.c | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +28 -0
@@ -335,6 +335,32 @@ mt7915_read_rate_txpower(struct seq_file *s, void *data)return 0 ; } +static int +mt7915_twt_stats (struct seq_file *s,void *data) +{ +struct mt7915_dev *dev =dev_get_drvdata (s->private); +struct mt7915_twt_flow *iter; + +rcu_read_lock (); + +seq_puts (s," wcid | id | flags | exp | mantissa" ); +seq_puts (s," | duration | tsf |\n" ); +list_for_each_entry_rcu (iter, &dev->twt_list, list) +seq_printf (s, +"%9d | %8d | %5c%c%c%c | %8d | %8d | %8d | %14lld |\n" , + iter->wcid, iter->id, + iter->sched ?'s' :'u' , + iter->protection ?'p' :'-' , + iter->trigger ?'t' :'-' , + iter->flowtype ?'-' :'a' , + iter->exp, iter->mantissa, + iter->duration, iter->tsf); + +rcu_read_unlock (); + +return 0 ; +} +int mt7915_init_debugfs (struct mt7915_dev *dev) {struct dentry *dir;
@@ -352,6 +378,8 @@ int mt7915_init_debugfs(struct mt7915_dev *dev)debugfs_create_file ("implicit_txbf" ,0600 , dir, dev, &fops_implicit_txbf);debugfs_create_u32 ("dfs_hw_pattern" ,0400 , dir, &dev->hw_pattern); +debugfs_create_devm_seqfile (dev->mt76.dev,"twt_stats" , dir, + mt7915_twt_stats);/* test knobs */ debugfs_create_file ("radar_trigger" ,0200 , dir, dev, &fops_radar_trigger);
Signature · 1 line
2.31.1
Johannes Berg
maintainerRe: [PATCH v2 mac80211-next 2/7] mac80211: introduce individual TWT support in AP mode.
In reply to Lorenzo BianconiQuoted 14 lines
net/mac80211/driver-ops.h +13
-0+static inline void drv_add_twt_setup (struct ieee80211_local *local, +struct ieee80211_sub_if_data *sdata, +struct ieee80211_sta *sta, +struct ieee80211_twt_params *agrt_req, +struct ieee80211_twt_params *agrt_resp) +{ +might_sleep (); +check_sdata_in_driver (sdata); + + local->ops->add_twt_setup (&local->hw, sta, agrt_req, agrt_resp); +} + +static inline void drv_twt_teardown_request(struct ieee80211_local *local,
net/mac80211/driver-ops.h static inline void drv_sta_set_decap_offload(struct ieee80211_local *local, · line 1472
Quoted 10 lines
net/mac80211/driver-ops.h +10
-0+struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta *sta, + u8 flowid) +{ +might_sleep (); +check_sdata_in_driver (sdata); + +if (local->ops->twt_teardown_request) + local->ops->twt_teardown_request (&local->hw, sta, flowid); +}
These should have tracing.
Quoted 4 lines
+++
b/net/mac80211/iface.cnet/mac80211/iface.c +0
-0@@ -1381,6 +1381,19 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local, WARN_ON(1); break;
net/mac80211/iface.c static void ieee80211_iface_process_skb(struct ieee80211_local *local, · line 1392
Quoted 10 lines
net/mac80211/iface.c +9
-0} + }else if (ieee80211_is_action (mgmt->frame_control) && + mgmt->u.action.category ==WLAN_CATEGORY_S1G ) { +switch (mgmt->u.action.u.s1g.action_code) { +case WLAN_S1G_TWT_TEARDOWN : +case WLAN_S1G_TWT_SETUP : +if (skb->pkt_type ==IEEE80211_TX_STATUS_MSG ) +ieee80211_s1g_status_h_twt (sdata, skb); +else +ieee80211_s1g_rx_h_twt (sdata, skb);
I *really* don't like what you're doing here with the sdata->skb_queue, which we only ever use for RX today.
We have today ieee80211_mgd_conn_tx_status() that gets called at the right place, so you should add stuff there, and perhaps it needs to queue things, or mark a separate TWT data structure before queueing the work, or something else - but please don't use the RX skb_queue.
net/mac80211/rx.c ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) · line 3210
Quoted 3 lines
net/mac80211/rx.c +2
-0+static ieee80211_rx_result debug_noinline +ieee80211_rx_h_twt (struct ieee80211_rx_data *rx)
Please rename this - it's not actually an rx_h_ that's called through the normal RX handler stuff, it's just a sub-function for the action RX handler.
It also doesn't need the rx_result, it can just be bool/int.
net/mac80211/rx.c ieee80211_rx_h_action(struct ieee80211_rx_data *rx) · line 3537
Quoted 6 lines
net/mac80211/rx.c +6
-0+case WLAN_CATEGORY_S1G : +switch (mgmt->u.action.u.s1g.action_code) { +case WLAN_S1G_TWT_SETUP : +case WLAN_S1G_TWT_TEARDOWN : +if (ieee80211_rx_h_twt (rx) !=RX_CONTINUE ) + goto queue;
(see here)
Review
Quoted 1 line
(quoted diff) +1
-0+ default:
Also missing a "fallthrough" annotation or such.
net/mac80211/s1g.c void ieee80211_s1g_sta_rate_init(struct sta_info *sta) · line 160
Quoted 11 lines
net/mac80211/s1g.c +11
-0+ +static int +ieee80211_s1g_rx_h_twt_teardown (struct ieee80211_sub_if_data *sdata, +struct sta_info *sta,struct sk_buff *skb) +{ +struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; + +drv_twt_teardown_request (sdata->local, sdata, &sta->sta, + mgmt->u.action.u.s1g.variable[0 ]); + +return 0 ;
Evidently, this cannot fail, so needs no return value.
Review
Quoted 2 lines
(quoted diff) +2
-0+void ieee80211_s1g_rx_h_twt(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb)
again, not a real RX handler
Quoted 4 lines
net/mac80211/s1g.c +4
-0+{ +struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; +struct ieee80211_local *local = sdata->local; +struct sta_info *sta;
net/mac80211/s1g.c void ieee80211_s1g_sta_rate_init(struct sta_info *sta) · line 178
Quoted 10 lines
net/mac80211/s1g.c +10
-0+ +mutex_lock (&local->sta_mtx); + + sta =sta_info_get_bss (sdata, mgmt->sa); +if (!sta) + goto out; + +switch (mgmt->u.action.u.s1g.action_code) { +case WLAN_S1G_TWT_SETUP : +ieee80211_s1g_rx_h_twt_setup (sdata, sta, skb);
You're completely ignoring the return value. That's probably fine in the -ENOMEM case, but the other cases you should still send a response. Just like the driver callback is void because it should just fill in the response to the other side (even in the failure cases).
johannes
Re: [PATCH v2 mac80211-next 2/7] mac80211: introduce individual TWT support in AP mode.
Quoted 18 lines
Quoted 18 lines
net/mac80211/driver-ops.h +17
-0+static inline void drv_add_twt_setup (struct ieee80211_local *local, +struct ieee80211_sub_if_data *sdata, +struct ieee80211_sta *sta, +struct ieee80211_twt_params *agrt_req, +struct ieee80211_twt_params *agrt_resp) +{ +might_sleep (); +check_sdata_in_driver (sdata); + + local->ops->add_twt_setup (&local->hw, sta, agrt_req, agrt_resp); +} + +static inline void drv_twt_teardown_request (struct ieee80211_local *local, +struct ieee80211_sub_if_data *sdata, +struct ieee80211_sta *sta, +u8 flowid) +{
Quoted 8 lines
net/mac80211/driver-ops.h static inline void drv_sta_set_decap_offload(struct ieee80211_local *local, · line 1472
Quoted 6 lines
net/mac80211/driver-ops.h +6
-0+might_sleep (); +check_sdata_in_driver (sdata); + +if (local->ops->twt_teardown_request) + local->ops->twt_teardown_request (&local->hw, sta, flowid); +}These should have tracing.
ack, I will add tracing in v3
Quoted 20 lines
Quoted 5 lines
+++
b/net/mac80211/iface.cnet/mac80211/iface.c +0
-0@@ -1381,6 +1381,19 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local, WARN_ON(1); break;net/mac80211/iface.c static void ieee80211_iface_process_skb(struct ieee80211_local *local, · line 1392
Quoted 10 lines
net/mac80211/iface.c +9
-0} + }else if (ieee80211_is_action (mgmt->frame_control) && + mgmt->u.action.category ==WLAN_CATEGORY_S1G ) { +switch (mgmt->u.action.u.s1g.action_code) { +case WLAN_S1G_TWT_TEARDOWN : +case WLAN_S1G_TWT_SETUP : +if (skb->pkt_type ==IEEE80211_TX_STATUS_MSG ) +ieee80211_s1g_status_h_twt (sdata, skb); +else +ieee80211_s1g_rx_h_twt (sdata, skb);I *really* don't like what you're doing here with the
sdata->skb_queue, which we only ever use for RX today.
Quoted 4 lines
We have today
ieee80211_mgd_conn_tx_status()that gets called at the right place, so you should add stuff there, and perhaps it needs to queue things, or mark a separate TWT data structure before queueing the work, or something else - but please don't use the RXskb_queue.
ack, I will review/work on ieee80211_mgd_conn_tx_status() in v3
Quoted 10 lines
net/mac80211/rx.c ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) · line 3210
Quoted 4 lines
net/mac80211/rx.c +2
-0+static ieee80211_rx_result debug_noinline +ieee80211_rx_h_twt (struct ieee80211_rx_data *rx)Please rename this - it's not actually an
rx_h_that's called through the normal RX handler stuff, it's just a sub-function for the action RX handler.It also doesn't need the
rx_result, it can just be bool/int.
ack, naming is hard :)
Quoted 11 lines
net/mac80211/rx.c ieee80211_rx_h_action(struct ieee80211_rx_data *rx) · line 3537
Quoted 7 lines
net/mac80211/rx.c +6
-0+case WLAN_CATEGORY_S1G : +switch (mgmt->u.action.u.s1g.action_code) { +case WLAN_S1G_TWT_SETUP : +case WLAN_S1G_TWT_TEARDOWN : +if (ieee80211_rx_h_twt (rx) !=RX_CONTINUE ) + goto queue;(see here)
Quoted 3 lines
Review
Quoted 1 line
(quoted diff) +1
-0+ default:Also missing a "fallthrough" annotation or such.
ack, I will fix it
Quoted 14 lines
net/mac80211/s1g.c void ieee80211_s1g_sta_rate_init(struct sta_info *sta) · line 160
Quoted 12 lines
net/mac80211/s1g.c +11
-0+ +static int +ieee80211_s1g_rx_h_twt_teardown (struct ieee80211_sub_if_data *sdata, +struct sta_info *sta,struct sk_buff *skb) +{ +struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; + +drv_twt_teardown_request (sdata->local, sdata, &sta->sta, + mgmt->u.action.u.s1g.variable[0 ]); + +return 0 ;Evidently, this cannot fail, so needs no return value.
ack, I will fix it
Quoted 5 lines
Review
Quoted 3 lines
(quoted diff) +2
-0+void ieee80211_s1g_rx_h_twt(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb)again, not a real RX handler
ack, I will fix it
Quoted 12 lines
Quoted 12 lines
net/mac80211/s1g.c +11
-0+{ +struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; +struct ieee80211_local *local = sdata->local; +struct sta_info *sta; + +mutex_lock (&local->sta_mtx); + + sta =sta_info_get_bss (sdata, mgmt->sa); +if (!sta) + goto out; +
Quoted 8 lines
net/mac80211/s1g.c void ieee80211_s1g_sta_rate_init(struct sta_info *sta) · line 178
Quoted 3 lines
net/mac80211/s1g.c +3
-0+switch (mgmt->u.action.u.s1g.action_code) { +case WLAN_S1G_TWT_SETUP : +ieee80211_s1g_rx_h_twt_setup (sdata, sta, skb);You're completely ignoring the return value. That's probably fine in the
-ENOMEMcase, but the other cases you should still send a response. Just like the driver callback is void because it should just fill in the response to the other side (even in the failure cases).
ack, I will fix it in v3
Regards,
Lorenzo
Quoted 3 lines
johannes