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