xref: /wlan-dirver/qca-wifi-host-cmn/umac/regulatory/core/src/reg_host_11d.c (revision dd4dc88b837a295134aa9869114a2efee0f4894b)
1 /*
2  * Copyright (c) 2018-2019 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_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 			reg_err("11d scan trigger failed!");
104 			return status;
105 		}
106 
107 		qdf_mc_timer_start(&soc_reg->timer, soc_reg->scan_11d_interval);
108 	} else {
109 		qdf_mc_timer_stop(&soc_reg->timer);
110 	}
111 	return status;
112 }
113 
114 static void reg_11d_scan_timer(void *context)
115 {
116 	struct wlan_regulatory_psoc_priv_obj *soc_reg = context;
117 
118 	reg_debug("11d scan timeout");
119 
120 	if (!soc_reg)
121 		return;
122 
123 	reg_11d_host_scan(soc_reg);
124 }
125 
126 QDF_STATUS reg_11d_host_scan_init(struct wlan_objmgr_psoc *psoc)
127 {
128 	struct wlan_regulatory_psoc_priv_obj *soc_reg;
129 
130 	soc_reg = reg_get_psoc_obj(psoc);
131 	if (!soc_reg) {
132 		reg_err("reg psoc private obj is NULL");
133 		return QDF_STATUS_E_FAULT;
134 	}
135 
136 	if (soc_reg->is_host_11d_inited) {
137 		reg_debug("host 11d scan are already inited");
138 		return QDF_STATUS_SUCCESS;
139 	}
140 	soc_reg->scan_req_id =
141 		ucfg_scan_register_requester(psoc, "11d",
142 					     reg_11d_scan_event_cb,
143 					     soc_reg);
144 	qdf_mc_timer_init(&soc_reg->timer, QDF_TIMER_TYPE_SW,
145 			  reg_11d_scan_timer, soc_reg);
146 
147 	soc_reg->is_host_11d_inited = true;
148 	reg_debug("reg 11d scan inited");
149 
150 	return QDF_STATUS_SUCCESS;
151 }
152 
153 QDF_STATUS reg_11d_host_scan_deinit(struct wlan_objmgr_psoc *psoc)
154 {
155 	struct wlan_regulatory_psoc_priv_obj *soc_reg;
156 
157 	soc_reg = reg_get_psoc_obj(psoc);
158 	if (!soc_reg) {
159 		reg_err("reg psoc private obj is NULL");
160 		return QDF_STATUS_E_FAULT;
161 	}
162 
163 	if (!soc_reg->is_host_11d_inited) {
164 		reg_debug("host 11d scan are not inited");
165 		return QDF_STATUS_SUCCESS;
166 	}
167 	qdf_mc_timer_stop(&soc_reg->timer);
168 	qdf_mc_timer_destroy(&soc_reg->timer);
169 	ucfg_scan_unregister_requester(psoc, soc_reg->scan_req_id);
170 	soc_reg->is_host_11d_inited = false;
171 	reg_debug("reg 11d scan deinit");
172 
173 	return QDF_STATUS_SUCCESS;
174 }
175