xref: /wlan-driver/qcacld-3.0/core/hdd/src/wlan_hdd_ocb.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: wlan_hdd_ocb.c
22  *
23  * WLAN Host Device Driver 802.11p OCB implementation
24  */
25 
26 #include "cds_sched.h"
27 #include "wlan_hdd_assoc.h"
28 #include "osif_sync.h"
29 #include "wlan_hdd_main.h"
30 #include "wlan_hdd_ocb.h"
31 #include "wlan_hdd_trace.h"
32 #include "wlan_osif_request_manager.h"
33 #include "wlan_tgt_def_config.h"
34 #include "sch_api.h"
35 #include "wma_api.h"
36 #include <cdp_txrx_cmn.h>
37 #include <cdp_txrx_peer_ops.h>
38 #include <cdp_txrx_handle.h>
39 #include "wlan_ocb_public_structs.h"
40 #include "wlan_ocb_ucfg_api.h"
41 #include <cdp_txrx_cmn.h>
42 #include <cdp_txrx_peer_ops.h>
43 #include <cdp_txrx_handle.h>
44 #include <cdp_txrx_ocb.h>
45 #include "ol_txrx.h"
46 #include "wlan_hdd_object_manager.h"
47 #include "wlan_dp_ucfg_api.h"
48 
49 /* Structure definitions for WLAN_SET_DOT11P_CHANNEL_SCHED */
50 #define AIFSN_MIN		(2)
51 #define AIFSN_MAX		(15)
52 #define CW_MIN			(1)
53 #define CW_MAX			(10)
54 
55 /* Maximum time(ms) to wait for OCB operations */
56 #define WLAN_WAIT_TIME_OCB_CMD 1500
57 
58 /**
59  * dot11p_validate_qos_params() - Check if QoS parameters are valid
60  * @qos_params:   Array of QoS parameters
61  *
62  * Return: 0 on success. error code on failure.
63  */
dot11p_validate_qos_params(struct ocb_wmm_param qos_params[])64 static int dot11p_validate_qos_params(struct ocb_wmm_param qos_params[])
65 {
66 	int i;
67 
68 	for (i = 0; i < QCA_WLAN_AC_ALL; i++) {
69 		if ((!qos_params[i].aifsn) && (!qos_params[i].cwmin)
70 				&& (!qos_params[i].cwmax))
71 			continue;
72 
73 		/* Validate AIFSN */
74 		if ((qos_params[i].aifsn < AIFSN_MIN)
75 				|| (qos_params[i].aifsn > AIFSN_MAX)) {
76 			hdd_err("Invalid QoS parameter aifsn %d",
77 				qos_params[i].aifsn);
78 			return -EINVAL;
79 		}
80 
81 		/* Validate CWMin */
82 		if ((qos_params[i].cwmin < CW_MIN)
83 				|| (qos_params[i].cwmin > CW_MAX)) {
84 			hdd_err("Invalid QoS parameter cwmin %d",
85 				qos_params[i].cwmin);
86 			return -EINVAL;
87 		}
88 
89 		/* Validate CWMax */
90 		if ((qos_params[i].cwmax < CW_MIN)
91 				|| (qos_params[i].cwmax > CW_MAX)) {
92 			hdd_err("Invalid QoS parameter cwmax %d",
93 				qos_params[i].cwmax);
94 			return -EINVAL;
95 		}
96 	}
97 
98 	return 0;
99 }
100 
101 /**
102  * dot11p_validate_channel() - validates a DSRC channel
103  * @wiphy: pointer to the wiphy
104  * @channel_freq: the channel's center frequency
105  * @bandwidth: the channel's bandwidth
106  * @tx_power: transmit power
107  * @reg_power: (output) the max tx power from the regulatory domain
108  * @antenna_max: (output) the max antenna gain from the regulatory domain
109  *
110  * Return: 0 if the channel is valid, error code otherwise.
111  */
dot11p_validate_channel(struct wiphy * wiphy,uint32_t channel_freq,uint32_t bandwidth,uint32_t tx_power,uint8_t * reg_power,uint8_t * antenna_max)112 static int dot11p_validate_channel(struct wiphy *wiphy,
113 				   uint32_t channel_freq, uint32_t bandwidth,
114 				   uint32_t tx_power, uint8_t *reg_power,
115 				   uint8_t *antenna_max)
116 {
117 	int band_idx, channel_idx;
118 	struct ieee80211_supported_band *current_band;
119 	struct ieee80211_channel *current_channel;
120 
121 	for (band_idx = 0; band_idx < HDD_NUM_NL80211_BANDS; band_idx++) {
122 		current_band = wiphy->bands[band_idx];
123 		if (!current_band)
124 			continue;
125 
126 		for (channel_idx = 0; channel_idx < current_band->n_channels;
127 		      channel_idx++) {
128 			current_channel = &current_band->channels[channel_idx];
129 
130 			if (channel_freq == current_channel->center_freq) {
131 				if (current_channel->flags &
132 				    IEEE80211_CHAN_DISABLED)
133 					return -EINVAL;
134 
135 				if (reg_power)
136 					*reg_power =
137 						current_channel->max_reg_power;
138 				if (antenna_max)
139 					*antenna_max =
140 						current_channel->
141 						max_antenna_gain;
142 
143 				switch (bandwidth) {
144 				case 0:
145 					if (current_channel->flags &
146 					    IEEE80211_CHAN_NO_10MHZ)
147 						bandwidth = 5;
148 					else if (current_channel->flags &
149 						 IEEE80211_CHAN_NO_20MHZ)
150 						bandwidth = 10;
151 					else
152 						bandwidth = 20;
153 					break;
154 				case 5:
155 					break;
156 				case 10:
157 					if (current_channel->flags &
158 					    IEEE80211_CHAN_NO_10MHZ)
159 						return -EINVAL;
160 					break;
161 				case 20:
162 					if (current_channel->flags &
163 					    IEEE80211_CHAN_NO_20MHZ)
164 						return -EINVAL;
165 					break;
166 				default:
167 					return -EINVAL;
168 				}
169 
170 				if (tx_power > current_channel->max_power)
171 					return -EINVAL;
172 
173 				return 0;
174 			}
175 		}
176 	}
177 
178 	return -EINVAL;
179 }
180 
181 /**
182  * hdd_ocb_validate_config() - Validates the config data
183  * @adapter: Pointer to HDD Adapter
184  * @config: configuration to be validated
185  *
186  * Return: 0 on success.
187  */
hdd_ocb_validate_config(struct hdd_adapter * adapter,struct ocb_config * config)188 static int hdd_ocb_validate_config(struct hdd_adapter *adapter,
189 				   struct ocb_config *config)
190 {
191 	int i;
192 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
193 
194 	for (i = 0; i < config->channel_count; i++) {
195 		if (dot11p_validate_channel(hdd_ctx->wiphy,
196 					    config->channels[i].chan_freq,
197 					    config->channels[i].bandwidth,
198 					    config->channels[i].max_pwr,
199 					    &config->channels[i].reg_pwr,
200 					    &config->channels[i].antenna_max)) {
201 			hdd_err("Invalid channel frequency %d",
202 				config->channels[i].chan_freq);
203 			return -EINVAL;
204 		}
205 		if (dot11p_validate_qos_params(config->channels[i].qos_params))
206 			return -EINVAL;
207 	}
208 
209 	return 0;
210 }
211 
212 /**
213  * hdd_ocb_register_sta() - Register station with Transport Layer
214  * @adapter: Pointer to HDD Adapter
215  *
216  * This function should be invoked in the OCB Set Schedule callback
217  * to enable the data path in the TL by calling RegisterSTAClient
218  *
219  * Return: 0 on success. -1 on failure.
220  */
hdd_ocb_register_sta(struct hdd_adapter * adapter)221 static int hdd_ocb_register_sta(struct hdd_adapter *adapter)
222 {
223 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
224 	struct ol_txrx_desc_type sta_desc = {0};
225 	struct hdd_station_ctx *sta_ctx;
226 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
227 	struct wlan_objmgr_vdev *vdev;
228 
229 	qdf_status = cdp_peer_register_ocb_peer(soc,
230 				adapter->mac_addr.bytes);
231 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
232 		hdd_err("Error registering OCB Self Peer!");
233 		return -EINVAL;
234 	}
235 
236 	WLAN_ADDR_COPY(sta_desc.peer_addr.bytes, adapter->mac_addr.bytes);
237 	sta_desc.is_qos_enabled = 1;
238 
239 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
240 	if (!vdev)
241 		return -EINVAL;
242 
243 	qdf_status = ucfg_dp_ocb_register_txrx_ops(vdev);
244 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
245 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
246 		hdd_err("Failed to register tx/rx ops. Status= %d", qdf_status);
247 		return -EINVAL;
248 	}
249 
250 	qdf_status = cdp_peer_register(soc, OL_TXRX_PDEV_ID, &sta_desc);
251 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
252 		hdd_err("Failed to register. Status= %d [0x%08X]",
253 		       qdf_status, qdf_status);
254 		return -EINVAL;
255 	}
256 
257 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
258 	qdf_copy_macaddr(&sta_ctx->conn_info.peer_macaddr[0],
259 			 &adapter->mac_addr);
260 
261 	return 0;
262 }
263 
264 /**
265  * hdd_ocb_config_new() - Creates a new OCB configuration
266  * @num_channels: the number of channels
267  * @num_schedule: the schedule size
268  * @ndl_chan_list_len: length in bytes of the NDL chan blob
269  * @ndl_active_state_list_len: length in bytes of the active state blob
270  *
271  * Return: A pointer to the OCB configuration struct, NULL on failure.
272  */
273 static
hdd_ocb_config_new(uint32_t num_channels,uint32_t num_schedule,uint32_t ndl_chan_list_len,uint32_t ndl_active_state_list_len)274 struct ocb_config *hdd_ocb_config_new(uint32_t num_channels,
275 				      uint32_t num_schedule,
276 				      uint32_t ndl_chan_list_len,
277 				      uint32_t ndl_active_state_list_len)
278 {
279 	struct ocb_config *ret = 0;
280 	uint32_t len;
281 	void *cursor;
282 
283 	if (num_channels > CFG_TGT_NUM_OCB_CHANNELS ||
284 			num_schedule > CFG_TGT_NUM_OCB_SCHEDULES)
285 		return NULL;
286 
287 	len = sizeof(*ret) +
288 		num_channels * sizeof(struct ocb_config_chan) +
289 		num_schedule * sizeof(struct ocb_config_schdl) +
290 		ndl_chan_list_len +
291 		ndl_active_state_list_len;
292 
293 	cursor = qdf_mem_malloc(len);
294 	if (!cursor)
295 		goto fail;
296 
297 	ret = cursor;
298 	cursor += sizeof(*ret);
299 
300 	ret->channel_count = num_channels;
301 	ret->channels = cursor;
302 	cursor += num_channels * sizeof(*ret->channels);
303 
304 	ret->schedule_size = num_schedule;
305 	ret->schedule = cursor;
306 	cursor += num_schedule * sizeof(*ret->schedule);
307 
308 	ret->dcc_ndl_chan_list = cursor;
309 	cursor += ndl_chan_list_len;
310 
311 	ret->dcc_ndl_active_state_list = cursor;
312 	cursor += ndl_active_state_list_len;
313 
314 	return ret;
315 
316 fail:
317 	qdf_mem_free(ret);
318 	return NULL;
319 }
320 
321 struct hdd_ocb_set_config_priv {
322 	int status;
323 };
324 
325 
326 /**
327  * hdd_ocb_set_config_callback() - OCB set config callback function
328  * @context_ptr: OCB call context
329  * @response_ptr: Pointer to response structure
330  *
331  * This function is registered as a callback with the lower layers
332  * and is used to respond with the status of a OCB set config command.
333  */
hdd_ocb_set_config_callback(void * context_ptr,void * response_ptr)334 static void hdd_ocb_set_config_callback(void *context_ptr, void *response_ptr)
335 {
336 	struct osif_request *request;
337 	struct hdd_ocb_set_config_priv *priv;
338 	struct ocb_set_config_response *response = response_ptr;
339 
340 	request = osif_request_get(context_ptr);
341 	if (!request) {
342 		hdd_err("Obsolete request");
343 		return;
344 	}
345 	priv = osif_request_priv(request);
346 
347 	if (response && response->status)
348 		hdd_warn("Operation failed: %d", response->status);
349 
350 	if (response && (response->status == OCB_CHANNEL_CONFIG_SUCCESS))
351 		priv->status = 0;
352 	else
353 		priv->status = -EINVAL;
354 
355 	osif_request_complete(request);
356 	osif_request_put(request);
357 }
358 
359 /**
360  * hdd_ocb_set_config_req() - Send an OCB set config request
361  * @adapter: a pointer to the adapter
362  * @config: a pointer to the OCB configuration
363  *
364  * Return: 0 on success.
365  */
hdd_ocb_set_config_req(struct hdd_adapter * adapter,struct ocb_config * config)366 static int hdd_ocb_set_config_req(struct hdd_adapter *adapter,
367 				  struct ocb_config *config)
368 {
369 	int rc;
370 	QDF_STATUS status;
371 	void *cookie;
372 	struct osif_request *request;
373 	struct hdd_ocb_set_config_priv *priv;
374 	static const struct osif_request_params params = {
375 		.priv_size = sizeof(*priv),
376 		.timeout_ms = WLAN_WAIT_TIME_OCB_CMD,
377 	};
378 	struct wlan_objmgr_vdev *vdev;
379 
380 	if (hdd_ocb_validate_config(adapter, config)) {
381 		hdd_err("The configuration is invalid");
382 		return -EINVAL;
383 	}
384 
385 	request = osif_request_alloc(&params);
386 	if (!request) {
387 		hdd_err("Request allocation failure");
388 		return -ENOMEM;
389 	}
390 	cookie = osif_request_cookie(request);
391 
392 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_OCB_ID);
393 	if (!vdev) {
394 		rc = -EINVAL;
395 		goto end;
396 	}
397 
398 	hdd_debug("Disabling queues");
399 	wlan_hdd_netif_queue_control(adapter,
400 				     WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
401 				     WLAN_CONTROL_PATH);
402 
403 	status = ucfg_ocb_set_channel_config(vdev, config,
404 					     hdd_ocb_set_config_callback,
405 					     cookie);
406 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_OCB_ID);
407 	if (QDF_IS_STATUS_ERROR(status)) {
408 		hdd_err("Failed to set channel config.");
409 		rc = qdf_status_to_os_return(status);
410 		goto end;
411 	}
412 
413 	/* Wait for the function to complete. */
414 	rc = osif_request_wait_for_response(request);
415 	if (rc) {
416 		hdd_err("Operation timed out");
417 		goto end;
418 	}
419 
420 	priv = osif_request_priv(request);
421 	rc = priv->status;
422 	if (rc) {
423 		hdd_err("Operation failed: %d", rc);
424 		goto end;
425 	}
426 
427 	/*
428 	 * OCB set config command successful.
429 	 * Open the TX data path
430 	 */
431 	if (!hdd_ocb_register_sta(adapter))
432 		wlan_hdd_netif_queue_control(adapter,
433 					WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
434 					WLAN_CONTROL_PATH);
435 
436 end:
437 	osif_request_put(request);
438 
439 	return rc;
440 }
441 
442 #ifdef WLAN_WEXT_SUPPORT_ENABLE
443 /**
444  * __iw_set_dot11p_channel_sched() - Handler for WLAN_SET_DOT11P_CHANNEL_SCHED
445  *				     ioctl
446  * @dev: Pointer to net_device structure
447  * @info: IW Request Info
448  * @wrqu: IW Request Userspace Data Pointer
449  * @extra: IW Request Kernel Data Pointer
450  *
451  * Return: 0 on success
452  */
__iw_set_dot11p_channel_sched(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)453 static int __iw_set_dot11p_channel_sched(struct net_device *dev,
454 					 struct iw_request_info *info,
455 					 union iwreq_data *wrqu, char *extra)
456 {
457 	int rc;
458 	struct dot11p_channel_sched *sched;
459 	struct hdd_context *hdd_ctx;
460 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
461 	struct ocb_config *config = NULL;
462 	uint8_t *mac_addr;
463 	int i, j;
464 	struct ocb_config_chan *curr_chan;
465 
466 	hdd_enter_dev(dev);
467 
468 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
469 	rc = wlan_hdd_validate_context(hdd_ctx);
470 	if (0 != rc)
471 		return rc;
472 
473 	rc = hdd_check_private_wext_control(hdd_ctx, info);
474 	if (0 != rc)
475 		return rc;
476 
477 	if (adapter->device_mode != QDF_OCB_MODE) {
478 		hdd_err("Device not in OCB mode!");
479 		return -EINVAL;
480 	}
481 
482 	sched = (struct dot11p_channel_sched *)extra;
483 
484 	/* Scheduled slots same as num channels for compatibility */
485 	config = hdd_ocb_config_new(sched->num_channels, sched->num_channels,
486 				    0, 0);
487 	if (!config) {
488 		hdd_err("Failed to allocate memory!");
489 		return -ENOMEM;
490 	}
491 
492 	/* Identify the vdev interface */
493 	config->vdev_id = adapter->deflink->vdev_id;
494 
495 	/* Release all the mac addresses used for OCB */
496 	for (i = 0; i < adapter->ocb_mac_addr_count; i++) {
497 		wlan_hdd_release_intf_addr(hdd_ctx,
498 					   adapter->ocb_mac_address[i].bytes);
499 	}
500 	adapter->ocb_mac_addr_count = 0;
501 
502 	config->channel_count = 0;
503 	for (i = 0; i < sched->num_channels; i++) {
504 		if (0 == sched->channels[i].channel_freq)
505 			continue;
506 
507 		curr_chan = &(config->channels[config->channel_count]);
508 
509 		curr_chan->chan_freq = sched->channels[i].channel_freq;
510 		/*
511 		 * tx_power is divided by 2 because ocb_channel.tx_power is
512 		 * in half dB increments and ocb_config_channel.max_pwr
513 		 * is in 1 dB increments.
514 		 */
515 		curr_chan->max_pwr = sched->channels[i].tx_power / 2;
516 		curr_chan->bandwidth = sched->channels[i].channel_bandwidth;
517 		/* assume 10 as default if not provided */
518 		if (curr_chan->bandwidth == 0)
519 			curr_chan->bandwidth = 10;
520 
521 		/*
522 		 * Setup locally administered mac addresses for each channel.
523 		 * First channel uses the adapter's address.
524 		 */
525 		if (i == 0) {
526 			qdf_copy_macaddr(&curr_chan->mac_address,
527 				     &adapter->mac_addr);
528 		} else {
529 			mac_addr = wlan_hdd_get_intf_addr(hdd_ctx,
530 							  adapter->device_mode);
531 			if (!mac_addr) {
532 				hdd_err("Cannot obtain mac address");
533 				rc = -EINVAL;
534 				goto fail;
535 			}
536 			qdf_mem_copy(config->channels[
537 				     config->channel_count].mac_address.bytes,
538 				     mac_addr, sizeof(tSirMacAddr));
539 			/* Save the mac address to release later */
540 			qdf_mem_copy(adapter->ocb_mac_address[
541 				     adapter->ocb_mac_addr_count].bytes,
542 				     mac_addr, QDF_MAC_ADDR_SIZE);
543 			adapter->ocb_mac_addr_count++;
544 		}
545 
546 		for (j = 0; j < QCA_WLAN_AC_ALL; j++) {
547 			curr_chan->qos_params[j].aifsn =
548 				sched->channels[i].qos_params[j].aifsn;
549 			curr_chan->qos_params[j].cwmin =
550 				sched->channels[i].qos_params[j].cwmin;
551 			curr_chan->qos_params[j].cwmax =
552 				sched->channels[i].qos_params[j].cwmax;
553 		}
554 
555 		config->channel_count++;
556 	}
557 
558 	/*
559 	 * Scheduled slots same as num channels for compatibility with
560 	 * legacy use.
561 	 */
562 	for (i = 0; i < sched->num_channels; i++) {
563 		config->schedule[i].chan_freq = sched->channels[i].channel_freq;
564 		config->schedule[i].guard_interval =
565 			sched->channels[i].start_guard_interval;
566 		config->schedule[i].total_duration =
567 			sched->channels[i].duration;
568 	}
569 
570 	rc = hdd_ocb_set_config_req(adapter, config);
571 	if (rc) {
572 		hdd_err("Error while setting OCB config");
573 		goto fail;
574 	}
575 
576 	rc = 0;
577 
578 fail:
579 	qdf_mem_free(config);
580 	return rc;
581 }
582 
583 /**
584  * iw_set_dot11p_channel_sched() - IOCTL interface for setting channel schedule
585  * @dev: Pointer to net_device structure
586  * @info: IW Request Info
587  * @wrqu: IW Request Userspace Data Pointer
588  * @extra: IW Request Kernel Data Pointer
589  *
590  * Return: 0 on success.
591  */
iw_set_dot11p_channel_sched(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)592 int iw_set_dot11p_channel_sched(struct net_device *dev,
593 				struct iw_request_info *info,
594 				union iwreq_data *wrqu, char *extra)
595 {
596 	int errno;
597 	struct osif_vdev_sync *vdev_sync;
598 
599 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
600 	if (errno)
601 		return errno;
602 
603 	errno = __iw_set_dot11p_channel_sched(dev, info, wrqu, extra);
604 
605 	osif_vdev_sync_op_stop(vdev_sync);
606 
607 	return errno;
608 }
609 #endif /* WLAN_WEXT_SUPPORT_ENABLE */
610 
611 const struct nla_policy qca_wlan_vendor_ocb_set_config_policy[
612 		QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_MAX + 1] = {
613 	[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_COUNT] = {
614 		.type = NLA_U32
615 	},
616 	[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_SIZE] = {
617 		.type = NLA_U32
618 	},
619 	[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_ARRAY] = {
620 		.type = NLA_BINARY
621 	},
622 	[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_ARRAY] = {
623 		.type = NLA_BINARY
624 	},
625 	[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_CHANNEL_ARRAY] = {
626 		.type = NLA_BINARY
627 	},
628 	[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_ACTIVE_STATE_ARRAY] = {
629 		.type = NLA_BINARY
630 	},
631 	[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS] = {
632 		.type = NLA_U32
633 	},
634 };
635 
636 const struct nla_policy qca_wlan_vendor_ocb_set_utc_time_policy[
637 		QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_MAX + 1] = {
638 	[QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_VALUE] = {
639 		.type = NLA_BINARY, .len = SIZE_UTC_TIME
640 	},
641 	[QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_ERROR] = {
642 		.type = NLA_BINARY, .len = SIZE_UTC_TIME_ERROR
643 	},
644 };
645 
646 const struct nla_policy qca_wlan_vendor_ocb_start_timing_advert_policy[
647 		QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_MAX + 1] = {
648 	[QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_CHANNEL_FREQ] = {
649 		.type = NLA_U32
650 	},
651 	[QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_REPEAT_RATE] = {
652 		.type = NLA_U32
653 	},
654 };
655 
656 const struct nla_policy  qca_wlan_vendor_ocb_stop_timing_advert_policy[
657 		QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_MAX + 1] = {
658 	[QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_CHANNEL_FREQ] = {
659 		.type = NLA_U32
660 	},
661 };
662 
663 static const struct nla_policy qca_wlan_vendor_ocb_get_tsf_timer_resp[] = {
664 	[QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH] = {
665 		.type = NLA_U32
666 	},
667 	[QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW] = {
668 		.type = NLA_U32
669 	},
670 };
671 
672 const struct nla_policy qca_wlan_vendor_dcc_get_stats[] = {
673 	[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_CHANNEL_COUNT] = {
674 		.type = NLA_U32
675 	},
676 	[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_REQUEST_ARRAY] = {
677 		.type = NLA_BINARY
678 	},
679 };
680 
681 static const struct nla_policy qca_wlan_vendor_dcc_get_stats_resp[] = {
682 	[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_CHANNEL_COUNT] = {
683 		.type = NLA_U32
684 	},
685 	[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_STATS_ARRAY] = {
686 		.type = NLA_BINARY
687 	},
688 };
689 
690 const struct nla_policy qca_wlan_vendor_dcc_clear_stats[] = {
691 	[QCA_WLAN_VENDOR_ATTR_DCC_CLEAR_STATS_BITMAP] = {
692 		.type = NLA_U32
693 	},
694 };
695 
696 const struct nla_policy qca_wlan_vendor_dcc_update_ndl[
697 		QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_MAX + 1] = {
698 	[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_COUNT] = {
699 		.type = NLA_U32
700 	},
701 	[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_ARRAY] = {
702 		.type = NLA_BINARY
703 	},
704 	[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_ACTIVE_STATE_ARRAY] = {
705 		.type = NLA_BINARY
706 	},
707 };
708 
709 /**
710  * struct wlan_hdd_ocb_config_channel
711  * @chan_freq: frequency of the channel
712  * @bandwidth: bandwidth of the channel, either 10 or 20 MHz
713  * @flags: channel flags
714  * @reserved: reserved padding, set to 0
715  * @qos_params: QoS parameters
716  * @max_pwr: maximum transmit power of the channel (1/2 dBm)
717  * @min_pwr: minimum transmit power of the channel (1/2 dBm)
718  */
719 struct wlan_hdd_ocb_config_channel {
720 	uint32_t chan_freq;
721 	uint32_t bandwidth;
722 	uint16_t flags;
723 	uint8_t reserved[4];
724 	struct sir_qos_params qos_params[QCA_WLAN_AC_ALL];
725 	uint32_t max_pwr;
726 	uint32_t min_pwr;
727 };
728 
wlan_hdd_ocb_config_channel_to_ocb_config_channel(struct ocb_config_chan * dest,struct wlan_hdd_ocb_config_channel * src,uint32_t channel_count)729 static void wlan_hdd_ocb_config_channel_to_ocb_config_channel(
730 	struct ocb_config_chan *dest,
731 	struct wlan_hdd_ocb_config_channel *src,
732 	uint32_t channel_count)
733 {
734 	uint32_t i;
735 
736 	qdf_mem_zero(dest, channel_count * sizeof(*dest));
737 
738 	for (i = 0; i < channel_count; i++) {
739 		dest[i].chan_freq = src[i].chan_freq;
740 		dest[i].bandwidth = src[i].bandwidth;
741 		qdf_mem_copy(dest[i].qos_params, src[i].qos_params,
742 			     sizeof(dest[i].qos_params));
743 		/*
744 		 *  max_pwr and min_pwr are divided by 2 because
745 		 *  ocb_channel_param.max_pwr and min_pwr
746 		 *  are in 1/2 dB increments and
747 		 *  ocb_config_channel.max_pwr and min_pwr are in
748 		 *  1 dB increments.
749 		 */
750 		dest[i].max_pwr = src[i].max_pwr / 2;
751 		dest[i].min_pwr = (src[i].min_pwr + 1) / 2;
752 		dest[i].flags = src[i].flags;
753 	}
754 }
755 
756 /**
757  * __wlan_hdd_cfg80211_ocb_set_config() - Interface for set config command
758  * @wiphy: pointer to the wiphy
759  * @wdev: pointer to the wdev
760  * @data: The netlink data
761  * @data_len: The length of the netlink data in bytes
762  *
763  * Return: 0 on success.
764  */
__wlan_hdd_cfg80211_ocb_set_config(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)765 static int __wlan_hdd_cfg80211_ocb_set_config(struct wiphy *wiphy,
766 					      struct wireless_dev *wdev,
767 					      const void *data,
768 					      int data_len)
769 {
770 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
771 	struct net_device *dev = wdev->netdev;
772 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
773 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_MAX + 1];
774 	struct nlattr *channel_array;
775 	struct nlattr *sched_array;
776 	struct nlattr *ndl_chan_list;
777 	uint32_t ndl_chan_list_len;
778 	struct nlattr *ndl_active_state_list;
779 	uint32_t ndl_active_state_list_len;
780 	uint32_t flags = 0;
781 	int i;
782 	uint32_t channel_count, schedule_size;
783 	struct ocb_config *config;
784 	int rc = -EINVAL;
785 	uint8_t *mac_addr;
786 
787 	hdd_enter_dev(dev);
788 
789 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
790 		hdd_err("Command not allowed in FTM mode");
791 		return -EPERM;
792 	}
793 
794 	if (wlan_hdd_validate_context(hdd_ctx))
795 		return -EINVAL;
796 
797 	if (adapter->device_mode != QDF_OCB_MODE) {
798 		hdd_err("Device not in OCB mode!");
799 		return -EINVAL;
800 	}
801 
802 	/* Parse the netlink message */
803 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_MAX,
804 				    data, data_len,
805 				    qca_wlan_vendor_ocb_set_config_policy)) {
806 		hdd_err("Invalid ATTR");
807 		return -EINVAL;
808 	}
809 
810 	/* Get the number of channels in the schedule */
811 	if (!tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_COUNT]) {
812 		hdd_err("CHANNEL_COUNT is not present");
813 		return -EINVAL;
814 	}
815 	channel_count = nla_get_u32(
816 		tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_COUNT]);
817 
818 	/* Get the size of the channel schedule */
819 	if (!tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_SIZE]) {
820 		hdd_err("SCHEDULE_SIZE is not present");
821 		return -EINVAL;
822 	}
823 	schedule_size = nla_get_u32(
824 		tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_SIZE]);
825 
826 	/* Get the ndl chan array and the ndl active state array. */
827 	ndl_chan_list =
828 		tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_CHANNEL_ARRAY];
829 	ndl_chan_list_len = (ndl_chan_list ? nla_len(ndl_chan_list) : 0);
830 
831 	ndl_active_state_list =
832 		tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_ACTIVE_STATE_ARRAY];
833 	ndl_active_state_list_len = (ndl_active_state_list ?
834 				    nla_len(ndl_active_state_list) : 0);
835 
836 	/* Get the flags */
837 	if (tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS])
838 		flags = nla_get_u32(tb[
839 				QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS]);
840 
841 	config = hdd_ocb_config_new(channel_count, schedule_size,
842 				    ndl_chan_list_len,
843 				    ndl_active_state_list_len);
844 	if (!config) {
845 		hdd_err("Failed to allocate memory!");
846 		return -ENOMEM;
847 	}
848 
849 	config->channel_count = channel_count;
850 	config->schedule_size = schedule_size;
851 	config->flags = flags;
852 
853 	/* Read the channel array */
854 	channel_array = tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_ARRAY];
855 	if (!channel_array) {
856 		hdd_err("No channel present");
857 		goto fail;
858 	}
859 	if (nla_len(channel_array) != channel_count *
860 	    sizeof(struct wlan_hdd_ocb_config_channel)) {
861 		hdd_err("CHANNEL_ARRAY is not the correct size");
862 		goto fail;
863 	}
864 	wlan_hdd_ocb_config_channel_to_ocb_config_channel(
865 	    config->channels, nla_data(channel_array), channel_count);
866 
867 	/* Identify the vdev interface */
868 	config->vdev_id = adapter->deflink->vdev_id;
869 
870 	/* Release all the mac addresses used for OCB */
871 	for (i = 0; i < adapter->ocb_mac_addr_count; i++) {
872 		wlan_hdd_release_intf_addr(hdd_ctx,
873 					   adapter->ocb_mac_address[i].bytes);
874 	}
875 	adapter->ocb_mac_addr_count = 0;
876 
877 	/*
878 	 * Setup locally administered mac addresses for each channel.
879 	 * First channel uses the adapter's address.
880 	 */
881 	for (i = 0; i < config->channel_count; i++) {
882 		if (i == 0) {
883 			qdf_copy_macaddr(&config->channels[i].mac_address,
884 				&adapter->mac_addr);
885 		} else {
886 			mac_addr = wlan_hdd_get_intf_addr(hdd_ctx,
887 							  adapter->device_mode);
888 			if (!mac_addr) {
889 				hdd_err("Cannot obtain mac address");
890 				goto fail;
891 			}
892 			qdf_mem_copy(config->channels[i].mac_address.bytes,
893 				mac_addr, QDF_MAC_ADDR_SIZE);
894 			/* Save the mac address to release later */
895 			qdf_copy_macaddr(&adapter->ocb_mac_address[
896 				     adapter->ocb_mac_addr_count],
897 				     &config->channels[i].mac_address);
898 			adapter->ocb_mac_addr_count++;
899 		}
900 	}
901 
902 	/* Read the schedule array */
903 	sched_array = tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_ARRAY];
904 	if (!sched_array) {
905 		hdd_err("No channel present");
906 		goto fail;
907 	}
908 	if (nla_len(sched_array) != schedule_size * sizeof(*config->schedule)) {
909 		hdd_err("SCHEDULE_ARRAY is not the correct size");
910 		goto fail;
911 	}
912 	qdf_mem_copy(config->schedule, nla_data(sched_array),
913 		nla_len(sched_array));
914 
915 	/* Copy the NDL chan array */
916 	if (ndl_chan_list_len) {
917 		config->dcc_ndl_chan_list_len = ndl_chan_list_len;
918 		qdf_mem_copy(config->dcc_ndl_chan_list, nla_data(ndl_chan_list),
919 			nla_len(ndl_chan_list));
920 	}
921 
922 	/* Copy the NDL active state array */
923 	if (ndl_active_state_list_len) {
924 		config->dcc_ndl_active_state_list_len =
925 			ndl_active_state_list_len;
926 		qdf_mem_copy(config->dcc_ndl_active_state_list,
927 			nla_data(ndl_active_state_list),
928 			nla_len(ndl_active_state_list));
929 	}
930 
931 	rc = hdd_ocb_set_config_req(adapter, config);
932 	if (rc)
933 		hdd_err("Error while setting OCB config: %d", rc);
934 
935 fail:
936 	qdf_mem_free(config);
937 	return rc;
938 }
939 
940 /**
941  * wlan_hdd_cfg80211_ocb_set_config() - Interface for set config command
942  * @wiphy: pointer to the wiphy
943  * @wdev: pointer to the wdev
944  * @data: The netlink data
945  * @data_len: The length of the netlink data in bytes
946  *
947  * Return: 0 on success.
948  */
wlan_hdd_cfg80211_ocb_set_config(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)949 int wlan_hdd_cfg80211_ocb_set_config(struct wiphy *wiphy,
950 				     struct wireless_dev *wdev,
951 				     const void *data,
952 				     int data_len)
953 {
954 	int errno;
955 	struct osif_vdev_sync *vdev_sync;
956 
957 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
958 	if (errno)
959 		return errno;
960 
961 	errno = __wlan_hdd_cfg80211_ocb_set_config(wiphy, wdev, data, data_len);
962 
963 	osif_vdev_sync_op_stop(vdev_sync);
964 
965 	return errno;
966 }
967 
968 /**
969  * __wlan_hdd_cfg80211_ocb_set_utc_time() - Interface for set UTC time command
970  * @wiphy: pointer to the wiphy
971  * @wdev: pointer to the wdev
972  * @data: The netlink data
973  * @data_len: The length of the netlink data in bytes
974  *
975  * Return: 0 on success.
976  */
__wlan_hdd_cfg80211_ocb_set_utc_time(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)977 static int __wlan_hdd_cfg80211_ocb_set_utc_time(struct wiphy *wiphy,
978 						struct wireless_dev *wdev,
979 						const void *data,
980 						int data_len)
981 {
982 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
983 	struct net_device *dev = wdev->netdev;
984 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
985 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_MAX + 1];
986 	struct nlattr *utc_attr;
987 	struct nlattr *time_error_attr;
988 	struct ocb_utc_param *utc;
989 	struct wlan_objmgr_vdev *vdev;
990 	int rc = -EINVAL;
991 
992 	hdd_enter_dev(dev);
993 
994 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
995 		hdd_err("Command not allowed in FTM mode");
996 		return -EPERM;
997 	}
998 
999 	if (wlan_hdd_validate_context(hdd_ctx))
1000 		return -EINVAL;
1001 
1002 	if (adapter->device_mode != QDF_OCB_MODE) {
1003 		hdd_err("Device not in OCB mode!");
1004 		return -EINVAL;
1005 	}
1006 
1007 	if (!wma_is_vdev_up(adapter->deflink->vdev_id)) {
1008 		hdd_err("The device has not been started");
1009 		return -EINVAL;
1010 	}
1011 
1012 	/* Parse the netlink message */
1013 	if (wlan_cfg80211_nla_parse(tb,
1014 				    QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_MAX,
1015 				    data, data_len,
1016 				    qca_wlan_vendor_ocb_set_utc_time_policy)) {
1017 		hdd_err("Invalid ATTR");
1018 		return -EINVAL;
1019 	}
1020 
1021 	/* Read the UTC time */
1022 	utc_attr = tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_VALUE];
1023 	if (!utc_attr) {
1024 		hdd_err("UTC_TIME is not present");
1025 		return -EINVAL;
1026 	}
1027 	if (nla_len(utc_attr) != SIZE_UTC_TIME) {
1028 		hdd_err("UTC_TIME is not the correct size");
1029 		return -EINVAL;
1030 	}
1031 
1032 	/* Read the time error */
1033 	time_error_attr = tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_ERROR];
1034 	if (!time_error_attr) {
1035 		hdd_err("UTC_TIME is not present");
1036 		return -EINVAL;
1037 	}
1038 	if (nla_len(time_error_attr) != SIZE_UTC_TIME_ERROR) {
1039 		hdd_err("UTC_TIME is not the correct size");
1040 		return -EINVAL;
1041 	}
1042 
1043 	utc = qdf_mem_malloc(sizeof(*utc));
1044 	if (!utc)
1045 		return -ENOMEM;
1046 
1047 	utc->vdev_id = adapter->deflink->vdev_id;
1048 	qdf_mem_copy(utc->utc_time, nla_data(utc_attr), SIZE_UTC_TIME);
1049 	qdf_mem_copy(utc->time_error, nla_data(time_error_attr),
1050 		SIZE_UTC_TIME_ERROR);
1051 
1052 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_OCB_ID);
1053 	if (!vdev) {
1054 		rc = -EINVAL;
1055 		goto out;
1056 	}
1057 
1058 	if (ucfg_ocb_set_utc_time(vdev, utc) !=
1059 			QDF_STATUS_SUCCESS) {
1060 		hdd_err("Error while setting UTC time");
1061 		rc = -EINVAL;
1062 	} else {
1063 		rc = 0;
1064 	}
1065 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_OCB_ID);
1066 out:
1067 	qdf_mem_free(utc);
1068 	return rc;
1069 }
1070 
1071 /**
1072  * wlan_hdd_cfg80211_ocb_set_utc_time() - Interface for the set UTC time command
1073  * @wiphy: pointer to the wiphy
1074  * @wdev: pointer to the wdev
1075  * @data: The netlink data
1076  * @data_len: The length of the netlink data in bytes
1077  *
1078  * Return: 0 on success.
1079  */
wlan_hdd_cfg80211_ocb_set_utc_time(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1080 int wlan_hdd_cfg80211_ocb_set_utc_time(struct wiphy *wiphy,
1081 				       struct wireless_dev *wdev,
1082 				       const void *data,
1083 				       int data_len)
1084 {
1085 	int errno;
1086 	struct osif_vdev_sync *vdev_sync;
1087 
1088 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
1089 	if (errno)
1090 		return errno;
1091 
1092 	errno = __wlan_hdd_cfg80211_ocb_set_utc_time(wiphy, wdev,
1093 						     data, data_len);
1094 
1095 	osif_vdev_sync_op_stop(vdev_sync);
1096 
1097 	return errno;
1098 }
1099 
1100 /**
1101  * __wlan_hdd_cfg80211_ocb_start_timing_advert() - Interface for start TA cmd
1102  * @wiphy: pointer to the wiphy
1103  * @wdev: pointer to the wdev
1104  * @data: The netlink data
1105  * @data_len: The length of the netlink data in bytes
1106  *
1107  * Return: 0 on success.
1108  */
1109 static int
__wlan_hdd_cfg80211_ocb_start_timing_advert(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1110 __wlan_hdd_cfg80211_ocb_start_timing_advert(struct wiphy *wiphy,
1111 					    struct wireless_dev *wdev,
1112 					    const void *data,
1113 					    int data_len)
1114 {
1115 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
1116 	struct net_device *dev = wdev->netdev;
1117 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1118 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_MAX + 1];
1119 	struct ocb_timing_advert_param *timing_advert;
1120 	struct wlan_objmgr_vdev *vdev;
1121 	int rc = -EINVAL;
1122 
1123 	hdd_enter_dev(dev);
1124 
1125 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1126 		hdd_err("Command not allowed in FTM mode");
1127 		return -EPERM;
1128 	}
1129 
1130 	if (wlan_hdd_validate_context(hdd_ctx))
1131 		return -EINVAL;
1132 
1133 	if (adapter->device_mode != QDF_OCB_MODE) {
1134 		hdd_err("Device not in OCB mode!");
1135 		return -EINVAL;
1136 	}
1137 
1138 	if (!wma_is_vdev_up(adapter->deflink->vdev_id)) {
1139 		hdd_err("The device has not been started");
1140 		return -EINVAL;
1141 	}
1142 
1143 	timing_advert = qdf_mem_malloc(sizeof(*timing_advert));
1144 	if (!timing_advert)
1145 		return -ENOMEM;
1146 
1147 	timing_advert->vdev_id = adapter->deflink->vdev_id;
1148 
1149 	/* Parse the netlink message */
1150 	if (wlan_cfg80211_nla_parse(tb,
1151 			      QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_MAX,
1152 			      data, data_len,
1153 			      qca_wlan_vendor_ocb_start_timing_advert_policy)) {
1154 		hdd_err("Invalid ATTR");
1155 		goto fail;
1156 	}
1157 
1158 	if (!tb[QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_CHANNEL_FREQ]) {
1159 		hdd_err("CHANNEL_FREQ is not present");
1160 		goto fail;
1161 	}
1162 	timing_advert->chan_freq = nla_get_u32(
1163 		tb[QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_CHANNEL_FREQ]);
1164 
1165 	if (!tb[QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_REPEAT_RATE]) {
1166 		hdd_err("REPEAT_RATE is not present");
1167 		goto fail;
1168 	}
1169 	timing_advert->repeat_rate = nla_get_u32(
1170 		tb[QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_REPEAT_RATE]);
1171 
1172 	timing_advert->template_length =
1173 		sme_ocb_gen_timing_advert_frame(hdd_ctx->mac_handle,
1174 			*(tSirMacAddr *)&adapter->mac_addr.bytes,
1175 			&timing_advert->template_value,
1176 			&timing_advert->timestamp_offset,
1177 			&timing_advert->time_value_offset);
1178 	if (timing_advert->template_length <= 0) {
1179 		hdd_err("Error while generating the TA frame");
1180 		goto fail;
1181 	}
1182 
1183 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_OCB_ID);
1184 	if (!vdev) {
1185 		rc = -EINVAL;
1186 		goto fail;
1187 	}
1188 
1189 	if (ucfg_ocb_start_timing_advert(vdev, timing_advert) !=
1190 			QDF_STATUS_SUCCESS) {
1191 		hdd_err("Error while starting timing advert");
1192 		rc = -EINVAL;
1193 	} else {
1194 		rc = 0;
1195 	}
1196 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_OCB_ID);
1197 
1198 fail:
1199 	if (timing_advert->template_value)
1200 		qdf_mem_free(timing_advert->template_value);
1201 	qdf_mem_free(timing_advert);
1202 	return rc;
1203 }
1204 
1205 /**
1206  * wlan_hdd_cfg80211_ocb_start_timing_advert() - Interface for the start TA cmd
1207  * @wiphy: pointer to the wiphy
1208  * @wdev: pointer to the wdev
1209  * @data: The netlink data
1210  * @data_len: The length of the netlink data in bytes
1211  *
1212  * Return: 0 on success.
1213  */
wlan_hdd_cfg80211_ocb_start_timing_advert(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1214 int wlan_hdd_cfg80211_ocb_start_timing_advert(struct wiphy *wiphy,
1215 					      struct wireless_dev *wdev,
1216 					      const void *data,
1217 					      int data_len)
1218 {
1219 	int errno;
1220 	struct osif_vdev_sync *vdev_sync;
1221 
1222 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
1223 	if (errno)
1224 		return errno;
1225 
1226 	errno = __wlan_hdd_cfg80211_ocb_start_timing_advert(wiphy, wdev,
1227 							    data, data_len);
1228 
1229 	osif_vdev_sync_op_stop(vdev_sync);
1230 
1231 	return errno;
1232 }
1233 
1234 /**
1235  * __wlan_hdd_cfg80211_ocb_stop_timing_advert() - Interface for the stop TA cmd
1236  * @wiphy: pointer to the wiphy
1237  * @wdev: pointer to the wdev
1238  * @data: The netlink data
1239  * @data_len: The length of the netlink data in bytes
1240  *
1241  * Return: 0 on success.
1242  */
1243 static int
__wlan_hdd_cfg80211_ocb_stop_timing_advert(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1244 __wlan_hdd_cfg80211_ocb_stop_timing_advert(struct wiphy *wiphy,
1245 					   struct wireless_dev *wdev,
1246 					   const void *data,
1247 					   int data_len)
1248 {
1249 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
1250 	struct net_device *dev = wdev->netdev;
1251 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1252 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_MAX + 1];
1253 	struct ocb_timing_advert_param *timing_advert;
1254 	struct wlan_objmgr_vdev *vdev;
1255 	int rc = -EINVAL;
1256 
1257 	hdd_enter_dev(dev);
1258 
1259 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1260 		hdd_err("Command not allowed in FTM mode");
1261 		return -EPERM;
1262 	}
1263 
1264 	if (wlan_hdd_validate_context(hdd_ctx))
1265 		return -EINVAL;
1266 
1267 	if (adapter->device_mode != QDF_OCB_MODE) {
1268 		hdd_err("Device not in OCB mode!");
1269 		return -EINVAL;
1270 	}
1271 
1272 	if (!wma_is_vdev_up(adapter->deflink->vdev_id)) {
1273 		hdd_err("The device has not been started");
1274 		return -EINVAL;
1275 	}
1276 
1277 	timing_advert = qdf_mem_malloc(sizeof(*timing_advert));
1278 	if (!timing_advert)
1279 		return -ENOMEM;
1280 
1281 	timing_advert->vdev_id = adapter->deflink->vdev_id;
1282 
1283 	/* Parse the netlink message */
1284 	if (wlan_cfg80211_nla_parse(tb,
1285 			       QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_MAX,
1286 			       data, data_len,
1287 			       qca_wlan_vendor_ocb_stop_timing_advert_policy)) {
1288 		hdd_err("Invalid ATTR");
1289 		goto fail;
1290 	}
1291 
1292 	if (!tb[QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_CHANNEL_FREQ]) {
1293 		hdd_err("CHANNEL_FREQ is not present");
1294 		goto fail;
1295 	}
1296 	timing_advert->chan_freq = nla_get_u32(
1297 		tb[QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_CHANNEL_FREQ]);
1298 
1299 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_OCB_ID);
1300 	if (!vdev) {
1301 		rc = -EINVAL;
1302 		goto fail;
1303 	}
1304 
1305 	if (ucfg_ocb_stop_timing_advert(vdev, timing_advert) !=
1306 			QDF_STATUS_SUCCESS) {
1307 		hdd_err("Error while stopping timing advert");
1308 		rc = -EINVAL;
1309 	} else {
1310 		rc = 0;
1311 	}
1312 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_OCB_ID);
1313 
1314 fail:
1315 	qdf_mem_free(timing_advert);
1316 	return rc;
1317 }
1318 
1319 /**
1320  * wlan_hdd_cfg80211_ocb_stop_timing_advert() - Interface for the stop TA cmd
1321  * @wiphy: pointer to the wiphy
1322  * @wdev: pointer to the wdev
1323  * @data: The netlink data
1324  * @data_len: The length of the netlink data in bytes
1325  *
1326  * Return: 0 on success.
1327  */
wlan_hdd_cfg80211_ocb_stop_timing_advert(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1328 int wlan_hdd_cfg80211_ocb_stop_timing_advert(struct wiphy *wiphy,
1329 					     struct wireless_dev *wdev,
1330 					     const void *data,
1331 					     int data_len)
1332 {
1333 	int errno;
1334 	struct osif_vdev_sync *vdev_sync;
1335 
1336 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
1337 	if (errno)
1338 		return errno;
1339 
1340 	errno = __wlan_hdd_cfg80211_ocb_stop_timing_advert(wiphy, wdev,
1341 							   data, data_len);
1342 
1343 	osif_vdev_sync_op_stop(vdev_sync);
1344 
1345 	return errno;
1346 }
1347 
1348 struct hdd_ocb_get_tsf_timer_priv {
1349 	struct ocb_get_tsf_timer_response response;
1350 	int status;
1351 };
1352 
1353 /**
1354  * hdd_ocb_get_tsf_timer_callback() - Callback to get TSF command
1355  * @context_ptr: request context
1356  * @response_ptr: response data
1357  */
hdd_ocb_get_tsf_timer_callback(void * context_ptr,void * response_ptr)1358 static void hdd_ocb_get_tsf_timer_callback(void *context_ptr,
1359 					   void *response_ptr)
1360 {
1361 	struct osif_request *request;
1362 	struct hdd_ocb_get_tsf_timer_priv *priv;
1363 	struct ocb_get_tsf_timer_response *response = response_ptr;
1364 
1365 	request = osif_request_get(context_ptr);
1366 	if (!request) {
1367 		hdd_err("Obsolete request");
1368 		return;
1369 	}
1370 
1371 	priv = osif_request_priv(request);
1372 	if (response) {
1373 		priv->response = *response;
1374 		priv->status = 0;
1375 	} else {
1376 		priv->status = -EINVAL;
1377 	}
1378 	osif_request_complete(request);
1379 	osif_request_put(request);
1380 }
1381 
1382 static int
hdd_ocb_get_tsf_timer_reply(struct wiphy * wiphy,struct ocb_get_tsf_timer_response * response)1383 hdd_ocb_get_tsf_timer_reply(struct wiphy *wiphy,
1384 			    struct ocb_get_tsf_timer_response *response)
1385 {
1386 	uint32_t nl_buf_len;
1387 	struct sk_buff *nl_resp;
1388 	int rc;
1389 
1390 	/* Allocate the buffer for the response. */
1391 	nl_buf_len = NLMSG_HDRLEN;
1392 	nl_buf_len += 2 * (NLA_HDRLEN + sizeof(uint32_t));
1393 	nl_resp = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, nl_buf_len);
1394 	if (!nl_resp) {
1395 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
1396 		return -ENOMEM;
1397 	}
1398 
1399 	/* Populate the response. */
1400 	rc = nla_put_u32(nl_resp,
1401 			 QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH,
1402 			 response->timer_high);
1403 	if (rc)
1404 		goto end;
1405 	rc = nla_put_u32(nl_resp,
1406 			 QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW,
1407 			 response->timer_low);
1408 	if (rc)
1409 		goto end;
1410 
1411 	/* Send the response. */
1412 	rc = wlan_cfg80211_vendor_cmd_reply(nl_resp);
1413 	nl_resp = NULL;
1414 	if (rc) {
1415 		hdd_err("wlan_cfg80211_vendor_cmd_reply failed: %d", rc);
1416 		goto end;
1417 	}
1418 end:
1419 	wlan_cfg80211_vendor_free_skb(nl_resp);
1420 	return rc;
1421 }
1422 
1423 /**
1424  * __wlan_hdd_cfg80211_ocb_get_tsf_timer() - Interface for get TSF timer cmd
1425  * @wiphy: pointer to the wiphy
1426  * @wdev: pointer to the wdev
1427  * @data: The netlink data
1428  * @data_len: The length of the netlink data in bytes
1429  *
1430  * Return: 0 on success.
1431  */
1432 static int
__wlan_hdd_cfg80211_ocb_get_tsf_timer(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1433 __wlan_hdd_cfg80211_ocb_get_tsf_timer(struct wiphy *wiphy,
1434 				      struct wireless_dev *wdev,
1435 				      const void *data,
1436 				      int data_len)
1437 {
1438 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
1439 	struct net_device *dev = wdev->netdev;
1440 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1441 	int rc;
1442 	struct ocb_get_tsf_timer_param tsf_request = {0};
1443 	QDF_STATUS status;
1444 	void *cookie;
1445 	struct osif_request *request;
1446 	struct hdd_ocb_get_tsf_timer_priv *priv;
1447 	static const struct osif_request_params params = {
1448 		.priv_size = sizeof(*priv),
1449 		.timeout_ms = WLAN_WAIT_TIME_OCB_CMD,
1450 	};
1451 	struct wlan_objmgr_vdev *vdev;
1452 
1453 	hdd_enter_dev(dev);
1454 
1455 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1456 		hdd_err("Command not allowed in FTM mode");
1457 		return -EPERM;
1458 	}
1459 
1460 	rc = wlan_hdd_validate_context(hdd_ctx);
1461 	if (rc)
1462 		return rc;
1463 
1464 	if (adapter->device_mode != QDF_OCB_MODE) {
1465 		hdd_err("Device not in OCB mode!");
1466 		return -EINVAL;
1467 	}
1468 
1469 	if (!wma_is_vdev_up(adapter->deflink->vdev_id)) {
1470 		hdd_err("The device has not been started");
1471 		return -EINVAL;
1472 	}
1473 
1474 	request = osif_request_alloc(&params);
1475 	if (!request) {
1476 		hdd_err("Request allocation failure");
1477 		return -ENOMEM;
1478 	}
1479 	cookie = osif_request_cookie(request);
1480 
1481 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_OCB_ID);
1482 	if (!vdev) {
1483 		rc = -EINVAL;
1484 		goto end;
1485 	}
1486 
1487 	tsf_request.vdev_id = adapter->deflink->vdev_id;
1488 	status = ucfg_ocb_get_tsf_timer(vdev, &tsf_request,
1489 					hdd_ocb_get_tsf_timer_callback,
1490 					cookie);
1491 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_OCB_ID);
1492 	if (QDF_IS_STATUS_ERROR(status)) {
1493 		hdd_err("Failed to get tsf timer.");
1494 		rc = qdf_status_to_os_return(status);
1495 		goto end;
1496 	}
1497 
1498 	rc = osif_request_wait_for_response(request);
1499 	if (rc) {
1500 		hdd_err("Operation timed out");
1501 		goto end;
1502 	}
1503 
1504 	priv = osif_request_priv(request);
1505 	rc = priv->status;
1506 	if (rc) {
1507 		hdd_err("Operation failed: %d", rc);
1508 		goto end;
1509 	}
1510 
1511 	hdd_debug("Got TSF timer response, high=%d, low=%d",
1512 		priv->response.timer_high,
1513 		priv->response.timer_low);
1514 
1515 	/* Send the response. */
1516 	rc = hdd_ocb_get_tsf_timer_reply(wiphy, &priv->response);
1517 	if (rc) {
1518 		hdd_err("hdd_ocb_get_tsf_timer_reply failed: %d", rc);
1519 		goto end;
1520 	}
1521 
1522 end:
1523 	osif_request_put(request);
1524 
1525 	return rc;
1526 }
1527 
1528 /**
1529  * wlan_hdd_cfg80211_ocb_get_tsf_timer() - Interface for get TSF timer cmd
1530  * @wiphy: pointer to the wiphy
1531  * @wdev: pointer to the wdev
1532  * @data: The netlink data
1533  * @data_len: The length of the netlink data in bytes
1534  *
1535  * Return: 0 on success.
1536  */
wlan_hdd_cfg80211_ocb_get_tsf_timer(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1537 int wlan_hdd_cfg80211_ocb_get_tsf_timer(struct wiphy *wiphy,
1538 					struct wireless_dev *wdev,
1539 					const void *data,
1540 					int data_len)
1541 {
1542 	int errno;
1543 	struct osif_vdev_sync *vdev_sync;
1544 
1545 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
1546 	if (errno)
1547 		return errno;
1548 
1549 	errno = __wlan_hdd_cfg80211_ocb_get_tsf_timer(wiphy, wdev,
1550 						      data, data_len);
1551 
1552 	osif_vdev_sync_op_stop(vdev_sync);
1553 
1554 	return errno;
1555 }
1556 
1557 struct hdd_dcc_stats_priv {
1558 	struct ocb_dcc_get_stats_response *response;
1559 	int status;
1560 };
1561 
hdd_dcc_get_stats_dealloc(void * context_ptr)1562 static void hdd_dcc_get_stats_dealloc(void *context_ptr)
1563 {
1564 	struct hdd_dcc_stats_priv *priv = context_ptr;
1565 
1566 	qdf_mem_free(priv->response);
1567 	priv->response = NULL;
1568 }
1569 
1570 /**
1571  * hdd_dcc_get_stats_callback() - Callback to get stats command
1572  * @context_ptr: request context
1573  * @response_ptr: response data
1574  */
hdd_dcc_get_stats_callback(void * context_ptr,void * response_ptr)1575 static void hdd_dcc_get_stats_callback(void *context_ptr, void *response_ptr)
1576 {
1577 	struct osif_request *request;
1578 	struct hdd_dcc_stats_priv *priv;
1579 	struct ocb_dcc_get_stats_response *response = response_ptr;
1580 	struct ocb_dcc_get_stats_response *hdd_resp;
1581 
1582 	request = osif_request_get(context_ptr);
1583 	if (!request) {
1584 		hdd_err("Obsolete request");
1585 		return;
1586 	}
1587 
1588 	priv = osif_request_priv(request);
1589 	if (!response) {
1590 		priv->status = -EINVAL;
1591 		goto end;
1592 	}
1593 
1594 	priv->response = qdf_mem_malloc(sizeof(*response) +
1595 					response->channel_stats_array_len);
1596 	if (!priv->response) {
1597 		priv->status = -ENOMEM;
1598 		goto end;
1599 	}
1600 
1601 	hdd_resp = priv->response;
1602 	*hdd_resp = *response;
1603 	hdd_resp->channel_stats_array = (void *)hdd_resp + sizeof(*hdd_resp);
1604 	qdf_mem_copy(hdd_resp->channel_stats_array,
1605 		     response->channel_stats_array,
1606 		     response->channel_stats_array_len);
1607 	priv->status = 0;
1608 
1609 end:
1610 	osif_request_complete(request);
1611 	osif_request_put(request);
1612 }
1613 
1614 static int
hdd_dcc_get_stats_send_reply(struct wiphy * wiphy,struct ocb_dcc_get_stats_response * response)1615 hdd_dcc_get_stats_send_reply(struct wiphy *wiphy,
1616 			     struct ocb_dcc_get_stats_response *response)
1617 {
1618 	uint32_t nl_buf_len;
1619 	struct sk_buff *nl_resp;
1620 	int rc;
1621 
1622 	/* Allocate the buffer for the response. */
1623 	nl_buf_len = NLMSG_HDRLEN;
1624 	nl_buf_len += NLA_HDRLEN + sizeof(uint32_t);
1625 	nl_buf_len += NLA_HDRLEN + response->channel_stats_array_len;
1626 	nl_resp = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, nl_buf_len);
1627 	if (!nl_resp) {
1628 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
1629 		return -ENOMEM;
1630 	}
1631 
1632 	/* Populate the response. */
1633 	rc = nla_put_u32(nl_resp,
1634 			 QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_CHANNEL_COUNT,
1635 			 response->num_channels);
1636 	if (rc)
1637 		goto end;
1638 	rc = nla_put(nl_resp,
1639 		     QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_STATS_ARRAY,
1640 		     response->channel_stats_array_len,
1641 		     response->channel_stats_array);
1642 	if (rc)
1643 		goto end;
1644 
1645 	/* Send the response. */
1646 	rc = wlan_cfg80211_vendor_cmd_reply(nl_resp);
1647 	nl_resp = NULL;
1648 	if (rc) {
1649 		hdd_err("wlan_cfg80211_vendor_cmd_reply failed: %d", rc);
1650 		goto end;
1651 	}
1652 end:
1653 	wlan_cfg80211_vendor_free_skb(nl_resp);
1654 	return rc;
1655 }
1656 
1657 /**
1658  * __wlan_hdd_cfg80211_dcc_get_stats() - Interface for get dcc stats
1659  * @wiphy: pointer to the wiphy
1660  * @wdev: pointer to the wdev
1661  * @data: The netlink data
1662  * @data_len: The length of the netlink data in bytes
1663  *
1664  * Return: 0 on success.
1665  */
__wlan_hdd_cfg80211_dcc_get_stats(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1666 static int __wlan_hdd_cfg80211_dcc_get_stats(struct wiphy *wiphy,
1667 					     struct wireless_dev *wdev,
1668 					     const void *data,
1669 					     int data_len)
1670 {
1671 	uint32_t channel_count = 0;
1672 	uint32_t request_array_len = 0;
1673 	void *request_array = 0;
1674 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
1675 	struct net_device *dev = wdev->netdev;
1676 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1677 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_MAX + 1];
1678 	int rc;
1679 	struct ocb_dcc_get_stats_param dcc_request = {0};
1680 	QDF_STATUS status;
1681 	void *cookie;
1682 	struct osif_request *request;
1683 	struct hdd_dcc_stats_priv *priv;
1684 	static const struct osif_request_params params = {
1685 		.priv_size = sizeof(*priv),
1686 		.timeout_ms = WLAN_WAIT_TIME_OCB_CMD,
1687 		.dealloc = hdd_dcc_get_stats_dealloc,
1688 	};
1689 	struct wlan_objmgr_vdev *vdev;
1690 
1691 	hdd_enter_dev(dev);
1692 
1693 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1694 		hdd_err("Command not allowed in FTM mode");
1695 		return -EPERM;
1696 	}
1697 
1698 	rc = wlan_hdd_validate_context(hdd_ctx);
1699 	if (rc)
1700 		return rc;
1701 
1702 	if (adapter->device_mode != QDF_OCB_MODE) {
1703 		hdd_err("Device not in OCB mode!");
1704 		return -EINVAL;
1705 	}
1706 
1707 	if (!wma_is_vdev_up(adapter->deflink->vdev_id)) {
1708 		hdd_err("The device has not been started");
1709 		return -EINVAL;
1710 	}
1711 
1712 	/* Parse the netlink message */
1713 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_MAX,
1714 				    data, data_len,
1715 				    qca_wlan_vendor_dcc_get_stats)) {
1716 		hdd_err("Invalid ATTR");
1717 		return -EINVAL;
1718 	}
1719 
1720 	/* Validate all the parameters are present */
1721 	if (!tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_CHANNEL_COUNT] ||
1722 	    !tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_REQUEST_ARRAY]) {
1723 		hdd_err("Parameters are not present.");
1724 		return -EINVAL;
1725 	}
1726 
1727 	channel_count = nla_get_u32(
1728 		tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_CHANNEL_COUNT]);
1729 	request_array_len = nla_len(
1730 		tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_REQUEST_ARRAY]);
1731 	request_array = nla_data(
1732 		tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_REQUEST_ARRAY]);
1733 
1734 	/* Check channel count. Per 11p spec, max 2 channels allowed */
1735 	if (!channel_count || channel_count > CFG_TGT_NUM_OCB_CHANNELS) {
1736 		hdd_err("Invalid channel_count %d", channel_count);
1737 		return -EINVAL;
1738 	}
1739 
1740 	request = osif_request_alloc(&params);
1741 	if (!request) {
1742 		hdd_err("Request allocation failure");
1743 		return -ENOMEM;
1744 	}
1745 	cookie = osif_request_cookie(request);
1746 
1747 	dcc_request.vdev_id = adapter->deflink->vdev_id;
1748 	dcc_request.channel_count = channel_count;
1749 	dcc_request.request_array_len = request_array_len;
1750 	dcc_request.request_array = request_array;
1751 
1752 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_OCB_ID);
1753 	if (!vdev) {
1754 		rc = -EINVAL;
1755 		goto end;
1756 	}
1757 
1758 	status = ucfg_ocb_dcc_get_stats(vdev, &dcc_request,
1759 					hdd_dcc_get_stats_callback,
1760 					cookie);
1761 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_OCB_ID);
1762 	if (QDF_IS_STATUS_ERROR(status)) {
1763 		hdd_err("Failed to get DCC stats.");
1764 		rc = qdf_status_to_os_return(status);
1765 		goto end;
1766 	}
1767 
1768 	/* Wait for the function to complete. */
1769 	rc = osif_request_wait_for_response(request);
1770 	if (rc) {
1771 		hdd_err("Operation timed out");
1772 		goto end;
1773 	}
1774 
1775 	priv = osif_request_priv(request);
1776 	rc = priv->status;
1777 	if (rc) {
1778 		hdd_err("Operation failed: %d", rc);
1779 		goto end;
1780 	}
1781 
1782 	/* Send the response. */
1783 	rc = hdd_dcc_get_stats_send_reply(wiphy, priv->response);
1784 	if (rc) {
1785 		hdd_err("hdd_dcc_get_stats_send_reply failed: %d", rc);
1786 		goto end;
1787 	}
1788 
1789 end:
1790 	osif_request_put(request);
1791 
1792 	return rc;
1793 }
1794 
1795 /**
1796  * wlan_hdd_cfg80211_dcc_get_stats() - Interface for get dcc stats
1797  * @wiphy: pointer to the wiphy
1798  * @wdev: pointer to the wdev
1799  * @data: The netlink data
1800  * @data_len: The length of the netlink data in bytes
1801  *
1802  * Return: 0 on success.
1803  */
wlan_hdd_cfg80211_dcc_get_stats(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1804 int wlan_hdd_cfg80211_dcc_get_stats(struct wiphy *wiphy,
1805 				    struct wireless_dev *wdev,
1806 				    const void *data,
1807 				    int data_len)
1808 {
1809 	int errno;
1810 	struct osif_vdev_sync *vdev_sync;
1811 
1812 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
1813 	if (errno)
1814 		return errno;
1815 
1816 	errno = __wlan_hdd_cfg80211_dcc_get_stats(wiphy, wdev, data, data_len);
1817 
1818 	osif_vdev_sync_op_stop(vdev_sync);
1819 
1820 	return errno;
1821 }
1822 
1823 /**
1824  * __wlan_hdd_cfg80211_dcc_clear_stats() - Interface for clear dcc stats cmd
1825  * @wiphy: pointer to the wiphy
1826  * @wdev: pointer to the wdev
1827  * @data: The netlink data
1828  * @data_len: The length of the netlink data in bytes
1829  *
1830  * Return: 0 on success.
1831  */
__wlan_hdd_cfg80211_dcc_clear_stats(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1832 static int __wlan_hdd_cfg80211_dcc_clear_stats(struct wiphy *wiphy,
1833 					       struct wireless_dev *wdev,
1834 					       const void *data,
1835 					       int data_len)
1836 {
1837 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
1838 	struct net_device *dev = wdev->netdev;
1839 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1840 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_DCC_CLEAR_STATS_MAX + 1];
1841 	struct wlan_objmgr_vdev *vdev;
1842 
1843 	hdd_enter_dev(dev);
1844 
1845 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1846 		hdd_err("Command not allowed in FTM mode");
1847 		return -EPERM;
1848 	}
1849 
1850 	if (wlan_hdd_validate_context(hdd_ctx))
1851 		return -EINVAL;
1852 
1853 	if (adapter->device_mode != QDF_OCB_MODE) {
1854 		hdd_err("Device not in OCB mode!");
1855 		return -EINVAL;
1856 	}
1857 
1858 	if (!wma_is_vdev_up(adapter->deflink->vdev_id)) {
1859 		hdd_err("The device has not been started");
1860 		return -EINVAL;
1861 	}
1862 
1863 	/* Parse the netlink message */
1864 	if (wlan_cfg80211_nla_parse(tb,
1865 				    QCA_WLAN_VENDOR_ATTR_DCC_CLEAR_STATS_MAX,
1866 				    data, data_len,
1867 				    qca_wlan_vendor_dcc_clear_stats)) {
1868 		hdd_err("Invalid ATTR");
1869 		return -EINVAL;
1870 	}
1871 
1872 	/* Verify that the parameter is present */
1873 	if (!tb[QCA_WLAN_VENDOR_ATTR_DCC_CLEAR_STATS_BITMAP]) {
1874 		hdd_err("Parameters are not present.");
1875 		return -EINVAL;
1876 	}
1877 
1878 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_OCB_ID);
1879 	if (!vdev)
1880 		return -EINVAL;
1881 
1882 	if (ucfg_ocb_dcc_clear_stats(
1883 		vdev, adapter->deflink->vdev_id,
1884 		nla_get_u32(
1885 			tb[QCA_WLAN_VENDOR_ATTR_DCC_CLEAR_STATS_BITMAP])) !=
1886 			QDF_STATUS_SUCCESS) {
1887 		hdd_err("Failed to clear DCC stats.");
1888 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_OCB_ID);
1889 		return -EINVAL;
1890 	}
1891 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_OCB_ID);
1892 
1893 	return 0;
1894 }
1895 
1896 /**
1897  * wlan_hdd_cfg80211_dcc_clear_stats() - Interface for clear dcc stats cmd
1898  * @wiphy: pointer to the wiphy
1899  * @wdev: pointer to the wdev
1900  * @data: The netlink data
1901  * @data_len: The length of the netlink data in bytes
1902  *
1903  * Return: 0 on success.
1904  */
wlan_hdd_cfg80211_dcc_clear_stats(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1905 int wlan_hdd_cfg80211_dcc_clear_stats(struct wiphy *wiphy,
1906 				      struct wireless_dev *wdev,
1907 				      const void *data,
1908 				      int data_len)
1909 {
1910 	int errno;
1911 	struct osif_vdev_sync *vdev_sync;
1912 
1913 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
1914 	if (errno)
1915 		return errno;
1916 
1917 	errno = __wlan_hdd_cfg80211_dcc_clear_stats(wiphy, wdev,
1918 						    data, data_len);
1919 
1920 	osif_vdev_sync_op_stop(vdev_sync);
1921 
1922 	return errno;
1923 }
1924 
1925 struct hdd_dcc_update_ndl_priv {
1926 	int status;
1927 };
1928 
1929 /**
1930  * hdd_dcc_update_ndl_callback() - Callback to update NDL command
1931  * @context_ptr: request context
1932  * @response_ptr: response data
1933  */
hdd_dcc_update_ndl_callback(void * context_ptr,void * response_ptr)1934 static void hdd_dcc_update_ndl_callback(void *context_ptr, void *response_ptr)
1935 {
1936 	struct osif_request *request;
1937 	struct hdd_dcc_update_ndl_priv *priv;
1938 	struct ocb_dcc_update_ndl_response *response = response_ptr;
1939 
1940 	request = osif_request_get(context_ptr);
1941 	if (!request) {
1942 		hdd_err("Obsolete request");
1943 		return;
1944 	}
1945 
1946 	priv = osif_request_priv(request);
1947 	if (response && (0 == response->status))
1948 		priv->status = 0;
1949 	else
1950 		priv->status = -EINVAL;
1951 
1952 	osif_request_complete(request);
1953 	osif_request_put(request);
1954 }
1955 
1956 /**
1957  * __wlan_hdd_cfg80211_dcc_update_ndl() - Interface for update dcc cmd
1958  * @wiphy: pointer to the wiphy
1959  * @wdev: pointer to the wdev
1960  * @data: The netlink data
1961  * @data_len: The length of the netlink data in bytes
1962  *
1963  * Return: 0 on success.
1964  */
__wlan_hdd_cfg80211_dcc_update_ndl(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1965 static int __wlan_hdd_cfg80211_dcc_update_ndl(struct wiphy *wiphy,
1966 					      struct wireless_dev *wdev,
1967 					      const void *data,
1968 					      int data_len)
1969 {
1970 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
1971 	struct net_device *dev = wdev->netdev;
1972 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1973 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_MAX + 1];
1974 	struct ocb_dcc_update_ndl_param dcc_request;
1975 	uint32_t channel_count;
1976 	uint32_t ndl_channel_array_len;
1977 	void *ndl_channel_array;
1978 	uint32_t ndl_active_state_array_len;
1979 	void *ndl_active_state_array;
1980 	int rc;
1981 	QDF_STATUS status;
1982 	void *cookie;
1983 	struct osif_request *request;
1984 	struct hdd_dcc_update_ndl_priv *priv;
1985 	static const struct osif_request_params params = {
1986 		.priv_size = sizeof(*priv),
1987 		.timeout_ms = WLAN_WAIT_TIME_OCB_CMD,
1988 	};
1989 	struct wlan_objmgr_vdev *vdev;
1990 
1991 	hdd_enter_dev(dev);
1992 
1993 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1994 		hdd_err("Command not allowed in FTM mode");
1995 		return -EPERM;
1996 	}
1997 
1998 	rc = wlan_hdd_validate_context(hdd_ctx);
1999 	if (rc)
2000 		return rc;
2001 
2002 	if (adapter->device_mode != QDF_OCB_MODE) {
2003 		hdd_err("Device not in OCB mode!");
2004 		return -EINVAL;
2005 	}
2006 
2007 	if (!wma_is_vdev_up(adapter->deflink->vdev_id)) {
2008 		hdd_err("The device has not been started");
2009 		return -EINVAL;
2010 	}
2011 
2012 	/* Parse the netlink message */
2013 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_MAX,
2014 				    data, data_len,
2015 				    qca_wlan_vendor_dcc_update_ndl)) {
2016 		hdd_err("Invalid ATTR");
2017 		return -EINVAL;
2018 	}
2019 
2020 	/* Verify that the parameter is present */
2021 	if (!tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_COUNT] ||
2022 	    !tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_ARRAY] ||
2023 	    !tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_ACTIVE_STATE_ARRAY]) {
2024 		hdd_err("Parameters are not present.");
2025 		return -EINVAL;
2026 	}
2027 
2028 	channel_count = nla_get_u32(
2029 		tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_COUNT]);
2030 	ndl_channel_array_len = nla_len(
2031 		tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_ARRAY]);
2032 	ndl_channel_array = nla_data(
2033 		tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_ARRAY]);
2034 	ndl_active_state_array_len = nla_len(
2035 		tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_ACTIVE_STATE_ARRAY]);
2036 	ndl_active_state_array = nla_data(
2037 		tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_ACTIVE_STATE_ARRAY]);
2038 
2039 	/* Check channel count. Per 11p spec, max 2 channels allowed */
2040 	if (!channel_count || channel_count > CFG_TGT_NUM_OCB_CHANNELS) {
2041 		hdd_err("Invalid channel_count %d", channel_count);
2042 		return -EINVAL;
2043 	}
2044 
2045 	request = osif_request_alloc(&params);
2046 	if (!request) {
2047 		hdd_err("Request allocation failure");
2048 		return -ENOMEM;
2049 	}
2050 	cookie = osif_request_cookie(request);
2051 
2052 	/* Copy the parameters to the request structure. */
2053 	dcc_request.vdev_id = adapter->deflink->vdev_id;
2054 	dcc_request.channel_count = channel_count;
2055 	dcc_request.dcc_ndl_chan_list_len = ndl_channel_array_len;
2056 	dcc_request.dcc_ndl_chan_list = ndl_channel_array;
2057 	dcc_request.dcc_ndl_active_state_list_len = ndl_active_state_array_len;
2058 	dcc_request.dcc_ndl_active_state_list = ndl_active_state_array;
2059 
2060 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_OCB_ID);
2061 	if (!vdev) {
2062 		rc = -EINVAL;
2063 		goto end;
2064 	}
2065 
2066 	status = ucfg_ocb_dcc_update_ndl(vdev, &dcc_request,
2067 					 hdd_dcc_update_ndl_callback,
2068 					 cookie);
2069 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_OCB_ID);
2070 	if (QDF_IS_STATUS_ERROR(status)) {
2071 		hdd_err("Failed to update NDL.");
2072 		rc = qdf_status_to_os_return(status);
2073 		goto end;
2074 	}
2075 
2076 	/* Wait for the function to complete. */
2077 	rc = osif_request_wait_for_response(request);
2078 	if (rc) {
2079 		hdd_err("Operation timed out");
2080 		goto end;
2081 	}
2082 
2083 	priv = osif_request_priv(request);
2084 	rc = priv->status;
2085 	if (rc) {
2086 		hdd_err("Operation failed: %d", rc);
2087 		goto end;
2088 	}
2089 
2090 end:
2091 	osif_request_put(request);
2092 
2093 	return rc;
2094 }
2095 
2096 /**
2097  * wlan_hdd_cfg80211_dcc_update_ndl() - Interface for update dcc cmd
2098  * @wiphy: pointer to the wiphy
2099  * @wdev: pointer to the wdev
2100  * @data: The netlink data
2101  * @data_len: The length of the netlink data in bytes
2102  *
2103  * Return: 0 on success.
2104  */
wlan_hdd_cfg80211_dcc_update_ndl(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)2105 int wlan_hdd_cfg80211_dcc_update_ndl(struct wiphy *wiphy,
2106 				     struct wireless_dev *wdev,
2107 				     const void *data,
2108 				     int data_len)
2109 {
2110 	int errno;
2111 	struct osif_vdev_sync *vdev_sync;
2112 
2113 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
2114 	if (errno)
2115 		return errno;
2116 
2117 	errno = __wlan_hdd_cfg80211_dcc_update_ndl(wiphy, wdev, data, data_len);
2118 
2119 	osif_vdev_sync_op_stop(vdev_sync);
2120 
2121 	return errno;
2122 }
2123 
2124 /**
2125  * wlan_hdd_dcc_stats_event_callback() - Callback to get stats event
2126  * @context_ptr: request context
2127  * @response_ptr: response data
2128  */
wlan_hdd_dcc_stats_event_callback(void * context_ptr,void * response_ptr)2129 static void wlan_hdd_dcc_stats_event_callback(void *context_ptr,
2130 					      void *response_ptr)
2131 {
2132 	struct hdd_context *hdd_ctx = (struct hdd_context *)context_ptr;
2133 	struct ocb_dcc_get_stats_response *resp = response_ptr;
2134 	struct sk_buff *vendor_event;
2135 	enum qca_nl80211_vendor_subcmds_index index =
2136 		QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX;
2137 
2138 	hdd_enter();
2139 
2140 	vendor_event =
2141 		wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
2142 						 sizeof(uint32_t) +
2143 						 resp->channel_stats_array_len +
2144 						 NLMSG_HDRLEN,
2145 						 index, GFP_KERNEL);
2146 
2147 	if (!vendor_event) {
2148 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
2149 		return;
2150 	}
2151 
2152 	if (nla_put_u32(vendor_event,
2153 			QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_CHANNEL_COUNT,
2154 			resp->num_channels) ||
2155 		nla_put(vendor_event,
2156 			QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_STATS_ARRAY,
2157 			resp->channel_stats_array_len,
2158 			resp->channel_stats_array)) {
2159 		hdd_err("nla put failed");
2160 		wlan_cfg80211_vendor_free_skb(vendor_event);
2161 		return;
2162 	}
2163 
2164 	wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2165 }
2166 
2167 /**
2168  * wlan_hdd_dcc_register_for_dcc_stats_event() - Register for dcc stats events
2169  * @hdd_ctx: hdd context
2170  */
wlan_hdd_dcc_register_for_dcc_stats_event(struct hdd_context * hdd_ctx)2171 void wlan_hdd_dcc_register_for_dcc_stats_event(struct hdd_context *hdd_ctx)
2172 {
2173 	int rc;
2174 
2175 	rc = ucfg_ocb_register_for_dcc_stats_event(hdd_ctx->pdev, hdd_ctx,
2176 				      wlan_hdd_dcc_stats_event_callback);
2177 	if (rc)
2178 		hdd_err("Register DCC stats callback failed: %d", rc);
2179 }
2180