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
reg_11d_scan_trigger_handler(struct wlan_regulatory_psoc_priv_obj * soc_reg)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
reg_11d_scan_event_cb(struct wlan_objmgr_vdev * vdev,struct scan_event * event,void * arg)83 static void reg_11d_scan_event_cb(
84 struct wlan_objmgr_vdev *vdev,
85 struct scan_event *event, void *arg)
86 {
87 };
88
reg_11d_host_scan(struct wlan_regulatory_psoc_priv_obj * soc_reg)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
reg_11d_scan_timer(void * context)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
reg_11d_host_scan_init(struct wlan_objmgr_psoc * psoc)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
reg_11d_host_scan_deinit(struct wlan_objmgr_psoc * psoc)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