1 /* 2 * Copyright (c) 2018 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 #include "reg_services.h" 26 #include "reg_priv.h" 27 #include "reg_host_11d.h" 28 29 static QDF_STATUS reg_11d_scan_trigger_handler( 30 struct wlan_regulatory_psoc_priv_obj *soc_reg) 31 { 32 struct scan_start_request *req; 33 struct wlan_objmgr_vdev *vdev; 34 QDF_STATUS status; 35 36 req = qdf_mem_malloc(sizeof(*req)); 37 if (!req) 38 return QDF_STATUS_E_NOMEM; 39 40 vdev = wlan_objmgr_get_vdev_by_id_from_psoc( 41 soc_reg->psoc_ptr, 42 soc_reg->vdev_id_for_11d_scan, 43 WLAN_REGULATORY_SB_ID); 44 if (!vdev) { 45 reg_err("vdev object is NULL id %d", 46 soc_reg->vdev_id_for_11d_scan); 47 qdf_mem_free(req); 48 return QDF_STATUS_E_FAILURE; 49 } 50 51 ucfg_scan_init_default_params(vdev, req); 52 53 req->scan_req.scan_id = ucfg_scan_get_scan_id(soc_reg->psoc_ptr); 54 if (!req->scan_req.scan_id) { 55 wlan_objmgr_vdev_release_ref(vdev, WLAN_REGULATORY_SB_ID); 56 qdf_mem_free(req); 57 reg_err("Invalid scan ID"); 58 return QDF_STATUS_E_FAILURE; 59 } 60 soc_reg->scan_id = req->scan_req.scan_id; 61 req->scan_req.vdev_id = soc_reg->vdev_id_for_11d_scan; 62 req->scan_req.scan_req_id = soc_reg->scan_req_id; 63 req->scan_req.scan_priority = SCAN_PRIORITY_LOW; 64 req->scan_req.scan_f_passive = false; 65 66 status = ucfg_scan_start(req); 67 reg_debug("11d scan trigger vdev %d scan_id %d req_id %d status %d", 68 soc_reg->vdev_id_for_11d_scan, soc_reg->scan_id, 69 soc_reg->scan_req_id, status); 70 71 if (status != QDF_STATUS_SUCCESS) 72 /* Don't free req here, ucfg_scan_start will do free */ 73 reg_err("11d scan req failed vdev %d", 74 soc_reg->vdev_id_for_11d_scan); 75 76 wlan_objmgr_vdev_release_ref(vdev, WLAN_REGULATORY_SB_ID); 77 78 return status; 79 } 80 81 static void reg_11d_scan_event_cb( 82 struct wlan_objmgr_vdev *vdev, 83 struct scan_event *event, void *arg) 84 { 85 }; 86 87 QDF_STATUS reg_11d_host_scan( 88 struct wlan_regulatory_psoc_priv_obj *soc_reg) 89 { 90 QDF_STATUS status = QDF_STATUS_SUCCESS; 91 92 reg_debug("host 11d enabled %d, inited: %d", soc_reg->enable_11d_supp, 93 soc_reg->is_host_11d_inited); 94 if (!soc_reg->is_host_11d_inited) 95 return QDF_STATUS_E_FAILURE; 96 97 if (soc_reg->enable_11d_supp) { 98 qdf_mc_timer_stop(&soc_reg->timer); 99 status = reg_11d_scan_trigger_handler(soc_reg); 100 if (status != QDF_STATUS_SUCCESS) { 101 reg_err("11d scan trigger failed!"); 102 return status; 103 } 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