1 /*
2  * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-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_bcn_recv.c
22  * Feature for receiving beacons of connected AP and sending select
23  * params to upper layer via vendor event
24  */
25 
26 #include <wlan_hdd_includes.h>
27 #include <net/cfg80211.h>
28 #include "wlan_osif_priv.h"
29 #include "qdf_trace.h"
30 #include "wlan_hdd_main.h"
31 #include "osif_sync.h"
32 #include "wlan_hdd_bcn_recv.h"
33 #include <linux/limits.h>
34 #include <wlan_hdd_object_manager.h>
35 
36 #define SET_BIT(value, mask) ((value) |= (1 << (mask)))
37 
38 #define BOOTTIME QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_BOOTTIME_WHEN_RECEIVED
39 
40 #ifndef CHAR_BIT
41 #define CHAR_BIT 8	/* Normally in <limits.h> */
42 #endif
43 
44 const struct nla_policy
45 	beacon_reporting_params_policy
46 	[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_MAX + 1] = {
47 	[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE] = {.type = NLA_U8},
48 	[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_ACTIVE_REPORTING] = {.type =
49 								     NLA_FLAG},
50 	[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PERIOD] = {.type = NLA_U8},
51 	[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_DO_NOT_RESUME] = {.type =
52 								  NLA_FLAG},
53 };
54 
55 /**
56  * get_beacon_report_data_len() - Calculate length for beacon
57  * report to allocate skb buffer
58  * @report: beacon report structure
59  *
60  * Return: skb buffer length
61  */
62 static
get_beacon_report_data_len(struct wlan_beacon_report * report)63 int get_beacon_report_data_len(struct wlan_beacon_report *report)
64 {
65 	uint32_t data_len = NLMSG_HDRLEN;
66 
67 	/* QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE */
68 	data_len += nla_total_size(sizeof(u32));
69 
70 	/* QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_SSID */
71 	data_len += nla_total_size(report->ssid.length);
72 
73 	/* QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_BSSID */
74 	data_len += nla_total_size(ETH_ALEN);
75 
76 	/* QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_FREQ */
77 	data_len += nla_total_size(sizeof(u32));
78 
79 	/* QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_BI */
80 	data_len += nla_total_size(sizeof(u16));
81 
82 	/* QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_TSF */
83 	data_len += nla_total_size(sizeof(uint64_t));
84 
85 	/* QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_BOOTTIME_WHEN_RECEIVED */
86 	data_len += nla_total_size(sizeof(uint64_t));
87 
88 	return data_len;
89 }
90 
91 /**
92  * get_pause_ind_data_len() - Calculate skb buffer length
93  * @is_disconnected: Connection state
94  *
95  * Calculate length for pause indication to allocate skb buffer
96  *
97  * Return: skb buffer length
98  */
get_pause_ind_data_len(bool is_disconnected)99 static int get_pause_ind_data_len(bool is_disconnected)
100 {
101 	uint32_t data_len = NLMSG_HDRLEN;
102 
103 	/* QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE */
104 	data_len += nla_total_size(sizeof(u32));
105 
106 	/* QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PAUSE_REASON */
107 	data_len += nla_total_size(sizeof(u32));
108 
109 	/* QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_AUTO_RESUMES */
110 	if (!is_disconnected)
111 		data_len += nla_total_size(sizeof(u8));
112 
113 	return data_len;
114 }
115 
116 /**
117  * hdd_send_bcn_recv_info() - Send beacon info to userspace for
118  * connected AP
119  * @hdd_handle: hdd_handle to get hdd_adapter
120  * @beacon_report: Required beacon report
121  *
122  * Send beacon info to userspace for connected AP through a vendor event:
123  * QCA_NL80211_VENDOR_SUBCMD_BEACON_REPORTING.
124  */
hdd_send_bcn_recv_info(hdd_handle_t hdd_handle,struct wlan_beacon_report * beacon_report)125 static QDF_STATUS hdd_send_bcn_recv_info(hdd_handle_t hdd_handle,
126 					 struct wlan_beacon_report
127 					 *beacon_report)
128 {
129 	struct sk_buff *vendor_event;
130 	struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
131 	uint32_t data_len;
132 	int flags = cds_get_gfp_flags();
133 	struct hdd_adapter *adapter;
134 	struct wlan_hdd_link_info *link_info;
135 	enum qca_nl80211_vendor_subcmds_index index =
136 		QCA_NL80211_VENDOR_SUBCMD_BEACON_REPORTING_INDEX;
137 
138 	if (wlan_hdd_validate_context(hdd_ctx))
139 		return QDF_STATUS_E_FAILURE;
140 
141 	data_len = get_beacon_report_data_len(beacon_report);
142 
143 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, beacon_report->vdev_id);
144 	if (!link_info || hdd_validate_adapter(link_info->adapter))
145 		return QDF_STATUS_E_FAILURE;
146 
147 	adapter = link_info->adapter;
148 	vendor_event = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
149 							&adapter->wdev,
150 							data_len, index, flags);
151 	if (!vendor_event) {
152 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
153 		return QDF_STATUS_E_FAILURE;
154 	}
155 
156 	if (nla_put_u32(vendor_event,
157 			QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE,
158 			QCA_WLAN_VENDOR_BEACON_REPORTING_OP_BEACON_INFO) ||
159 	    nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_SSID,
160 		    beacon_report->ssid.length, beacon_report->ssid.ssid) ||
161 	    nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_BSSID,
162 		    ETH_ALEN, beacon_report->bssid.bytes) ||
163 	    nla_put_u32(vendor_event,
164 			QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_FREQ,
165 			beacon_report->frequency) ||
166 	    nla_put_u16(vendor_event,
167 			QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_BI,
168 			beacon_report->beacon_interval) ||
169 	    wlan_cfg80211_nla_put_u64(vendor_event,
170 				      QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_TSF,
171 				      beacon_report->time_stamp) ||
172 	    wlan_cfg80211_nla_put_u64(vendor_event, BOOTTIME,
173 				      beacon_report->boot_time)) {
174 		hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
175 		wlan_cfg80211_vendor_free_skb(vendor_event);
176 		return QDF_STATUS_E_FAILURE;
177 	}
178 
179 	wlan_cfg80211_vendor_event(vendor_event, flags);
180 	return QDF_STATUS_SUCCESS;
181 }
182 
183 /**
184  * hdd_handle_beacon_reporting_start_op() - Process bcn recv start op
185  * @hdd_ctx: Pointer to hdd context
186  * @adapter: Pointer to network adapter
187  * @active_report: Active reporting flag
188  * @nth_value: Beacon report period
189  * @do_not_resume: beacon reporting resume after a pause is completed
190  *
191  * This function process beacon reporting start operation.
192  */
hdd_handle_beacon_reporting_start_op(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter,bool active_report,uint32_t nth_value,bool do_not_resume)193 static int hdd_handle_beacon_reporting_start_op(struct hdd_context *hdd_ctx,
194 						struct hdd_adapter *adapter,
195 						bool active_report,
196 						uint32_t nth_value,
197 						bool do_not_resume)
198 {
199 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
200 	int errno;
201 	uint32_t mask = 0;
202 
203 	if (active_report) {
204 		/* Register beacon report callback */
205 		qdf_status =
206 			sme_register_bcn_report_pe_cb(hdd_ctx->mac_handle,
207 						      hdd_send_bcn_recv_info);
208 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
209 			hdd_err("bcn recv info cb reg failed = %d", qdf_status);
210 			errno = qdf_status_to_os_return(qdf_status);
211 			return errno;
212 		}
213 
214 		/* Register pause indication callback */
215 		qdf_status =
216 			sme_register_bcn_recv_pause_ind_cb(hdd_ctx->mac_handle,
217 					hdd_beacon_recv_pause_indication);
218 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
219 			hdd_err("pause_ind_cb reg failed = %d", qdf_status);
220 			errno = qdf_status_to_os_return(qdf_status);
221 			return errno;
222 		}
223 		/* Update Beacon report period in case of active reporting */
224 		nth_value = 1;
225 		/*
226 		 * Set MSB which indicates fw to don't wakeup host in wow
227 		 * mode in case of active beacon report.
228 		 */
229 		mask = (sizeof(uint32_t) * CHAR_BIT) - 1;
230 		SET_BIT(nth_value, mask);
231 	}
232 	/* Handle beacon receive start indication */
233 	qdf_status = sme_handle_bcn_recv_start(hdd_ctx->mac_handle,
234 					       adapter->deflink->vdev_id,
235 					       nth_value, do_not_resume);
236 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
237 		hdd_err("bcn rcv start failed with status=%d", qdf_status);
238 		if (sme_register_bcn_report_pe_cb(hdd_ctx->mac_handle, NULL))
239 			hdd_err("bcn report cb deregistration failed");
240 		if (sme_register_bcn_recv_pause_ind_cb(hdd_ctx->mac_handle,
241 						       NULL))
242 			hdd_err("bcn pause ind cb deregistration failed");
243 		errno = qdf_status_to_os_return(qdf_status);
244 		return errno;
245 	}
246 
247 	errno = qdf_status_to_os_return(qdf_status);
248 
249 	return errno;
250 }
251 
252 /**
253  * hdd_handle_beacon_reporting_stop_op() - Process bcn recv stop op
254  * @hdd_ctx: Pointer to hdd context
255  * @adapter: Pointer to network adapter
256  *
257  * This function process beacon reporting stop operation.
258  */
hdd_handle_beacon_reporting_stop_op(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)259 static int hdd_handle_beacon_reporting_stop_op(struct hdd_context *hdd_ctx,
260 					       struct hdd_adapter *adapter)
261 {
262 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
263 	int errno;
264 
265 	/* Reset bcn recv start flag */
266 	sme_stop_beacon_report(hdd_ctx->mac_handle, adapter->deflink->vdev_id);
267 
268 	/* Deregister beacon report callback */
269 	qdf_status = sme_register_bcn_report_pe_cb(hdd_ctx->mac_handle, NULL);
270 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
271 		hdd_err("Callback de-registration failed = %d", qdf_status);
272 		errno = qdf_status_to_os_return(qdf_status);
273 		return errno;
274 	}
275 
276 	/* Deregister pause indication callback */
277 	qdf_status = sme_register_bcn_recv_pause_ind_cb(hdd_ctx->mac_handle,
278 							NULL);
279 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
280 		hdd_err("scan even deregister failed = %d", qdf_status);
281 		errno = qdf_status_to_os_return(qdf_status);
282 		return errno;
283 	}
284 
285 	if (hdd_cm_is_vdev_associated(adapter->deflink))
286 		/* Add beacon filter */
287 		if (hdd_add_beacon_filter(adapter)) {
288 			hdd_err("Beacon filter addition failed");
289 			return -EINVAL;
290 		}
291 
292 	errno = qdf_status_to_os_return(qdf_status);
293 
294 	return errno;
295 }
296 
297 /**
298  * __wlan_hdd_cfg80211_bcn_rcv_op() - enable/disable beacon reporting
299  * indication
300  * @wiphy: Pointer to wireless phy
301  * @wdev: Pointer to wireless device
302  * @data: Pointer to data
303  * @data_len: Length of @data
304  *
305  * This function is used to enable/disable asynchronous beacon
306  * reporting feature using vendor commands.
307  *
308  * Return: 0 on success, negative errno on failure
309  */
__wlan_hdd_cfg80211_bcn_rcv_op(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)310 static int __wlan_hdd_cfg80211_bcn_rcv_op(struct wiphy *wiphy,
311 					  struct wireless_dev *wdev,
312 					  const void *data, int data_len)
313 {
314 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
315 	struct net_device *dev = wdev->netdev;
316 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
317 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_MAX + 1];
318 	uint32_t bcn_report, nth_value = 1;
319 	int errno;
320 	bool active_report, do_not_resume;
321 	struct wlan_objmgr_vdev *vdev;
322 	enum scm_scan_status scan_req_status;
323 
324 	hdd_enter_dev(dev);
325 
326 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
327 		hdd_err("Command not allowed in FTM mode");
328 		return -EPERM;
329 	}
330 
331 	errno = hdd_validate_adapter(adapter);
332 	if (errno)
333 		return errno;
334 
335 	if (adapter->device_mode != QDF_STA_MODE) {
336 		hdd_err("Command not allowed as device not in STA mode");
337 		return -EINVAL;
338 	}
339 
340 	if (!hdd_cm_is_vdev_associated(adapter->deflink)) {
341 		hdd_err("STA not in connected state");
342 		return -EINVAL;
343 	}
344 
345 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_SCAN_ID);
346 	if (!vdev)
347 		return -EINVAL;
348 
349 	scan_req_status = ucfg_scan_get_pdev_status(wlan_vdev_get_pdev(vdev));
350 	wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_SCAN_ID);
351 
352 	if (scan_req_status != SCAN_NOT_IN_PROGRESS) {
353 		hdd_debug("Scan in progress: %d, bcn rpt start OP not allowed",
354 			  scan_req_status);
355 		return -EBUSY;
356 	}
357 
358 	errno =
359 	   wlan_cfg80211_nla_parse(tb,
360 				   QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_MAX,
361 				   data,
362 				   data_len, beacon_reporting_params_policy);
363 	if (errno) {
364 		hdd_err("Failed to parse the beacon reporting params %d",
365 			errno);
366 		return errno;
367 	}
368 
369 	/* Parse and fetch OP Type */
370 	if (!tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE]) {
371 		hdd_err("attr beacon report OP type failed");
372 		return -EINVAL;
373 	}
374 	bcn_report =
375 		nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE]);
376 	hdd_debug("Bcn Report: OP type:%d", bcn_report);
377 
378 	switch (bcn_report) {
379 	case QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START:
380 		active_report =
381 			!!tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_ACTIVE_REPORTING];
382 		hdd_debug("attr active_report %d", active_report);
383 
384 		do_not_resume =
385 			!!tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_DO_NOT_RESUME];
386 		hdd_debug("Attr beacon report do not resume %d", do_not_resume);
387 
388 		if (tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PERIOD])
389 			nth_value =
390 				nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PERIOD]);
391 		hdd_debug("Beacon Report: Period: %d", nth_value);
392 
393 		if (sme_is_beacon_report_started(hdd_ctx->mac_handle,
394 						 adapter->deflink->vdev_id)) {
395 			hdd_debug("Start cmd already in progress, issue the stop to FW, before new start");
396 			if (hdd_handle_beacon_reporting_stop_op(hdd_ctx,
397 								adapter)) {
398 				hdd_err("Failed to stop the beacon reporting before starting new start");
399 				return -EAGAIN;
400 			}
401 		}
402 		errno = hdd_handle_beacon_reporting_start_op(hdd_ctx,
403 							     adapter,
404 							     active_report,
405 							     nth_value,
406 							     do_not_resume);
407 		if (errno) {
408 			hdd_err("Failed to start beacon reporting %d,", errno);
409 			break;
410 		}
411 		break;
412 	case QCA_WLAN_VENDOR_BEACON_REPORTING_OP_STOP:
413 		if (sme_is_beacon_report_started(hdd_ctx->mac_handle,
414 						 adapter->deflink->vdev_id)) {
415 			errno = hdd_handle_beacon_reporting_stop_op(hdd_ctx,
416 								    adapter);
417 			if (errno) {
418 				hdd_err("Failed to stop the beacon report, %d",
419 					errno);
420 			}
421 		} else {
422 			hdd_err_rl("BCN_RCV_STOP rej as no START CMD active");
423 			errno = -EINVAL;
424 		}
425 		break;
426 	default:
427 		hdd_debug("Invalid bcn report type %d", bcn_report);
428 	}
429 
430 	return errno;
431 }
432 
hdd_beacon_recv_pause_indication(hdd_handle_t hdd_handle,uint8_t vdev_id,enum scan_event_type type,bool is_disconnected)433 void hdd_beacon_recv_pause_indication(hdd_handle_t hdd_handle,
434 				      uint8_t vdev_id,
435 				      enum scan_event_type type,
436 				      bool is_disconnected)
437 {
438 	struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
439 	struct hdd_adapter *adapter;
440 	struct sk_buff *vendor_event;
441 	uint32_t data_len;
442 	int flags;
443 	uint32_t abort_reason;
444 	bool do_not_resume;
445 	struct wlan_hdd_link_info *link_info;
446 
447 	if (wlan_hdd_validate_context(hdd_ctx))
448 		return;
449 
450 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
451 	if (!link_info || hdd_validate_adapter(link_info->adapter))
452 		return;
453 
454 	adapter = link_info->adapter;
455 	data_len = get_pause_ind_data_len(is_disconnected);
456 	flags = cds_get_gfp_flags();
457 
458 	vendor_event =
459 		wlan_cfg80211_vendor_event_alloc(
460 			hdd_ctx->wiphy, &(adapter->wdev),
461 			data_len,
462 			QCA_NL80211_VENDOR_SUBCMD_BEACON_REPORTING_INDEX,
463 			flags);
464 	if (!vendor_event) {
465 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
466 		return;
467 	}
468 
469 	do_not_resume =
470 		sme_is_beacon_reporting_do_not_resume(hdd_ctx->mac_handle,
471 						      link_info->vdev_id);
472 
473 	if (is_disconnected) {
474 		abort_reason =
475 		     QCA_WLAN_VENDOR_BEACON_REPORTING_PAUSE_REASON_DISCONNECTED;
476 		/* Deregister callbacks and Reset bcn recv start flag */
477 		if (sme_is_beacon_report_started(hdd_ctx->mac_handle,
478 						 link_info->vdev_id))
479 			hdd_handle_beacon_reporting_stop_op(hdd_ctx, adapter);
480 	} else {
481 		/*
482 		 * In case of scan, Check that auto resume of beacon reporting
483 		 * is allowed or not.
484 		 * If not allowed:
485 		 * Deregister callbacks and Reset bcn recv start flag in order
486 		 * to make sure host should not send beacon report to userspace
487 		 * further.
488 		 * If Auto resume allowed:
489 		 * Send pause indication to userspace and continue sending
490 		 * connected AP's beacon to userspace.
491 		 */
492 		if (do_not_resume)
493 			hdd_handle_beacon_reporting_stop_op(hdd_ctx, adapter);
494 
495 		switch (type) {
496 		case SCAN_EVENT_TYPE_STARTED:
497 			abort_reason =
498 		     QCA_WLAN_VENDOR_BEACON_REPORTING_PAUSE_REASON_SCAN_STARTED;
499 			break;
500 		default:
501 			abort_reason =
502 		      QCA_WLAN_VENDOR_BEACON_REPORTING_PAUSE_REASON_UNSPECIFIED;
503 		}
504 	}
505 	/* Send vendor event to user space to inform ABORT */
506 	if (nla_put_u32(vendor_event,
507 			QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE,
508 			QCA_WLAN_VENDOR_BEACON_REPORTING_OP_PAUSE) ||
509 	    nla_put_u32(vendor_event,
510 			QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PAUSE_REASON,
511 			abort_reason)) {
512 		hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
513 		wlan_cfg80211_vendor_free_skb(vendor_event);
514 		return;
515 	}
516 
517 	/*
518 	 * Send auto resume flag to user space to specify the driver will
519 	 * automatically resume reporting beacon events only in case of
520 	 * pause indication due to scan started.
521 	 * If do_not_resume flag is set in the recent
522 	 * QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START command, then in the
523 	 * subsequent QCA_WLAN_VENDOR_BEACON_REPORTING_OP_PAUSE event (if any)
524 	 * the QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_AUTO_RESUMES shall not be
525 	 * set by the driver.
526 	 */
527 	if (!is_disconnected && !do_not_resume)
528 		if (nla_put_flag(vendor_event,
529 			QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_AUTO_RESUMES)) {
530 			hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
531 			wlan_cfg80211_vendor_free_skb(vendor_event);
532 			return;
533 		}
534 
535 	wlan_cfg80211_vendor_event(vendor_event, flags);
536 }
537 
wlan_hdd_cfg80211_bcn_rcv_op(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)538 int wlan_hdd_cfg80211_bcn_rcv_op(struct wiphy *wiphy,
539 				 struct wireless_dev *wdev,
540 				 const void *data, int data_len)
541 {
542 	int errno;
543 	struct osif_vdev_sync *vdev_sync;
544 
545 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
546 	if (errno)
547 		return errno;
548 
549 	errno = __wlan_hdd_cfg80211_bcn_rcv_op(wiphy, wdev,
550 					       data, data_len);
551 
552 	osif_vdev_sync_op_stop(vdev_sync);
553 
554 	return errno;
555 }
556