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 = ¤t_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(¶ms);
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(¶ms);
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(¶ms);
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(¶ms);
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