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