diff --git a/components/spatial_reuse/dispatcher/inc/spatial_reuse_api.h b/components/spatial_reuse/dispatcher/inc/spatial_reuse_api.h index 3f920f65ef..a99616bc75 100644 --- a/components/spatial_reuse/dispatcher/inc/spatial_reuse_api.h +++ b/components/spatial_reuse/dispatcher/inc/spatial_reuse_api.h @@ -25,6 +25,43 @@ #include #include +/** + * enum sr_osif_operation - Spatial Reuse operation + * @SR_OPERATION_SUSPEND: Spatial Reuse suspend indication + * @SR_OPERATION_RESUME: Spatial Reuse resume indication + * @SR_OPERATION_UPDATE_PARAMS: Spatial Reuse parameters are updated + */ +enum sr_osif_operation { + SR_OPERATION_SUSPEND = 0, + SR_OPERATION_RESUME = 1, + SR_OPERATION_UPDATE_PARAMS = 2, +}; + +/** + * enum sr_osif_reason_code - Spatial Reuse reason codes + * @SR_REASON_CODE_ROAMING: Spatial Reuse reason code is Roaming will be + * set when SR is suspended / resumed due to roaming + * @SR_REASON_CODE_CONCURRENCY: Spatial Reuse reason code is concurrency + * will be set when SR is suspended / resumed + * due to concurrency + */ +enum sr_osif_reason_code { + SR_REASON_CODE_ROAMING = 0, + SR_REASON_CODE_CONCURRENCY = 1, +}; + +/** + * sr_osif_event_cb() - CB to deliver SR events + * @vdev: objmgr manager vdev + * @sr_osif_oper: SR Operation like suspend / resume + * @sr_osif_rc: Event reason code + * + * Return: void + */ +typedef void (*sr_osif_event_cb)(struct wlan_objmgr_vdev *vdev, + enum sr_osif_operation sr_osif_oper, + enum sr_osif_reason_code sr_osif_rc); + #ifdef WLAN_FEATURE_SR /** * wlan_spatial_reuse_config_set() - Set spatial reuse config @@ -47,6 +84,28 @@ QDF_STATUS wlan_spatial_reuse_config_set(struct wlan_objmgr_vdev *vdev, * Return: QDF_STATUS */ QDF_STATUS wlan_spatial_reuse_pdev_init(struct wlan_objmgr_pdev *pdev); + +/** + * wlan_sr_register_callback() - registers SR osif events + * @psoc: pointer to psoc + * @cb: Callback to be registered + * + * Return: void + */ +void wlan_sr_register_callback(struct wlan_objmgr_psoc *psoc, + sr_osif_event_cb cb); + +/** + * wlan_spatial_reuse_osif_event() - Send SR asynchronous events + * @vdev: objmgr manager vdev + * @sr_osif_oper: SR Operation like suspend / resume + * @sr_osif_rc: Event reason code + * + * Return: void + */ +void wlan_spatial_reuse_osif_event(struct wlan_objmgr_vdev *vdev, + enum sr_osif_operation sr_osif_oper, + enum sr_osif_reason_code sr_osif_rc); #else static inline QDF_STATUS wlan_spatial_reuse_config_set(struct wlan_objmgr_vdev *vdev, @@ -61,6 +120,13 @@ QDF_STATUS wlan_spatial_reuse_pdev_init(struct wlan_objmgr_pdev *pdev) { return QDF_STATUS_SUCCESS; } + +static inline +void wlan_spatial_reuse_osif_event(struct wlan_objmgr_vdev *vdev, + enum sr_osif_operation sr_osif_oper, + enum sr_osif_reason_code sr_osif_rc) +{ +} #endif /** diff --git a/components/spatial_reuse/dispatcher/inc/spatial_reuse_ucfg_api.h b/components/spatial_reuse/dispatcher/inc/spatial_reuse_ucfg_api.h index 00548ec8a0..c5f65ad19b 100644 --- a/components/spatial_reuse/dispatcher/inc/spatial_reuse_ucfg_api.h +++ b/components/spatial_reuse/dispatcher/inc/spatial_reuse_ucfg_api.h @@ -20,9 +20,21 @@ #ifndef _SPATIAL_REUSE_UCFG_API_H_ #define _SPATIAL_REUSE_UCFG_API_H_ -#ifdef WLAN_FEATURE_SR #include #include +#include + +#ifdef WLAN_FEATURE_SR +/** + * ucfg_spatial_reuse_register_cb() - Registers CB for SR + * @psoc: pointer to psoc + * @cb: SR osif event callback + * + * Return: void + */ +void ucfg_spatial_reuse_register_cb(struct wlan_objmgr_psoc *psoc, + sr_osif_event_cb cb); + /** * ucfg_spatial_reuse_get_sr_config() - Spatial reuse config get * @@ -120,5 +132,11 @@ QDF_STATUS ucfg_spatial_reuse_setup_req(struct wlan_objmgr_vdev *vdev, struct wlan_objmgr_pdev *pdev, bool is_sr_enable, int32_t pd_threshold); +#else +static inline +void ucfg_spatial_reuse_register_cb(struct wlan_objmgr_psoc *psoc, + sr_osif_event_cb cb) +{ +} #endif #endif diff --git a/components/spatial_reuse/dispatcher/src/spatial_reuse_api.c b/components/spatial_reuse/dispatcher/src/spatial_reuse_api.c index 93f86d051f..3cafff09d7 100644 --- a/components/spatial_reuse/dispatcher/src/spatial_reuse_api.c +++ b/components/spatial_reuse/dispatcher/src/spatial_reuse_api.c @@ -20,6 +20,10 @@ #include #include +struct sr_cb { + sr_osif_event_cb send_osif_event; +} sr_cb; + QDF_STATUS wlan_spatial_reuse_config_set(struct wlan_objmgr_vdev *vdev, uint8_t sr_ctrl, uint8_t non_srg_max_pd_offset) @@ -114,3 +118,19 @@ QDF_STATUS wlan_spatial_reuse_pdev_init(struct wlan_objmgr_pdev *pdev) return wmi_unified_pdev_param_send(wmi_handle, &pparam, WILDCARD_PDEV_ID); } + +void wlan_sr_register_callback(struct wlan_objmgr_psoc *psoc, + sr_osif_event_cb cb) +{ + if (!psoc) + return; + sr_cb.send_osif_event = cb; +} + +void wlan_spatial_reuse_osif_event(struct wlan_objmgr_vdev *vdev, + enum sr_osif_operation sr_osif_oper, + enum sr_osif_reason_code sr_osif_rc) +{ + if (sr_cb.send_osif_event) + sr_cb.send_osif_event(vdev, sr_osif_oper, sr_osif_rc); +} diff --git a/components/spatial_reuse/dispatcher/src/spatial_reuse_ucfg_api.c b/components/spatial_reuse/dispatcher/src/spatial_reuse_ucfg_api.c index e2503b3e3b..d21e450895 100644 --- a/components/spatial_reuse/dispatcher/src/spatial_reuse_ucfg_api.c +++ b/components/spatial_reuse/dispatcher/src/spatial_reuse_ucfg_api.c @@ -21,6 +21,12 @@ #include #include +void ucfg_spatial_reuse_register_cb(struct wlan_objmgr_psoc *psoc, + sr_osif_event_cb cb) +{ + wlan_sr_register_callback(psoc, cb); +} + void ucfg_spatial_reuse_get_sr_config(struct wlan_objmgr_vdev *vdev, uint8_t *sr_ctrl, uint8_t *non_srg_max_pd_offset, diff --git a/core/hdd/inc/wlan_hdd_he.h b/core/hdd/inc/wlan_hdd_he.h index 7c4a2e5fce..309c439913 100644 --- a/core/hdd/inc/wlan_hdd_he.h +++ b/core/hdd/inc/wlan_hdd_he.h @@ -134,6 +134,15 @@ int wlan_hdd_cfg80211_get_he_cap(struct wiphy *wiphy, int wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); + +/** + * hdd_sr_register_callbacks() - register hdd callback for sr + * @hdd_ctx: hdd context + * + * Return: void + */ +void hdd_sr_register_callbacks(struct hdd_context *hdd_ctx); + #else static inline int wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy, @@ -142,6 +151,10 @@ int wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy, { return 0; } + +static inline void hdd_sr_register_callbacks(struct hdd_context *hdd_ctx) +{ +} #endif #define FEATURE_11AX_VENDOR_COMMANDS \ @@ -180,6 +193,10 @@ static inline int hdd_update_he_cap_in_cfg(struct hdd_context *hdd_ctx) return 0; } +static inline void hdd_sr_register_callbacks(struct hdd_context *hdd_ctx) +{ +} + /* dummy definition */ #define FEATURE_11AX_VENDOR_COMMANDS diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 2f56468f60..5c82a8d786 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -1839,6 +1839,12 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = .subcmd = QCA_NL80211_VENDOR_SUBCMD_DRIVER_READY, }, FEATURE_WIFI_POS_11AZ_AUTH_EVENTS +#ifdef WLAN_FEATURE_SR + [QCA_NL80211_VENDOR_SUBCMD_SR_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_SR, + }, +#endif }; /** diff --git a/core/hdd/src/wlan_hdd_he.c b/core/hdd/src/wlan_hdd_he.c index 7844b0e88f..e90901a18e 100644 --- a/core/hdd/src/wlan_hdd_he.c +++ b/core/hdd/src/wlan_hdd_he.c @@ -247,6 +247,164 @@ int wlan_hdd_cfg80211_get_he_cap(struct wiphy *wiphy, } #ifdef WLAN_FEATURE_SR +static QDF_STATUS +hdd_sr_event_convert_reason_code(enum sr_osif_reason_code sr_osif_rc, + enum qca_wlan_sr_reason_code *sr_nl_rc) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + + switch (sr_osif_rc) { + case SR_REASON_CODE_ROAMING: + *sr_nl_rc = QCA_WLAN_SR_REASON_CODE_ROAMING; + break; + case SR_REASON_CODE_CONCURRENCY: + *sr_nl_rc = QCA_WLAN_SR_REASON_CODE_CONCURRENCY; + break; + default: + status = QDF_STATUS_E_INVAL; + } + + return status; +} + +static QDF_STATUS +hdd_sr_event_convert_operation(enum sr_osif_operation sr_osif_oper, + enum qca_wlan_sr_operation *sr_nl_oper) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + + switch (sr_osif_oper) { + case SR_OPERATION_SUSPEND: + *sr_nl_oper = QCA_WLAN_SR_OPERATION_SR_SUSPEND; + break; + case SR_OPERATION_RESUME: + *sr_nl_oper = QCA_WLAN_SR_OPERATION_SR_RESUME; + break; + case SR_OPERATION_UPDATE_PARAMS: + *sr_nl_oper = QCA_WLAN_SR_OPERATION_UPDATE_PARAMS; + break; + default: + status = QDF_STATUS_E_INVAL; + } + + return status; +} + +static QDF_STATUS hdd_sr_pack_conc_event(struct sk_buff *skb, + enum qca_wlan_sr_operation sr_nl_oper, + enum qca_wlan_sr_reason_code sr_nl_rc) +{ + struct nlattr *attr; + QDF_STATUS status = QDF_STATUS_E_FAULT; + + if (sr_nl_rc != QCA_WLAN_SR_REASON_CODE_CONCURRENCY || + (sr_nl_oper != QCA_WLAN_SR_OPERATION_SR_SUSPEND && + sr_nl_oper != QCA_WLAN_SR_OPERATION_SR_RESUME)) { + hdd_err("SR concurrency operation is invalid"); + status = QDF_STATUS_E_INVAL; + goto sr_events_end; + } + + if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_SR_OPERATION, sr_nl_oper)) { + hdd_err("failed to put attr SR Operation"); + goto sr_events_end; + } + + attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_SR_PARAMS); + if (!attr) { + hdd_err("nesting failed"); + goto sr_events_end; + } + + if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_SR_PARAMS_REASON_CODE, + sr_nl_rc)) { + hdd_err("failed to put attr SR Reascon Code"); + goto sr_events_end; + } + status = QDF_STATUS_SUCCESS; + nla_nest_end(skb, attr); + +sr_events_end: + return status; +} + +static void hdd_sr_osif_events(struct wlan_objmgr_vdev *vdev, + enum sr_osif_operation sr_osif_oper, + enum sr_osif_reason_code sr_osif_rc) +{ + struct hdd_adapter *adapter; + struct wireless_dev *wdev; + struct wiphy *wiphy; + struct sk_buff *skb; + uint32_t idx = QCA_NL80211_VENDOR_SUBCMD_SR_INDEX; + uint32_t len = NLMSG_HDRLEN; + QDF_STATUS status; + enum qca_wlan_sr_operation sr_nl_oper; + enum qca_wlan_sr_reason_code sr_nl_rc; + + if (!vdev) { + hdd_err("Null VDEV"); + return; + } + + adapter = wlan_hdd_get_adapter_from_objmgr(vdev); + if (!adapter) { + hdd_err("Null adapter"); + return; + } + + status = hdd_sr_event_convert_operation(sr_osif_oper, &sr_nl_oper); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Invalid SR Operation: %d", sr_osif_oper); + return; + } + status = hdd_sr_event_convert_reason_code(sr_osif_rc, &sr_nl_rc); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Invalid SR Reason Code: %d", sr_osif_rc); + return; + } + + hdd_debug("SR Operation: %u SR Reason Code: %u", + sr_nl_oper, sr_nl_rc); + switch (sr_nl_oper) { + case QCA_WLAN_SR_OPERATION_SR_SUSPEND: + case QCA_WLAN_SR_OPERATION_SR_RESUME: + if (sr_nl_rc == QCA_WLAN_SR_REASON_CODE_CONCURRENCY) { + wiphy = adapter->hdd_ctx->wiphy; + wdev = &adapter->wdev; + len += nla_total_size(sizeof(uint8_t)) + + nla_total_size(sizeof(uint32_t)); + skb = wlan_cfg80211_vendor_event_alloc(wiphy, wdev, + len, idx, + GFP_KERNEL); + if (!skb) { + hdd_err("cfg80211_vendor_event_alloc failed"); + return; + } + status = hdd_sr_pack_conc_event(skb, sr_nl_oper, + sr_nl_rc); + if (QDF_IS_STATUS_ERROR(status)) { + kfree_skb(skb); + return; + } + + wlan_cfg80211_vendor_event(skb, GFP_KERNEL); + hdd_debug("SR cfg80211 event is sent"); + } else { + hdd_debug("SR Reason code not supported"); + } + break; + default: + hdd_debug("SR Operation not supported"); + break; + } +} + +void hdd_sr_register_callbacks(struct hdd_context *hdd_ctx) +{ + ucfg_spatial_reuse_register_cb(hdd_ctx->psoc, hdd_sr_osif_events); +} + static int hdd_get_srp_stats_len(void) { struct cdp_pdev_obss_pd_stats_tlv stats; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 09e40cb90a..afc2d21fb5 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -4289,6 +4289,8 @@ int hdd_wlan_start_modules(struct hdd_context *hdd_ctx, bool reinit) hdd_son_register_callbacks(hdd_ctx); + hdd_sr_register_callbacks(hdd_ctx); + wlan_hdd_register_btc_chain_mode_handler(hdd_ctx->psoc); status = cds_pre_enable(); diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 63312d2bc5..31331b7c83 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -9527,8 +9527,6 @@ void lim_process_set_he_bss_color(struct mac_context *mac_ctx, uint32_t *msg_buf struct sir_set_he_bss_color *bss_color; struct pe_session *session_entry = NULL; tUpdateBeaconParams beacon_params; - /* PD threshold -128 to disable SR */ - uint8_t non_srg_pd_threshold_disabled = 0x80; if (!msg_buf) { pe_err("Buffer is Pointing to NULL"); @@ -9566,8 +9564,7 @@ void lim_process_set_he_bss_color(struct mac_context *mac_ctx, uint32_t *msg_buf if (wlan_vdev_mlme_get_he_spr_enabled(session_entry->vdev)) /* Disable spatial reuse during BSS color change */ - wlan_spatial_reuse_config_set(session_entry->vdev, 0, - non_srg_pd_threshold_disabled); + wlan_spatial_reuse_config_set(session_entry->vdev, 0, 0); if (sch_set_fixed_beacon_fields(mac_ctx, session_entry) != QDF_STATUS_SUCCESS) { diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index 510dd5b016..0b28b0823d 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -2344,11 +2344,17 @@ lim_update_spatial_reuse(struct pe_session *session) false); wlan_spatial_reuse_config_set(session->vdev, sr_ctrl, non_srg_pd_max_offset); + wlan_spatial_reuse_osif_event(session->vdev, + SR_OPERATION_RESUME, + SR_REASON_CODE_CONCURRENCY); } else { wlan_vdev_mlme_set_sr_disable_due_conc(session->vdev, true); wlan_spatial_reuse_config_set(session->vdev, sr_ctrl, - 0x80); + NON_SR_PD_THRESHOLD_DISABLED); + wlan_spatial_reuse_osif_event(session->vdev, + SR_OPERATION_SUSPEND, + SR_REASON_CODE_CONCURRENCY); } } } diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index c30e47a727..7ec6ab5fd2 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -69,6 +69,7 @@ #include "target_if_nan.h" #endif #include "wlan_scan_api.h" +#include "spatial_reuse_api.h" #include "wlan_cm_api.h" #include #include "cdp_txrx_host_stats.h" @@ -683,6 +684,9 @@ static void wma_sr_handle_conc(tp_wma_handle wma, return; wma_sr_send_pd_threshold(wma, conc_vdev_id, val); + wlan_spatial_reuse_osif_event(conc_vdev, + SR_OPERATION_SUSPEND, + SR_REASON_CODE_CONCURRENCY); } else if (wlan_vdev_mlme_is_sr_disable_due_conc(conc_vdev)) { wlan_vdev_mlme_set_sr_disable_due_conc(conc_vdev, false); if (!wlan_vdev_mlme_get_he_spr_enabled(conc_vdev)) @@ -694,6 +698,9 @@ static void wma_sr_handle_conc(tp_wma_handle wma, (sr_ctrl & SRG_INFO_PRESENT)) { wlan_mlme_update_sr_data(conc_vdev, &val, 0, true); wma_sr_send_pd_threshold(wma, conc_vdev_id, val); + wlan_spatial_reuse_osif_event(conc_vdev, + SR_OPERATION_RESUME, + SR_REASON_CODE_CONCURRENCY); } else { wma_debug("SR Disabled in SR Control"); }