xref: /wlan-dirver/qca-wifi-host-cmn/umac/regulatory/core/src/reg_host_11d.c (revision 0626a4da6c07f30da06dd6747e8cc290a60371d8)
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