diff --git a/target_if/scan/src/target_if_scan.c b/target_if/scan/src/target_if_scan.c index 7e1e0f3f67..374574941b 100644 --- a/target_if/scan/src/target_if_scan.c +++ b/target_if/scan/src/target_if_scan.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021 The Linux Foundation. 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 @@ -357,6 +357,20 @@ target_if_pno_stop(struct wlan_objmgr_psoc *psoc, } #endif +static QDF_STATUS +target_if_obss_scan_disable(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id) +{ + struct wmi_unified *wmi_handle; + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("Invalid WMI handle"); + return QDF_STATUS_E_FAILURE; + } + + return wmi_unified_obss_disable_cmd(wmi_handle, vdev_id); +} QDF_STATUS target_if_scan_register_event_handler(struct wlan_objmgr_psoc *psoc, void *arg) @@ -453,6 +467,7 @@ target_if_scan_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) scan->scan_cancel = target_if_scan_cancel; scan->pno_start = target_if_pno_start; scan->pno_stop = target_if_pno_stop; + scan->obss_disable = target_if_obss_scan_disable; scan->scan_reg_ev_handler = target_if_scan_register_event_handler; scan->scan_unreg_ev_handler = target_if_scan_unregister_event_handler; 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 293a63f445..b8f686724d 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 @@ -241,6 +241,7 @@ struct wlan_lmac_if_mgmt_txrx_tx_ops { * @scan_cancel: function to cancel scan * @pno_start: start pno scan * @pno_stop: stop pno scan + * @obss_disable: disable obss scan * @scan_reg_ev_handler: function to register for scan events * @scan_unreg_ev_handler: function to unregister for scan events * @@ -255,6 +256,8 @@ struct wlan_lmac_if_scan_tx_ops { struct pno_scan_req_params *req); QDF_STATUS (*pno_stop)(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id); + QDF_STATUS (*obss_disable)(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id); QDF_STATUS (*scan_reg_ev_handler)(struct wlan_objmgr_psoc *psoc, void *arg); QDF_STATUS (*scan_unreg_ev_handler)(struct wlan_objmgr_psoc *psoc, diff --git a/umac/scan/core/src/wlan_scan_main.h b/umac/scan/core/src/wlan_scan_main.h index 29c0e08e17..8b519f931c 100644 --- a/umac/scan/core/src/wlan_scan_main.h +++ b/umac/scan/core/src/wlan_scan_main.h @@ -508,6 +508,7 @@ struct scan_cb { * @miracast_enabled: miracast enabled * @disable_timeout: command timeout disabled * @drop_bcn_on_chan_mismatch: drop bcn if channel mismatch + * @obss_scan_offload: if obss scan offload is enabled * @drop_bcn_on_invalid_freq: drop bcn if freq is invalid in IEs (DS/HT/HE) * @scan_start_request_buff: buffer used to pass * scan config to event handlers @@ -541,6 +542,7 @@ struct wlan_scan_obj { bool disable_timeout; bool drop_bcn_on_chan_mismatch; bool drop_bcn_on_invalid_freq; + bool obss_scan_offload; struct scan_start_request scan_start_request_buff; #ifdef FEATURE_6G_SCAN_CHAN_SORT_ALGO struct channel_list_db rnr_channel_db; diff --git a/umac/scan/core/src/wlan_scan_manager.c b/umac/scan/core/src/wlan_scan_manager.c index d968c03e15..699177b1aa 100644 --- a/umac/scan/core/src/wlan_scan_manager.c +++ b/umac/scan/core/src/wlan_scan_manager.c @@ -1629,3 +1629,36 @@ QDF_STATUS scm_scan_cancel_flush_callback(struct scheduler_msg *msg) return QDF_STATUS_SUCCESS; } + +void scm_disable_obss_pdev_scan(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + struct wlan_objmgr_vdev *vdev; + struct wlan_scan_obj *scan_obj; + struct scan_vdev_obj *scan_vdev_obj; + QDF_STATUS status; + + scan_obj = wlan_psoc_get_scan_obj(psoc); + if (!scan_obj) { + scm_err("scan object null"); + return; + } + + if (scan_obj->obss_scan_offload) { + vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_SCAN_ID); + if (!vdev) + return; + + scan_vdev_obj = wlan_get_vdev_scan_obj(vdev); + if (!scan_vdev_obj) { + scm_err("null scan_vdev_obj"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_SCAN_ID); + return; + } + + status = tgt_scan_obss_disable(vdev); + if (QDF_IS_STATUS_ERROR(status)) + scm_err("disable obss scan failed"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_SCAN_ID); + } +} diff --git a/umac/scan/core/src/wlan_scan_manager.h b/umac/scan/core/src/wlan_scan_manager.h index 545caa8482..741b704c6e 100644 --- a/umac/scan/core/src/wlan_scan_manager.h +++ b/umac/scan/core/src/wlan_scan_manager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 2020-2021 The Linux Foundation. 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 @@ -128,4 +128,14 @@ QDF_STATUS scm_scan_start_flush_callback(struct scheduler_msg *msg); */ QDF_STATUS scm_scan_cancel_flush_callback(struct scheduler_msg *msg); +/** + * scm_disable_obss_pdev_scan() - Public API to disable pdev obss scan + * @psoc: psoc pointer + * @pdev: pdev pointer + * + * Return: void + */ +void scm_disable_obss_pdev_scan(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev); + #endif diff --git a/umac/scan/dispatcher/inc/wlan_scan_tgt_api.h b/umac/scan/dispatcher/inc/wlan_scan_tgt_api.h index 23127e13ec..5792c11bb5 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_tgt_api.h +++ b/umac/scan/dispatcher/inc/wlan_scan_tgt_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017,2021 The Linux Foundation. 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 @@ -86,6 +86,15 @@ QDF_STATUS tgt_scan_pno_stop(struct wlan_objmgr_vdev *vdev, #endif +/** + * tgt_scan_obss_disable() - invoke lmac disable obss scan req + * @vdev: vdev pointer + * + * + * Return: QDF_STATUS_SUCCESS for success or error code. + */ +QDF_STATUS tgt_scan_obss_disable(struct wlan_objmgr_vdev *vdev); + /** * tgt_scan_start() - invoke lmac scan start * @req: scan request object diff --git a/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h b/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h index dccf0960fc..4982cd7f0d 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h +++ b/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h @@ -266,6 +266,15 @@ QDF_STATUS ucfg_scan_get_global_config(struct wlan_objmgr_psoc *psoc, enum scan_config config, uint32_t *val); +/** + * ucfg_scan_set_obss_scan_offload() - Public API to set obss scan flag + * @psoc: psoc context + * @val: the value to be set + * + * Return: void. + */ +void ucfg_scan_set_obss_scan_offload(struct wlan_objmgr_psoc *psoc, bool value); + /** * ucfg_scan_set_wide_band_scan() - Public API to disable/enable wide band scan * @pdev: psoc on which scans need to be disabled diff --git a/umac/scan/dispatcher/src/wlan_scan_tgt_api.c b/umac/scan/dispatcher/src/wlan_scan_tgt_api.c index a1b13caec6..a4cc8b3a40 100644 --- a/umac/scan/dispatcher/src/wlan_scan_tgt_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_tgt_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021 The Linux Foundation. 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 @@ -135,6 +135,34 @@ QDF_STATUS tgt_scan_pno_stop(struct wlan_objmgr_vdev *vdev, } #endif +QDF_STATUS tgt_scan_obss_disable(struct wlan_objmgr_vdev *vdev) +{ + struct wlan_lmac_if_scan_tx_ops *scan_ops; + struct wlan_objmgr_psoc *psoc; + uint8_t vdev_id; + + psoc = wlan_vdev_get_psoc(vdev); + + if (!psoc) { + scm_err("NULL PSOC"); + return QDF_STATUS_E_FAILURE; + } + scan_ops = wlan_psoc_get_scan_txops(psoc); + if (!scan_ops) { + scm_err("NULL scan_ops"); + return QDF_STATUS_E_FAILURE; + } + + vdev_id = wlan_vdev_get_id(vdev); + + /* invoke wmi_unified_obss_disable_cmd() */ + QDF_ASSERT(scan_ops->obss_disable); + if (scan_ops->obss_disable) + return scan_ops->obss_disable(psoc, vdev_id); + + return QDF_STATUS_SUCCESS; +} + QDF_STATUS tgt_scan_start(struct scan_start_request *req) { diff --git a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c index 72136a2694..031751ab1b 100644 --- a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c @@ -753,6 +753,7 @@ wlan_scan_global_init(struct wlan_objmgr_psoc *psoc, scan_obj->drop_bcn_on_invalid_freq = cfg_get(psoc, CFG_DROP_BCN_ON_INVALID_FREQ); scan_obj->disable_timeout = false; + scan_obj->obss_scan_offload = false; scan_obj->scan_def.active_dwell = cfg_get(psoc, CFG_ACTIVE_MAX_CHANNEL_TIME); /* the ini is disallow DFS channel scan if ini is 1, so negate that */ @@ -1308,16 +1309,18 @@ ucfg_scan_suspend_handler(struct wlan_objmgr_psoc *psoc, void *arg) struct wlan_objmgr_pdev *pdev = NULL; QDF_STATUS status = QDF_STATUS_SUCCESS; int i; - ucfg_scan_psoc_set_disable(psoc, REASON_SUSPEND); + /* Check all pdev */ for (i = 0; i < WLAN_UMAC_MAX_PDEVS; i++) { pdev = wlan_objmgr_get_pdev_by_id(psoc, i, WLAN_SCAN_ID); if (!pdev) continue; if (ucfg_scan_get_pdev_status(pdev) != - SCAN_NOT_IN_PROGRESS) + SCAN_NOT_IN_PROGRESS) { status = ucfg_scan_cancel_pdev_scan(pdev); + scm_disable_obss_pdev_scan(psoc, pdev); + } wlan_objmgr_pdev_release_ref(pdev, WLAN_SCAN_ID); if (QDF_IS_STATUS_ERROR(status)) { scm_err("failed to cancel scan for pdev_id %d", i); @@ -1690,6 +1693,19 @@ ucfg_scan_get_global_config(struct wlan_objmgr_psoc *psoc, return status; } +void ucfg_scan_set_obss_scan_offload(struct wlan_objmgr_psoc *psoc, bool value) +{ + struct wlan_scan_obj *scan_obj; + + scan_obj = wlan_psoc_get_scan_obj(psoc); + if (!scan_obj) { + scm_err("NULL scan obj"); + return; + } + + scan_obj->obss_scan_offload = value; +} + #ifdef FEATURE_WLAN_SCAN_PNO bool ucfg_scan_is_pno_offload_enabled(struct wlan_objmgr_psoc *psoc) { diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h index b3877e0384..e417b4810a 100644 --- a/wmi/inc/wmi_unified_api.h +++ b/wmi/inc/wmi_unified_api.h @@ -1431,6 +1431,18 @@ wmi_unified_ipa_offload_control_cmd( */ QDF_STATUS wmi_unified_pno_stop_cmd(wmi_unified_t wmi_handle, uint8_t vdev_id); +/** + * wmi_unified_obss_disable_cmd() - disable obss scan request + * @wmi_handle: wmi handle + * @vdev_id: vdev id + * + * This function request FW to disable obss scan. + * + * Return: QDF_STATUS_SUCCESS on success and others for failure + */ +QDF_STATUS wmi_unified_obss_disable_cmd(wmi_unified_t wmi_handle, + uint8_t vdev_id); + #ifdef FEATURE_WLAN_SCAN_PNO /** * wmi_unified_pno_start_cmd() - PNO start request diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index f7580f3a2c..4554cf329e 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -798,6 +798,8 @@ QDF_STATUS (*send_pno_stop_cmd)(wmi_unified_t wmi_handle, uint8_t vdev_id); QDF_STATUS (*send_pno_start_cmd)(wmi_unified_t wmi_handle, struct pno_scan_req_params *pno); +QDF_STATUS (*send_obss_disable_cmd)(wmi_unified_t wmi_handle, uint8_t vdev_id); + QDF_STATUS (*send_nlo_mawc_cmd)(wmi_unified_t wmi_handle, struct nlo_mawc_params *params); diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c index ab1b8e49aa..cf26ef39bf 100644 --- a/wmi/src/wmi_unified_api.c +++ b/wmi/src/wmi_unified_api.c @@ -727,6 +727,16 @@ QDF_STATUS wmi_unified_pno_stop_cmd(wmi_unified_t wmi_handle, uint8_t vdev_id) return QDF_STATUS_E_FAILURE; } +QDF_STATUS wmi_unified_obss_disable_cmd(wmi_unified_t wmi_handle, + uint8_t vdev_id) +{ + if (wmi_handle->ops->send_obss_disable_cmd) + return wmi_handle->ops->send_obss_disable_cmd(wmi_handle, + vdev_id); + + return QDF_STATUS_E_FAILURE; +} + #ifdef FEATURE_WLAN_SCAN_PNO QDF_STATUS wmi_unified_pno_start_cmd(wmi_unified_t wmi_handle, struct pno_scan_req_params *pno) diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 2486902112..baf0b7d978 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -4877,6 +4877,44 @@ static QDF_STATUS send_pno_stop_cmd_tlv(wmi_unified_t wmi_handle, uint8_t vdev_i return QDF_STATUS_SUCCESS; } +/** + * send_obss_disable_cmd_tlv() - disable obss scan request + * @wmi_handle: wmi handle + * @vdev_id: vdev id + * + * This function request FW to disable ongoing obss scan operation. + * + * Return: QDF status + */ +static QDF_STATUS send_obss_disable_cmd_tlv(wmi_unified_t wmi_handle, + uint8_t vdev_id) +{ + QDF_STATUS status; + wmi_buf_t buf; + wmi_obss_scan_disable_cmd_fixed_param *cmd; + int len = sizeof(*cmd); + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) + return QDF_STATUS_E_NOMEM; + + wmi_debug("cmd %x vdev_id %d", WMI_OBSS_SCAN_DISABLE_CMDID, vdev_id); + + cmd = (wmi_obss_scan_disable_cmd_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_obss_scan_disable_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_obss_scan_disable_cmd_fixed_param)); + + cmd->vdev_id = vdev_id; + status = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_OBSS_SCAN_DISABLE_CMDID); + if (QDF_IS_STATUS_ERROR(status)) + wmi_buf_free(buf); + + return status; +} + /** * wmi_set_pno_channel_prediction() - Set PNO channel prediction * @buf_ptr: Buffer passed by upper layers @@ -15005,6 +15043,7 @@ struct wmi_ops tlv_ops = { #endif .send_pno_stop_cmd = send_pno_stop_cmd_tlv, .send_pno_start_cmd = send_pno_start_cmd_tlv, + .send_obss_disable_cmd = send_obss_disable_cmd_tlv, .send_nlo_mawc_cmd = send_nlo_mawc_cmd_tlv, #ifdef WLAN_FEATURE_LINK_LAYER_STATS .send_process_ll_stats_clear_cmd = send_process_ll_stats_clear_cmd_tlv,