From aa4fe41237443991dafa9e0aae181ff73a29ed3e Mon Sep 17 00:00:00 2001 From: Priyadarshnee S Date: Tue, 23 Jul 2019 14:37:06 +0530 Subject: [PATCH 1/3] qcacmn: Add a Regulatory API to compute channel list after HW Mode Switch Add regulatory API and a dispatcher function to compute current channel list after dynamic HW Mode Switch. range_5g_low, range_5g_high and wireless modes are extracted from wlan_psoc_host_mac_phy_caps based on the new HW mode configured and are used to derive the current channel list. Change-Id: I799712da8992ede0b5896dd2eb438cffea5fe048 CRs-Fixed: 2481535 --- .../regulatory/core/src/reg_services_common.c | 84 +++++++++++++++++++ .../regulatory/core/src/reg_services_common.h | 9 ++ .../dispatcher/inc/wlan_reg_services_api.h | 9 ++ .../dispatcher/src/wlan_reg_services_api.c | 11 +++ 4 files changed, 113 insertions(+) diff --git a/umac/regulatory/core/src/reg_services_common.c b/umac/regulatory/core/src/reg_services_common.c index c10a431f28ae..8cf19a04226f 100644 --- a/umac/regulatory/core/src/reg_services_common.c +++ b/umac/regulatory/core/src/reg_services_common.c @@ -2023,3 +2023,87 @@ bool reg_is_regdmn_en302502_applicable(struct wlan_objmgr_pdev *pdev) return reg_en302_502_regdmn(cur_reg_dmn.regdmn_pair_id); } + +QDF_STATUS reg_modify_pdev_chan_range(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_reg_tx_ops *reg_tx_ops; + struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap_ptr; + uint32_t cnt; + uint32_t pdev_id; + enum direction dir; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("pdev reg component is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + reg_err("psoc is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc_priv_obj = reg_get_psoc_obj(psoc); + if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { + reg_err("psoc reg component is NULL"); + return QDF_STATUS_E_INVAL; + } + + reg_cap_ptr = psoc_priv_obj->reg_cap; + + for (cnt = 0; cnt < PSOC_MAX_PHY_REG_CAP; cnt++) { + if (!reg_cap_ptr) { + qdf_mem_free(pdev_priv_obj); + reg_err("reg cap ptr is NULL"); + return QDF_STATUS_E_FAULT; + } + + if (reg_cap_ptr->phy_id == pdev_id) + break; + reg_cap_ptr++; + } + + if (cnt == PSOC_MAX_PHY_REG_CAP) { + qdf_mem_free(pdev_priv_obj); + reg_err("extended capabilities not found for pdev"); + return QDF_STATUS_E_FAULT; + } + + if (psoc_priv_obj->offload_enabled) { + dir = NORTHBOUND; + } else { + dir = SOUTHBOUND; + } + + pdev_priv_obj->range_2g_low = reg_cap_ptr->low_2ghz_chan; + pdev_priv_obj->range_2g_high = reg_cap_ptr->high_2ghz_chan; + pdev_priv_obj->range_5g_low = reg_cap_ptr->low_5ghz_chan; + pdev_priv_obj->range_5g_high = reg_cap_ptr->high_5ghz_chan; + pdev_priv_obj->wireless_modes = reg_cap_ptr->wireless_modes; + + reg_compute_pdev_current_chan_list(pdev_priv_obj); + + reg_tx_ops = reg_get_psoc_tx_ops(psoc); + + /* Fill the ic channel list with the updated current channel + * chan list. + */ + if (reg_tx_ops->fill_umac_legacy_chanlist) { + reg_tx_ops->fill_umac_legacy_chanlist(pdev, + pdev_priv_obj->cur_chan_list); + + } else { + if (dir == NORTHBOUND) + status = reg_send_scheduler_msg_nb(psoc, pdev); + else + status = reg_send_scheduler_msg_sb(psoc, pdev); + } + + return status; +} diff --git a/umac/regulatory/core/src/reg_services_common.h b/umac/regulatory/core/src/reg_services_common.h index d2ed228f755e..52df9be9558e 100644 --- a/umac/regulatory/core/src/reg_services_common.h +++ b/umac/regulatory/core/src/reg_services_common.h @@ -514,4 +514,13 @@ QDF_STATUS reg_enable_dfs_channels(struct wlan_objmgr_pdev *pdev, bool enable); * Return: True if en302_502 is applicable, else false. */ bool reg_is_regdmn_en302502_applicable(struct wlan_objmgr_pdev *pdev); + +/** + * reg_modify_pdev_chan_range() - Compute current channel list + * in accordance with the modified reg caps. + * @pdev: The physical dev for which channel list must be built. + * + * Return: QDF_STATUS + */ +QDF_STATUS reg_modify_pdev_chan_range(struct wlan_objmgr_pdev *pdev); #endif diff --git a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h index f7da9e3d51d8..b3a7d3290867 100644 --- a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h +++ b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h @@ -703,4 +703,13 @@ void wlan_reg_update_nol_history_ch(struct wlan_objmgr_pdev *pdev, * False: otherwise. */ bool wlan_reg_is_regdmn_en302502_applicable(struct wlan_objmgr_pdev *pdev); + +/** + * wlan_reg_modify_pdev_chan_range() - Compute current channel list for the + * modified channel range in the regcap. + * @pdev: pointer to wlan_objmgr_pdev. + * + * Return : QDF_STATUS + */ +QDF_STATUS wlan_reg_modify_pdev_chan_range(struct wlan_objmgr_pdev *pdev); #endif diff --git a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c index 67e5d745e955..5b9172521267 100644 --- a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c +++ b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c @@ -713,3 +713,14 @@ bool wlan_reg_is_regdmn_en302502_applicable(struct wlan_objmgr_pdev *pdev) { return reg_is_regdmn_en302502_applicable(pdev); } + +/** + * wlan_reg_modify_pdev_chan_range() - Compute current channel list for the + * modified regcap. + * @pdev: pointer to struct wlan_objmgr_pdev + * + */ +QDF_STATUS wlan_reg_modify_pdev_chan_range(struct wlan_objmgr_pdev *pdev) +{ + return reg_modify_pdev_chan_range(pdev); +} From 9d2d6e928b4a727367f3ea107ad2669fd7414ce7 Mon Sep 17 00:00:00 2001 From: Priyadarshnee S Date: Tue, 23 Jul 2019 15:22:32 +0530 Subject: [PATCH 2/3] qcacmn: Add RX ops to invoke DFS/REG APIs Provide Global function pointers for accessing DFS/REG APIs that 1. Build channel list as per the configured HW Mode. 2. Reinitialize DFS timers after mode switch. 3. Reset ADFS Config. CRs-Fixed: 2481535 Change-Id: Ied4d13b0c3ce39e696f273a7ac1f51962671c734 --- umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h | 6 ++++++ umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h index 4062353019e0..4d8a42dd7382 100644 --- a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h +++ b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h @@ -982,6 +982,8 @@ struct wlan_lmac_if_reg_rx_ops { struct cur_regdmn_info *cur_regdmn); QDF_STATUS (*reg_enable_dfs_channels)(struct wlan_objmgr_pdev *pdev, bool dfs_enable); + QDF_STATUS (*reg_modify_pdev_chan_range)(struct + wlan_objmgr_pdev *pdev); }; #ifdef CONVERGED_P2P_ENABLE @@ -1253,8 +1255,10 @@ struct wlan_lmac_if_wifi_pos_rx_ops { * @dfs_dfs_cac_complete_ind: Process cac complete indication. * @dfs_agile_precac_start: Initiate Agile PreCAC run. * @dfs_set_agile_precac_state: Set agile precac state. + * @dfs_reset_adfs_config: Reset agile dfs variables. * @dfs_dfs_ocac_complete_ind: Process offchan cac complete indication. * @dfs_stop: Clear dfs timers. + * @dfs_reinit_timers: Reinitialize DFS timers. * @dfs_enable_stadfs: Enable/Disable STADFS capability. * @dfs_is_stadfs_enabled: Get STADFS capability value. * @dfs_process_phyerr_filter_offload:Process radar event. @@ -1308,6 +1312,7 @@ struct wlan_lmac_if_dfs_rx_ops { QDF_STATUS (*dfs_agile_precac_start)(struct wlan_objmgr_pdev *pdev); QDF_STATUS (*dfs_set_agile_precac_state)(struct wlan_objmgr_pdev *pdev, int agile_precac_state); + QDF_STATUS (*dfs_reset_adfs_config)(struct wlan_objmgr_psoc *psoc); QDF_STATUS (*dfs_dfs_ocac_complete_ind)(struct wlan_objmgr_pdev *pdev, struct vdev_adfs_complete_status *ocac_st); @@ -1348,6 +1353,7 @@ struct wlan_lmac_if_dfs_rx_ops { uint32_t vdev_id); #endif QDF_STATUS (*dfs_stop)(struct wlan_objmgr_pdev *pdev); + QDF_STATUS (*dfs_reinit_timers)(struct wlan_objmgr_pdev *pdev); void (*dfs_enable_stadfs)(struct wlan_objmgr_pdev *pdev, bool val); bool (*dfs_is_stadfs_enabled)(struct wlan_objmgr_pdev *pdev); QDF_STATUS (*dfs_process_phyerr_filter_offload)( diff --git a/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c b/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c index c4d843318aeb..f8a7d70dc274 100644 --- a/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c +++ b/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c @@ -323,6 +323,9 @@ static void wlan_lmac_if_umac_reg_rx_ops_register( rx_ops->reg_rx_ops.reg_enable_dfs_channels = ucfg_reg_enable_dfs_channels; + + rx_ops->reg_rx_ops.reg_modify_pdev_chan_range = + wlan_reg_modify_pdev_chan_range; } #ifdef CONVERGED_P2P_ENABLE @@ -394,6 +397,7 @@ wlan_lmac_if_umac_dfs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) tgt_dfs_set_agile_precac_state; dfs_rx_ops->dfs_start_precac_timer = utils_dfs_start_precac_timer; dfs_rx_ops->dfs_cancel_precac_timer = utils_dfs_cancel_precac_timer; + dfs_rx_ops->dfs_reset_adfs_config = ucfg_dfs_reset_agile_config; dfs_rx_ops->dfs_override_precac_timeout = ucfg_dfs_override_precac_timeout; dfs_rx_ops->dfs_set_precac_enable = ucfg_dfs_set_precac_enable; @@ -405,6 +409,7 @@ wlan_lmac_if_umac_dfs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) dfs_rx_ops->dfs_dfs_cac_complete_ind = tgt_dfs_cac_complete; dfs_rx_ops->dfs_dfs_ocac_complete_ind = tgt_dfs_ocac_complete; dfs_rx_ops->dfs_stop = tgt_dfs_stop; + dfs_rx_ops->dfs_reinit_timers = ucfg_dfs_reinit_timers; dfs_rx_ops->dfs_enable_stadfs = tgt_dfs_enable_stadfs; dfs_rx_ops->dfs_is_stadfs_enabled = tgt_dfs_is_stadfs_enabled; dfs_rx_ops->dfs_process_phyerr_filter_offload = From d2ede02e219fea117af2e3bb3afed0eacc8fa2b0 Mon Sep 17 00:00:00 2001 From: Kiran Venkatappa Date: Wed, 31 Jul 2019 23:03:07 +0530 Subject: [PATCH 3/3] qcacmn: Add support in wifi pos to send wru/ftmrr frames FTMRR and WRU frames should be sent from host and these request should not be forwarded to FW. Add support in wifi pos to process this request and send response to userspace. Change-Id: I54049a1a889839e44d418ceebcca09e5092f6063 CRs-Fixed: 2500751 --- umac/wifi_pos/inc/wifi_pos_api.h | 29 +++++++++++++++ umac/wifi_pos/src/wifi_pos_api.c | 28 +++++++++++++++ umac/wifi_pos/src/wifi_pos_main.c | 53 ++++++++++++++++++++++++++-- umac/wifi_pos/src/wifi_pos_utils_i.h | 39 ++++++++++++++++++++ 4 files changed, 147 insertions(+), 2 deletions(-) diff --git a/umac/wifi_pos/inc/wifi_pos_api.h b/umac/wifi_pos/inc/wifi_pos_api.h index 9841b15433bc..72665e1b7ddf 100644 --- a/umac/wifi_pos/inc/wifi_pos_api.h +++ b/umac/wifi_pos/inc/wifi_pos_api.h @@ -412,4 +412,33 @@ QDF_STATUS wifi_pos_register_get_phy_mode_cb( struct wlan_objmgr_psoc *psoc, void (*handler)(uint8_t, uint32_t, uint32_t *)); +/** + * wifi_pos_register_send_action: API to register callback to send + * action frames + * @psoc: pointer to psoc object + * @handler: callback to be registered + * + * Return: QDF_STATUS_SUCCESS in case of success, error codes in + * case of failure + */ +QDF_STATUS wifi_pos_register_send_action( + struct wlan_objmgr_psoc *psoc, + void (*handler)(struct wlan_objmgr_psoc *psoc, + uint32_t sub_type, + uint8_t *buf, + uint32_t buf_len)); + +/** + * wifi_pos_send_report_resp: Send report to osif + * @psoc: pointer to psoc object + * @req_id: Request id + * @dest_mac: destination mac address + * @err_code: Error code to be sent + * + * Return: QDF_STATUS_SUCCESS in case of success, error codes in + * case of failure + */ +QDF_STATUS wifi_pos_send_report_resp(struct wlan_objmgr_psoc *psoc, + int req_id, uint8_t *dest_mac, + int err_code); #endif diff --git a/umac/wifi_pos/src/wifi_pos_api.c b/umac/wifi_pos/src/wifi_pos_api.c index c421fa38bdc8..cbcf95cedd84 100644 --- a/umac/wifi_pos/src/wifi_pos_api.c +++ b/umac/wifi_pos/src/wifi_pos_api.c @@ -350,3 +350,31 @@ QDF_STATUS wifi_pos_register_get_phy_mode_cb( return QDF_STATUS_SUCCESS; } +QDF_STATUS wifi_pos_register_send_action( + struct wlan_objmgr_psoc *psoc, + void (*handler)(struct wlan_objmgr_psoc *psoc, + uint32_t sub_type, + uint8_t *buf, + uint32_t buf_len)) +{ + struct wifi_pos_psoc_priv_obj *wifi_pos_psoc; + + if (!psoc) { + wifi_pos_err("psoc is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + if (!handler) { + wifi_pos_err("Null callback"); + return QDF_STATUS_E_NULL_VALUE; + } + wifi_pos_psoc = wifi_pos_get_psoc_priv_obj(psoc); + if (!wifi_pos_psoc) { + wifi_pos_err("wifi_pos priv obj is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + wifi_pos_psoc->wifi_pos_send_action = handler; + + return QDF_STATUS_SUCCESS; +} diff --git a/umac/wifi_pos/src/wifi_pos_main.c b/umac/wifi_pos/src/wifi_pos_main.c index de5951062112..b298cbf69b31 100644 --- a/umac/wifi_pos/src/wifi_pos_main.c +++ b/umac/wifi_pos/src/wifi_pos_main.c @@ -99,6 +99,13 @@ static QDF_STATUS wifi_pos_process_data_req(struct wlan_objmgr_psoc *psoc, struct oem_data_req data_req; struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops; struct wlan_objmgr_pdev *pdev; + struct wifi_pos_psoc_priv_obj *wifi_pos_obj = + wifi_pos_get_psoc_priv_obj(psoc); + + if (!wifi_pos_obj) { + wifi_pos_err("wifi_pos priv obj is null"); + return QDF_STATUS_E_INVAL; + } wifi_pos_debug("Received data req pid(%d), len(%d)", req->pid, req->buf_len); @@ -151,10 +158,18 @@ static QDF_STATUS wifi_pos_process_data_req(struct wlan_objmgr_psoc *psoc, /* TBD */ break; case TARGET_OEM_CONFIGURE_FTMRR: - /* TBD */ + wifi_pos_debug("FTMRR request"); + if (wifi_pos_obj->wifi_pos_send_action) + wifi_pos_obj->wifi_pos_send_action(psoc, sub_type, + req->buf, + req->buf_len); break; case TARGET_OEM_CONFIGURE_WRU: - /* TBD */ + wifi_pos_debug("WRU request"); + if (wifi_pos_obj->wifi_pos_send_action) + wifi_pos_obj->wifi_pos_send_action(psoc, sub_type, + req->buf, + req->buf_len); break; default: wifi_pos_debug("invalid sub type or not passed"); @@ -234,6 +249,40 @@ static QDF_STATUS wifi_pos_process_get_cap_req(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } +QDF_STATUS wifi_pos_send_report_resp(struct wlan_objmgr_psoc *psoc, + int req_id, uint8_t *dest_mac, + int err_code) +{ + struct wifi_pos_err_msg_report err_report = {0}; + struct wifi_pos_psoc_priv_obj *wifi_pos_obj = + wifi_pos_get_psoc_priv_obj(psoc); + + if (!wifi_pos_obj) { + wifi_pos_err("wifi_pos priv obj is null"); + return QDF_STATUS_E_INVAL; + } + + err_report.msg_tag_len = OEM_MSG_RSP_HEAD_TAG_ID << 16; + err_report.msg_tag_len |= (sizeof(err_report) - + sizeof(err_report.err_rpt)) & 0x0000FFFF; + err_report.msg_subtype = TARGET_OEM_ERROR_REPORT_RSP; + err_report.req_id = req_id & 0xFFFF; + err_report.req_id |= ((err_code & 0xFF) << 16); + err_report.req_id |= (0x1 << 24); + err_report.time_left = 0xFFFFFFFF; + err_report.err_rpt.tag_len = OEM_MEAS_RSP_HEAD_TAG_ID << 16; + err_report.err_rpt.tag_len |= + (sizeof(struct wifi_pos_err_rpt)) & 0x0000FFFF; + memcpy(&err_report.err_rpt.dest_mac, dest_mac, QDF_MAC_ADDR_SIZE); + + wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid, + ANI_MSG_OEM_DATA_RSP, + sizeof(err_report), + (uint8_t *)&err_report); + + return QDF_STATUS_SUCCESS; +} + static void wifi_update_channel_bw_info(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_pdev *pdev, uint16_t chan, diff --git a/umac/wifi_pos/src/wifi_pos_utils_i.h b/umac/wifi_pos/src/wifi_pos_utils_i.h index 4c23460b1b4c..c94269b51e56 100644 --- a/umac/wifi_pos/src/wifi_pos_utils_i.h +++ b/umac/wifi_pos/src/wifi_pos_utils_i.h @@ -188,6 +188,42 @@ struct qdf_packed wifi_pos_oem_get_cap_rsp { struct wifi_pos_user_defined_caps user_defined_cap; }; +/** + * struct wifi_pos_err_rpt - Error report response for userspace. + * @tag_len: tlv header of the message. + * @info: Report info. Reserved for error report. + * @dest_mac: Mac address of the sta in the request. + * @reserved: Reserved in error report. + */ +struct qdf_packed wifi_pos_err_rpt { + uint32_t tag_len; + uint32_t info; + uint8_t dest_mac[QDF_MAC_ADDR_SIZE + 2]; + uint32_t reserved; +}; + +#define OEM_MSG_RSP_HEAD_TAG_ID 33 +#define OEM_MEAS_RSP_HEAD_TAG_ID 41 +/** + * struct wifi_pos_err_msg_report - Error report message + * @msg_tag_len: Message tlv header + * @msg_subtype: Message subtype + * @req_id: id corresponding to the request. + * @fragment_info: Valid only for fragments. + * @pdev_id: pdev_id of radion. + * @time_left: time left in the measurment req. + * @err_rpt: Error report data. + */ +struct qdf_packed wifi_pos_err_msg_report { + uint32_t msg_tag_len; + uint32_t msg_subtype; + uint32_t req_id; + uint32_t fragment_info; + uint32_t pdev_id; + uint32_t time_left; + struct wifi_pos_err_rpt err_rpt; +}; + /** * struct wifi_pos_dma_rings_cap - capabilities requested by firmware. * @pdev_id: pdev_id or mac_id of ring @@ -306,6 +342,9 @@ struct wifi_pos_psoc_priv_obj { struct wifi_pos_req_msg *req); void (*wifi_pos_send_rsp)(uint32_t, uint32_t, uint32_t, uint8_t *); void (*wifi_pos_get_phy_mode)(uint8_t, uint32_t, uint32_t *); + void (*wifi_pos_send_action)(struct wlan_objmgr_psoc *psoc, + uint32_t oem_subtype, uint8_t *buf, + uint32_t len); }; /**