diff --git a/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c b/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c index 5e6052b1c0..67f53dc18d 100644 --- a/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c +++ b/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -36,6 +36,7 @@ #ifdef WLAN_FEATURE_ROAM_OFFLOAD #include #endif +#include static inline void target_if_vdev_mgr_handle_recovery(struct wlan_objmgr_psoc *psoc, @@ -871,6 +872,85 @@ static int target_if_pdev_csa_status_event_handler( return target_if_csa_switch_count_status(psoc, tgt_hdl, csa_status); } +/** + * target_if_vdev_mgr_csa_ie_received_handler - CSA IE Received event handler + * @scn: Pointer to scn structure + * @data: pointer to event data + * @datalen: event data length + * + * Return: 0 on success + */ +static int target_if_vdev_mgr_csa_ie_received_handler(ol_scn_t scn, + uint8_t *data, + uint32_t datalen) +{ + QDF_STATUS status; + uint8_t vdev_id = 0; + struct wlan_objmgr_psoc *psoc; + struct wmi_unified *wmi_handle; + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_pdev *pdev; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + struct csa_offload_params csa_event = {0}; + + if (!scn || !data) { + mlme_err("Invalid input"); + return -EINVAL; + } + + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + mlme_err("PSOC is NULL"); + return -EINVAL; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); +/*TODO: Uncomment these changes + * if (!rx_ops || !rx_ops->vdev_mgr_csa_received) { + * mlme_err("No Rx Ops"); + * return -EINVAL; + * } + */ + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + mlme_err("wmi_handle is null"); + return -EINVAL; + } + + status = wmi_extract_csa_ie_received_event(wmi_handle, data, + &vdev_id, &csa_event); + if (QDF_IS_STATUS_ERROR(status)) { + mlme_err("Extracting CSA IE Received event failed"); + return -EINVAL; + } + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_VDEV_TARGET_IF_ID); + if (!vdev) { + mlme_err("Null Vdev"); + return -EINVAL; + } + + pdev = wlan_vdev_get_pdev(vdev); + wlan_objmgr_vdev_release_ref(vdev, WLAN_VDEV_TARGET_IF_ID); + + if (csa_event.new_op_class && + wlan_reg_is_6ghz_op_class(pdev, csa_event.new_op_class)) { + csa_event.csa_chan_freq = + wlan_reg_chan_band_to_freq(pdev, csa_event.channel, + BIT(REG_BAND_6G)); + } else { + csa_event.csa_chan_freq = + wlan_reg_legacy_chan_to_freq(pdev, csa_event.channel); + } + +/*TODO: Uncomment these changes + * return rx_ops->vdev_mgr_csa_received(psoc, vdev_id, &csa_event); + */ + return 0; +} + #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE /** * target_if_update_macaddr_conf_evt_handler() - Set MAC address confirmation @@ -1102,6 +1182,14 @@ QDF_STATUS target_if_vdev_mgr_wmi_event_register( mlme_err("failed to register for csa event handler"); } + retval = wmi_unified_register_event_handler + (wmi_handle, + wmi_csa_ie_received_event_id, + target_if_vdev_mgr_csa_ie_received_handler, + VDEV_RSP_RX_CTX); + if (QDF_IS_STATUS_ERROR(retval)) + mlme_err("failed to register for CSA IE Received Event"); + target_if_register_set_mac_addr_evt_cbk(wmi_handle); target_if_register_quiet_offload_event(wmi_handle); @@ -1129,6 +1217,9 @@ QDF_STATUS target_if_vdev_mgr_wmi_event_unregister( target_if_unregister_set_mac_addr_evt_cbk(wmi_handle); + wmi_unified_unregister_event_handler(wmi_handle, + wmi_csa_ie_received_event_id); + wmi_unified_unregister_event_handler( wmi_handle, wmi_pdev_multi_vdev_restart_response_event_id); diff --git a/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h b/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h index 26d1bcd4de..53c7966f5d 100644 --- a/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h +++ b/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h @@ -3512,6 +3512,40 @@ struct wlan_edca_pifs_param_ie { } qdf_packed edca_pifs_param; } qdf_packed; +/** + * struct csa_ie: Channel Switch Announcement IE + * @id: CSA IE + * @len: CSA IE len + * @switch_mode: Channel Switch Mode + * @new_channel: New channel to which CSA is announced + * @tbtt_count: CSA count in beacon intervals + */ +struct csa_ie { + uint8_t id; + uint8_t len; + uint8_t switch_mode; + uint8_t new_channel; + uint8_t tbtt_count; +} qdf_packed; + +/** + * struct xcsa_ie: Extended Channel Switch Announcement IE + * @id: CSA IE + * @len: CSA IE len + * @switch_mode: Channel Switch Mode + * @new_class: New operating class + * @new_channel: New channel to which CSA is announced + * @tbtt_count: CSA count in beacon intervals + */ +struct xcsa_ie { + uint8_t id; + uint8_t len; + uint8_t switch_mode; + uint8_t new_class; + uint8_t new_channel; + uint8_t tbtt_count; +} qdf_packed; + /** * struct oce_reduced_wan_metrics: struct for oce wan metrics * @downlink_av_cap: Download available capacity diff --git a/umac/cmn_services/utils/src/wlan_utility.c b/umac/cmn_services/utils/src/wlan_utility.c index 895f0d99fe..e29ea21a9c 100644 --- a/umac/cmn_services/utils/src/wlan_utility.c +++ b/umac/cmn_services/utils/src/wlan_utility.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -1821,6 +1821,8 @@ bool wlan_get_connected_vdev_from_psoc_by_bssid(struct wlan_objmgr_psoc *psoc, return context.connected; } +qdf_export_symbol(wlan_get_connected_vdev_from_psoc_by_bssid); + bool wlan_get_connected_vdev_by_bssid(struct wlan_objmgr_pdev *pdev, uint8_t *bssid, uint8_t *vdev_id) { diff --git a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c index ea57b75a49..0a68f9a66e 100644 --- a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c +++ b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c @@ -650,6 +650,8 @@ qdf_freq_t wlan_reg_legacy_chan_to_freq(struct wlan_objmgr_pdev *pdev, return reg_legacy_chan_to_freq(pdev, chan_num); } +qdf_export_symbol(wlan_reg_legacy_chan_to_freq); + QDF_STATUS wlan_reg_set_country(struct wlan_objmgr_pdev *pdev, uint8_t *country) { @@ -1515,12 +1517,16 @@ bool wlan_reg_is_2ghz_op_class(const uint8_t *country, uint8_t op_class) return reg_is_2ghz_op_class(country, op_class); } +qdf_export_symbol(wlan_reg_is_2ghz_op_class); + bool wlan_reg_is_6ghz_op_class(struct wlan_objmgr_pdev *pdev, uint8_t op_class) { return reg_is_6ghz_op_class(pdev, op_class); } +qdf_export_symbol(wlan_reg_is_6ghz_op_class); + #ifdef CONFIG_REG_CLIENT bool wlan_reg_is_6ghz_supported(struct wlan_objmgr_psoc *psoc) { diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h index 2da6b5509d..138e22b5d0 100644 --- a/wmi/inc/wmi_unified_api.h +++ b/wmi/inc/wmi_unified_api.h @@ -5117,4 +5117,18 @@ QDF_STATUS wmi_extract_sap_coex_cap_service_ready_ext2( wmi_unified_t wmi_handle, uint8_t *evt_buf, struct wmi_host_coex_fix_chan_cap *cap); + +/** + * wmi_extract_csa_ie_received_event() - extract csa IE received event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @vdev_id: VDEV ID + * @csa_event: csa event data + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS +wmi_extract_csa_ie_received_event(wmi_unified_t wmi_handle, + void *evt_buf, uint8_t *vdev_id, + struct csa_offload_params *csa_event); #endif /* _WMI_UNIFIED_API_H_ */ diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index b78387e56c..6af01d9070 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -5278,6 +5278,7 @@ typedef enum { #ifdef QCA_STANDALONE_SOUNDING_TRIGGER wmi_vdev_standalone_sound_complete_eventid, #endif + wmi_csa_ie_received_event_id, wmi_events_max, } wmi_conv_event_id; diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index 87bc4edf27..e16529e078 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -3275,6 +3275,10 @@ QDF_STATUS uint8_t *evt_buf, struct r2p_table_update_status_obj *update_status, uint32_t len); +QDF_STATUS +(*extract_csa_ie_received_ev_params)(wmi_unified_t wmi_handle, + void *evt_buf, uint8_t *vdev_id, + struct csa_offload_params *csa_event); }; /* Forward declaration for psoc*/ diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c index 91f5b5671d..6df40350d2 100644 --- a/wmi/src/wmi_unified_api.c +++ b/wmi/src/wmi_unified_api.c @@ -4033,3 +4033,15 @@ QDF_STATUS wmi_extract_sap_coex_cap_service_ready_ext2( return QDF_STATUS_E_FAILURE; } + +QDF_STATUS +wmi_extract_csa_ie_received_event(wmi_unified_t wmi_handle, + void *evt_buf, uint8_t *vdev_id, + struct csa_offload_params *csa_event) +{ + if (wmi_handle->ops->extract_csa_ie_received_ev_params) + return wmi_handle->ops->extract_csa_ie_received_ev_params + (wmi_handle, evt_buf, vdev_id, csa_event); + + return QDF_STATUS_E_FAILURE; +} diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 97a6ea1f2a..0f3170f1a5 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -5495,6 +5495,79 @@ fail: return QDF_STATUS_E_FAILURE; } +/** + * extract_csa_ie_received_ev_params_tlv() - extract csa IE received event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @vdev_id: VDEV ID + * @csa_event: csa event data + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +static QDF_STATUS +extract_csa_ie_received_ev_params_tlv(wmi_unified_t wmi_handle, + void *evt_buf, uint8_t *vdev_id, + struct csa_offload_params *csa_event) +{ + WMI_CSA_IE_RECEIVED_EVENTID_param_tlvs *param_buf; + wmi_csa_event_fixed_param *csa_ev; + struct xcsa_ie *xcsa_ie; + struct csa_ie *csa_ie; + uint8_t *bssid; + bool ret; + + param_buf = (WMI_CSA_IE_RECEIVED_EVENTID_param_tlvs *)evt_buf; + if (!param_buf) { + wmi_err("Invalid csa event buffer"); + return QDF_STATUS_E_FAILURE; + } + csa_ev = param_buf->fixed_param; + WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_ev->i_addr2, + &csa_event->bssid.bytes[0]); + + bssid = csa_event->bssid.bytes; + ret = wlan_get_connected_vdev_from_psoc_by_bssid(wmi_handle->soc->wmi_psoc, + bssid, vdev_id); + if (!ret) { + wmi_err("VDEV is not connected with BSSID"); + return QDF_STATUS_E_FAILURE; + } + + if (csa_ev->ies_present_flag & WMI_CSA_IE_PRESENT) { + csa_ie = (struct csa_ie *)(&csa_ev->csa_ie[0]); + csa_event->channel = csa_ie->new_channel; + csa_event->switch_mode = csa_ie->switch_mode; + csa_event->ies_present_flag |= MLME_CSA_IE_PRESENT; + } else if (csa_ev->ies_present_flag & WMI_XCSA_IE_PRESENT) { + xcsa_ie = (struct xcsa_ie *)(&csa_ev->xcsa_ie[0]); + csa_event->channel = xcsa_ie->new_channel; + csa_event->switch_mode = xcsa_ie->switch_mode; + csa_event->new_op_class = xcsa_ie->new_class; + csa_event->ies_present_flag |= MLME_XCSA_IE_PRESENT; + } else { + wmi_err("CSA Event error: No CSA IE present"); + return QDF_STATUS_E_INVAL; + } + + wmi_debug("CSA IE Received: BSSID " QDF_MAC_ADDR_FMT " chan %d freq %d flag 0x%x width = %d freq1 = %d freq2 = %d op class = %d", + QDF_MAC_ADDR_REF(csa_event->bssid.bytes), + csa_event->channel, + csa_event->csa_chan_freq, + csa_event->ies_present_flag, + csa_event->new_ch_width, + csa_event->new_ch_freq_seg1, + csa_event->new_ch_freq_seg2, + csa_event->new_op_class); + + if (!csa_event->channel) { + wmi_err("CSA Event with channel %d. Ignore !!", + csa_event->channel); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + /** * send_probe_rsp_tmpl_send_cmd_tlv() - send probe response template to fw * @wmi_handle: wmi handle @@ -20985,6 +21058,8 @@ struct wmi_ops tlv_ops = { extract_sap_coex_fix_chan_caps, .extract_tgtr2p_table_event = extract_tgtr2p_table_event_tlv, .send_egid_info_cmd = send_egid_info_cmd_tlv, + .extract_csa_ie_received_ev_params = + extract_csa_ie_received_ev_params_tlv, }; #ifdef WLAN_FEATURE_11BE_MLO @@ -21499,6 +21574,8 @@ static void populate_tlv_events_id(WMI_EVT_ID *event_ids) event_ids[wmi_vdev_standalone_sound_complete_eventid] = WMI_VDEV_STANDALONE_SOUND_COMPLETE_EVENTID; #endif + event_ids[wmi_csa_ie_received_event_id] = + WMI_CSA_IE_RECEIVED_EVENTID; } #ifdef WLAN_FEATURE_LINK_LAYER_STATS