From 3516552a3cb6cd8c6f889c16ccf16054a31cc761 Mon Sep 17 00:00:00 2001 From: Guisen Yang Date: Mon, 19 Apr 2021 17:17:26 +0800 Subject: [PATCH] qcacmn: Disable obss scan before suspend When obss scan is enabled, FW will trigger scan periodically by a timer. If a scan was triggered, FW need to access host memory for data transfer. Occasionally, suspend may happen during one scan, then FW is unable to access host memory and fw will crash. So disable the obss scan before suspend. Change-Id: Ie507da929a3701473cb57888e96e702e34d4c95a CRs-Fixed: 2927239 --- target_if/scan/src/target_if_scan.c | 17 +++++++- .../lmac_if/inc/wlan_lmac_if_def.h | 3 ++ umac/scan/core/src/wlan_scan_main.h | 2 + umac/scan/core/src/wlan_scan_manager.c | 33 ++++++++++++++++ umac/scan/core/src/wlan_scan_manager.h | 12 +++++- umac/scan/dispatcher/inc/wlan_scan_tgt_api.h | 11 +++++- umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h | 9 +++++ umac/scan/dispatcher/src/wlan_scan_tgt_api.c | 30 +++++++++++++- umac/scan/dispatcher/src/wlan_scan_ucfg_api.c | 20 +++++++++- wmi/inc/wmi_unified_api.h | 12 ++++++ wmi/inc/wmi_unified_priv.h | 2 + wmi/src/wmi_unified_api.c | 10 +++++ wmi/src/wmi_unified_tlv.c | 39 +++++++++++++++++++ 13 files changed, 194 insertions(+), 6 deletions(-) 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,