1 /* 2 * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /** 20 * DOC: Add host 11d scan utility functions 21 */ 22 23 #include <wlan_scan_public_structs.h> 24 #include <wlan_scan_ucfg_api.h> 25 26 #include "reg_priv_objs.h" 27 28 #include "reg_host_11d.h" 29 #include "reg_services_common.h" 30 31 static QDF_STATUS reg_11d_scan_trigger_handler( 32 struct wlan_regulatory_psoc_priv_obj *soc_reg) 33 { 34 struct scan_start_request *req; 35 struct wlan_objmgr_vdev *vdev; 36 QDF_STATUS status; 37 38 req = qdf_mem_malloc(sizeof(*req)); 39 if (!req) 40 return QDF_STATUS_E_NOMEM; 41 42 vdev = wlan_objmgr_get_vdev_by_id_from_psoc( 43 soc_reg->psoc_ptr, 44 soc_reg->vdev_id_for_11d_scan, 45 WLAN_REGULATORY_SB_ID); 46 if (!vdev) { 47 reg_err("vdev object is NULL id %d", 48 soc_reg->vdev_id_for_11d_scan); 49 qdf_mem_free(req); 50 return QDF_STATUS_E_FAILURE; 51 } 52 53 ucfg_scan_init_default_params(vdev, req); 54 55 req->scan_req.scan_id = ucfg_scan_get_scan_id(soc_reg->psoc_ptr); 56 if (!req->scan_req.scan_id) { 57 wlan_objmgr_vdev_release_ref(vdev, WLAN_REGULATORY_SB_ID); 58 qdf_mem_free(req); 59 reg_err("Invalid scan ID"); 60 return QDF_STATUS_E_FAILURE; 61 } 62 soc_reg->scan_id = req->scan_req.scan_id; 63 req->scan_req.vdev_id = soc_reg->vdev_id_for_11d_scan; 64 req->scan_req.scan_req_id = soc_reg->scan_req_id; 65 req->scan_req.scan_priority = SCAN_PRIORITY_LOW; 66 req->scan_req.scan_f_passive = false; 67 68 status = ucfg_scan_start(req); 69 reg_nofl_debug("11d scan trigger vdev %d scan_id %d req_id %d status %d", 70 soc_reg->vdev_id_for_11d_scan, soc_reg->scan_id, 71 soc_reg->scan_req_id, status); 72 73 if (status != QDF_STATUS_SUCCESS) 74 /* Don't free req here, ucfg_scan_start will do free */ 75 reg_err("11d scan req failed vdev %d", 76 soc_reg->vdev_id_for_11d_scan); 77 78 wlan_objmgr_vdev_release_ref(vdev, WLAN_REGULATORY_SB_ID); 79 80 return status; 81 } 82 83 static void reg_11d_scan_event_cb( 84 struct wlan_objmgr_vdev *vdev, 85 struct scan_event *event, void *arg) 86 { 87 }; 88 89 QDF_STATUS reg_11d_host_scan( 90 struct wlan_regulatory_psoc_priv_obj *soc_reg) 91 { 92 QDF_STATUS status = QDF_STATUS_SUCCESS; 93 94 reg_debug("host 11d enabled %d, inited: %d", soc_reg->enable_11d_supp, 95 soc_reg->is_host_11d_inited); 96 if (!soc_reg->is_host_11d_inited) 97 return QDF_STATUS_E_FAILURE; 98 99 if (soc_reg->enable_11d_supp) { 100 qdf_mc_timer_stop(&soc_reg->timer); 101 status = reg_11d_scan_trigger_handler(soc_reg); 102 if (status != QDF_STATUS_SUCCESS) 103 return status; 104 105 qdf_mc_timer_start(&soc_reg->timer, soc_reg->scan_11d_interval); 106 } else { 107 qdf_mc_timer_stop(&soc_reg->timer); 108 } 109 return status; 110 } 111 112 static void reg_11d_scan_timer(void *context) 113 { 114 struct wlan_regulatory_psoc_priv_obj *soc_reg = context; 115 116 reg_debug("11d scan timeout"); 117 118 if (!soc_reg) 119 return; 120 121 reg_11d_host_scan(soc_reg); 122 } 123 124 QDF_STATUS reg_11d_host_scan_init(struct wlan_objmgr_psoc *psoc) 125 { 126 struct wlan_regulatory_psoc_priv_obj *soc_reg; 127 128 soc_reg = reg_get_psoc_obj(psoc); 129 if (!soc_reg) { 130 reg_err("reg psoc private obj is NULL"); 131 return QDF_STATUS_E_FAULT; 132 } 133 134 if (soc_reg->is_host_11d_inited) { 135 reg_debug("host 11d scan are already inited"); 136 return QDF_STATUS_SUCCESS; 137 } 138 soc_reg->scan_req_id = 139 ucfg_scan_register_requester(psoc, "11d", 140 reg_11d_scan_event_cb, 141 soc_reg); 142 qdf_mc_timer_init(&soc_reg->timer, QDF_TIMER_TYPE_SW, 143 reg_11d_scan_timer, soc_reg); 144 145 soc_reg->is_host_11d_inited = true; 146 reg_debug("reg 11d scan inited"); 147 148 return QDF_STATUS_SUCCESS; 149 } 150 151 QDF_STATUS reg_11d_host_scan_deinit(struct wlan_objmgr_psoc *psoc) 152 { 153 struct wlan_regulatory_psoc_priv_obj *soc_reg; 154 155 soc_reg = reg_get_psoc_obj(psoc); 156 if (!soc_reg) { 157 reg_err("reg psoc private obj is NULL"); 158 return QDF_STATUS_E_FAULT; 159 } 160 161 if (!soc_reg->is_host_11d_inited) { 162 reg_debug("host 11d scan are not inited"); 163 return QDF_STATUS_SUCCESS; 164 } 165 qdf_mc_timer_stop(&soc_reg->timer); 166 qdf_mc_timer_destroy(&soc_reg->timer); 167 ucfg_scan_unregister_requester(psoc, soc_reg->scan_req_id); 168 soc_reg->is_host_11d_inited = false; 169 reg_debug("reg 11d scan deinit"); 170 171 return QDF_STATUS_SUCCESS; 172 } 173