1  /*
2   * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3   * Copyright (c) 2021-2024 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_power.c
22   *
23   * WLAN power management functions
24   *
25   */
26  
27  /* Include files */
28  
29  #include <linux/pm.h>
30  #include <linux/wait.h>
31  #include <linux/cpu.h>
32  #include "osif_sync.h"
33  #include <wlan_hdd_includes.h>
34  #if defined(CONFIG_HAS_WAKELOCK)
35  #include <linux/wakelock.h>
36  #endif
37  #include "qdf_types.h"
38  #include "sme_api.h"
39  #include <cds_api.h>
40  #include <cds_sched.h>
41  #include <mac_init_api.h>
42  #include <wlan_qct_sys.h>
43  #include <wlan_hdd_main.h>
44  #include <wlan_hdd_assoc.h>
45  #include <wlan_nlink_srv.h>
46  #include <wlan_hdd_misc.h>
47  #include <wlan_hdd_power.h>
48  #include <wlan_hdd_host_offload.h>
49  #include <dbglog_host.h>
50  #include <wlan_hdd_trace.h>
51  #include <wlan_hdd_p2p.h>
52  
53  #include <linux/semaphore.h>
54  #include <wlan_hdd_hostapd.h>
55  
56  #include <linux/inetdevice.h>
57  #include <wlan_hdd_cfg.h>
58  #include <wlan_hdd_scan.h>
59  #include <wlan_hdd_stats.h>
60  #include <wlan_hdd_cfg80211.h>
61  #include <net/addrconf.h>
62  #include <wlan_hdd_lpass.h>
63  
64  #include <wma_types.h>
65  #include <ol_txrx_osif_api.h>
66  #include <ol_defines.h>
67  #include "hif.h"
68  #include "hif_unit_test_suspend.h"
69  #include "sme_power_save_api.h"
70  #include "wlan_policy_mgr_api.h"
71  #include "cdp_txrx_flow_ctrl_v2.h"
72  #include "pld_common.h"
73  #include "wlan_hdd_driver_ops.h"
74  #include <wlan_logging_sock_svc.h>
75  #include "scheduler_api.h"
76  #include "cds_utils.h"
77  #include "wlan_hdd_packet_filter_api.h"
78  #include "wlan_cfg80211_scan.h"
79  #include "wlan_ipa_ucfg_api.h"
80  #include <wlan_cfg80211_mc_cp_stats.h>
81  #include "wlan_p2p_ucfg_api.h"
82  #include "wlan_mlme_ucfg_api.h"
83  #include "wlan_osif_request_manager.h"
84  #include <wlan_hdd_sar_limits.h>
85  #include "wlan_pkt_capture_ucfg_api.h"
86  #include "wlan_hdd_thermal.h"
87  #include "wlan_hdd_object_manager.h"
88  #include <linux/igmp.h>
89  #include "qdf_types.h"
90  #include <linux/cpuidle.h>
91  #include <cdp_txrx_ctrl.h>
92  #include <wlan_cp_stats_mc_ucfg_api.h>
93  #include "wlan_dp_ucfg_api.h"
94  
95  /* Preprocessor definitions and constants */
96  #ifdef QCA_WIFI_EMULATION
97  #define HDD_SSR_BRING_UP_TIME 3000000
98  #else
99  #define HDD_SSR_BRING_UP_TIME 30000
100  #endif
101  
102  /* Type declarations */
103  
104  #ifdef FEATURE_WLAN_DIAG_SUPPORT
hdd_wlan_suspend_resume_event(uint8_t state)105  void hdd_wlan_suspend_resume_event(uint8_t state)
106  {
107  	WLAN_HOST_DIAG_EVENT_DEF(suspend_state, struct host_event_suspend);
108  	qdf_mem_zero(&suspend_state, sizeof(suspend_state));
109  
110  	suspend_state.state = state;
111  	WLAN_HOST_DIAG_EVENT_REPORT(&suspend_state, EVENT_WLAN_SUSPEND_RESUME);
112  }
113  
114  /**
115   * hdd_wlan_offload_event() - send offloads event
116   * @type: offload type
117   * @state: enabled or disabled
118   *
119   * This Function send offloads enable/disable diag event
120   *
121   * Return: void.
122   */
123  
hdd_wlan_offload_event(uint8_t type,uint8_t state)124  void hdd_wlan_offload_event(uint8_t type, uint8_t state)
125  {
126  	WLAN_HOST_DIAG_EVENT_DEF(host_offload, struct host_event_offload_req);
127  	qdf_mem_zero(&host_offload, sizeof(host_offload));
128  
129  	host_offload.offload_type = type;
130  	host_offload.state = state;
131  
132  	WLAN_HOST_DIAG_EVENT_REPORT(&host_offload, EVENT_WLAN_OFFLOAD_REQ);
133  }
134  #endif
135  
136  #ifdef WLAN_DP_LEGACY_OL_RX_THREAD
137  
138  /* timeout in msec to wait for RX_THREAD to suspend */
139  #define HDD_RXTHREAD_SUSPEND_TIMEOUT 200
140  
wlan_hdd_rx_thread_resume(struct hdd_context * hdd_ctx)141  void wlan_hdd_rx_thread_resume(struct hdd_context *hdd_ctx)
142  {
143  	if (hdd_ctx->is_ol_rx_thread_suspended) {
144  		cds_resume_rx_thread();
145  		hdd_ctx->is_ol_rx_thread_suspended = false;
146  	}
147  }
148  
wlan_hdd_rx_thread_suspend(struct hdd_context * hdd_ctx)149  int wlan_hdd_rx_thread_suspend(struct hdd_context *hdd_ctx)
150  {
151  	p_cds_sched_context cds_sched_context = get_cds_sched_ctxt();
152  	int rc;
153  
154  	if (!cds_sched_context)
155  		return 0;
156  
157  	/* Suspend tlshim rx thread */
158  	set_bit(RX_SUSPEND_EVENT, &cds_sched_context->ol_rx_event_flag);
159  	wake_up_interruptible(&cds_sched_context->ol_rx_wait_queue);
160  	rc = wait_for_completion_timeout(&cds_sched_context->
161  					 ol_suspend_rx_event,
162  					 msecs_to_jiffies
163  					 (HDD_RXTHREAD_SUSPEND_TIMEOUT)
164  					);
165  	if (!rc) {
166  		clear_bit(RX_SUSPEND_EVENT,
167  			  &cds_sched_context->ol_rx_event_flag);
168  		hdd_err("Failed to stop tl_shim rx thread");
169  		return -EINVAL;
170  	}
171  	hdd_ctx->is_ol_rx_thread_suspended = true;
172  
173  	return 0;
174  }
175  #endif /* WLAN_DP_LEGACY_OL_RX_THREAD */
176  
177  /**
178   * hdd_enable_gtk_offload() - enable GTK offload
179   * @vdev: VDEV objmgr pointer
180   *
181   * Central function to enable GTK offload.
182   *
183   * Return: nothing
184   */
hdd_enable_gtk_offload(struct wlan_objmgr_vdev * vdev)185  static void hdd_enable_gtk_offload(struct wlan_objmgr_vdev *vdev)
186  {
187  	QDF_STATUS status;
188  
189  	status = ucfg_pmo_enable_gtk_offload_in_fwr(vdev);
190  	if (status != QDF_STATUS_SUCCESS)
191  		hdd_debug("Failed to enable gtk offload");
192  }
193  
194  #ifdef WLAN_FEATURE_IGMP_OFFLOAD
195  /**
196   * hdd_send_igmp_offload_params() - enable igmp offload
197   * @adapter: pointer to the adapter
198   * @vdev: VDEV ojbmgr pointer
199   * @enable: enable/disable
200   *
201   * Return: nothing
202   */
203  static QDF_STATUS
hdd_send_igmp_offload_params(struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev,bool enable)204  hdd_send_igmp_offload_params(struct hdd_adapter *adapter,
205  			     struct wlan_objmgr_vdev *vdev, bool enable)
206  {
207  	struct in_device *in_dev = adapter->dev->ip_ptr;
208  	struct ip_mc_list *ip_list;
209  	struct pmo_igmp_offload_req *igmp_req = NULL;
210  	int count = 0;
211  	QDF_STATUS status;
212  
213  	if (!in_dev) {
214  		hdd_err("in_dev is NULL");
215  		return QDF_STATUS_E_FAILURE;
216  	}
217  
218  	ip_list = in_dev->mc_list;
219  	if (!ip_list) {
220  		hdd_debug("ip list empty");
221  		return QDF_STATUS_E_FAILURE;
222  	}
223  
224  	igmp_req = qdf_mem_malloc(sizeof(*igmp_req));
225  	if (!igmp_req)
226  		return QDF_STATUS_E_FAILURE;
227  
228  	while (ip_list && ip_list->multiaddr && enable &&
229  	       count < MAX_MC_IP_ADDR) {
230  		if (IGMP_QUERY_ADDRESS !=  ip_list->multiaddr) {
231  			igmp_req->grp_ip_address[count] = ip_list->multiaddr;
232  			count++;
233  		}
234  
235  		ip_list = ip_list->next;
236  	}
237  	igmp_req->enable = enable;
238  	igmp_req->num_grp_ip_address = count;
239  
240  	status = ucfg_pmo_enable_igmp_offload(vdev, igmp_req);
241  	if (status != QDF_STATUS_SUCCESS)
242  		hdd_debug("Failed to configure igmp offload");
243  
244  	qdf_mem_free(igmp_req);
245  	return status;
246  }
247  
248  /**
249   * hdd_enable_igmp_offload() - enable GTK offload
250   * @adapter: pointer to the adapter
251   * @vdev: VDEV objmgr pointer
252   *
253   * Enable IGMP offload in suspended case to save power
254   *
255   * Return: nothing
256   */
hdd_enable_igmp_offload(struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev)257  static void hdd_enable_igmp_offload(struct hdd_adapter *adapter,
258  				    struct wlan_objmgr_vdev *vdev)
259  {
260  	QDF_STATUS status;
261  
262  	status = hdd_send_igmp_offload_params(adapter, vdev, true);
263  	if (status != QDF_STATUS_SUCCESS)
264  		hdd_debug("Failed to enable igmp offload");
265  }
266  
267  /**
268   * hdd_disable_igmp_offload() - disable GTK offload
269   * @adapter: pointer to the adapter
270   * @vdev: VDEV objmgr pointer
271   *
272   * Enable IGMP offload in suspended case to save power
273   *
274   * Return: nothing
275   */
hdd_disable_igmp_offload(struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev)276  static void hdd_disable_igmp_offload(struct hdd_adapter *adapter,
277  				     struct wlan_objmgr_vdev *vdev)
278  {
279  	QDF_STATUS status;
280  
281  	status = hdd_send_igmp_offload_params(adapter, vdev, false);
282  	if (status != QDF_STATUS_SUCCESS)
283  		hdd_debug("Failed to disable igmp offload");
284  }
285  #else
hdd_enable_igmp_offload(struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev)286  static inline void hdd_enable_igmp_offload(struct hdd_adapter *adapter,
287  					   struct wlan_objmgr_vdev *vdev)
288  {}
289  
290  static inline QDF_STATUS
hdd_send_igmp_offload_params(struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev,bool enable)291  hdd_send_igmp_offload_params(struct hdd_adapter *adapter,
292  			     struct wlan_objmgr_vdev *vdev, bool enable)
293  {
294  	return QDF_STATUS_SUCCESS;
295  }
296  
hdd_disable_igmp_offload(struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev)297  static inline void hdd_disable_igmp_offload(struct hdd_adapter *adapter,
298  					    struct wlan_objmgr_vdev *vdev)
299  {}
300  #endif
301  
302  /**
303   * hdd_disable_gtk_offload() - disable GTK offload
304   * @adapter:   pointer to the adapter
305   * @vdev: VDEV objmgr pointer
306   *
307   * Central function to disable GTK offload.
308   *
309   * Return: nothing
310   */
hdd_disable_gtk_offload(struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev)311  static void hdd_disable_gtk_offload(struct hdd_adapter *adapter,
312  				    struct wlan_objmgr_vdev *vdev)
313  {
314  	struct pmo_gtk_rsp_req gtk_rsp_request;
315  	QDF_STATUS status;
316  
317  	/* ensure to get gtk rsp first before disable it*/
318  	gtk_rsp_request.callback = wlan_hdd_cfg80211_update_replay_counter_cb;
319  
320  	/* Passing as void* as PMO does not know legacy HDD adapter type */
321  	gtk_rsp_request.callback_context = (void *)adapter;
322  
323  	status = ucfg_pmo_get_gtk_rsp(vdev, &gtk_rsp_request);
324  	if (status != QDF_STATUS_SUCCESS) {
325  		hdd_err("Failed to send get gtk rsp status:%d", status);
326  		return;
327  	}
328  
329  	hdd_debug("send get_gtk_rsp successful");
330  	status = ucfg_pmo_disable_gtk_offload_in_fwr(vdev);
331  	if (status != QDF_STATUS_SUCCESS)
332  		hdd_info("Failed to disable gtk offload");
333  }
334  
335  #ifdef WLAN_NS_OFFLOAD
336  /**
337   * __wlan_hdd_ipv6_changed() - IPv6 notifier callback function
338   * @net_dev: net_device whose IP address changed
339   * @event: event from kernel, NETDEV_UP or NETDEV_DOWN
340   *
341   * This is a callback function that is registered with the kernel via
342   * register_inet6addr_notifier() which allows the driver to be
343   * notified when there is an IPv6 address change.
344   *
345   * Return: None
346   */
__wlan_hdd_ipv6_changed(struct net_device * net_dev,unsigned long event)347  static void __wlan_hdd_ipv6_changed(struct net_device *net_dev,
348  				    unsigned long event)
349  {
350  	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(net_dev);
351  	struct hdd_context *hdd_ctx;
352  	int errno;
353  
354  	hdd_enter_dev(net_dev);
355  
356  	errno = hdd_validate_adapter(adapter);
357  	if (errno || adapter->dev != net_dev)
358  		goto exit;
359  
360  	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
361  	errno = wlan_hdd_validate_context(hdd_ctx);
362  	if (errno)
363  		goto exit;
364  
365  	/* Only need to be notified for ipv6_add_addr
366  	 * No need for ipv6_del_addr or addrconf_ifdown
367  	 */
368  	if (event == NETDEV_UP &&
369  	    (adapter->device_mode == QDF_STA_MODE ||
370  	     adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
371  		hdd_debug("invoking sme_dhcp_done_ind");
372  		sme_dhcp_done_ind(hdd_ctx->mac_handle,
373  				  adapter->deflink->vdev_id);
374  		schedule_work(&adapter->ipv6_notifier_work);
375  	}
376  
377  exit:
378  	hdd_exit();
379  }
380  
wlan_hdd_ipv6_changed(struct notifier_block * nb,unsigned long data,void * context)381  int wlan_hdd_ipv6_changed(struct notifier_block *nb,
382  			  unsigned long data, void *context)
383  {
384  	struct inet6_ifaddr *ifa = context;
385  	struct net_device *net_dev = ifa->idev->dev;
386  	struct osif_vdev_sync *vdev_sync;
387  
388  	if (osif_vdev_sync_op_start(net_dev, &vdev_sync))
389  		return NOTIFY_DONE;
390  
391  	__wlan_hdd_ipv6_changed(net_dev, data);
392  
393  	osif_vdev_sync_op_stop(vdev_sync);
394  
395  	return NOTIFY_DONE;
396  }
397  
398  /**
399   * hdd_fill_ipv6_uc_addr() - fill IPv6 unicast addresses
400   * @idev: pointer to net device
401   * @ipv6_uc_addr: destination array to fill IPv6 addresses
402   * @ipv6addr_type: IPv6 Address type
403   * @scope_array: scope of ipv6 addr
404   * @count: number of IPv6 addresses
405   *
406   * This is the IPv6 utility function to populate unicast addresses.
407   *
408   * Return: 0 on success, error number otherwise.
409   */
hdd_fill_ipv6_uc_addr(struct inet6_dev * idev,uint8_t ipv6_uc_addr[][QDF_IPV6_ADDR_SIZE],uint8_t * ipv6addr_type,enum pmo_ns_addr_scope * scope_array,uint32_t * count)410  static int hdd_fill_ipv6_uc_addr(struct inet6_dev *idev,
411  				uint8_t ipv6_uc_addr[][QDF_IPV6_ADDR_SIZE],
412  				uint8_t *ipv6addr_type,
413  				enum pmo_ns_addr_scope *scope_array,
414  				uint32_t *count)
415  {
416  	struct inet6_ifaddr *ifa;
417  	struct list_head *p;
418  	uint32_t scope;
419  
420  	read_lock_bh(&idev->lock);
421  	list_for_each(p, &idev->addr_list) {
422  		if (*count >= PMO_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA) {
423  			read_unlock_bh(&idev->lock);
424  			return -EINVAL;
425  		}
426  		ifa = list_entry(p, struct inet6_ifaddr, if_list);
427  		if (ifa->flags & IFA_F_DADFAILED)
428  			continue;
429  		scope = ipv6_addr_src_scope(&ifa->addr);
430  		switch (scope) {
431  		case IPV6_ADDR_SCOPE_GLOBAL:
432  		case IPV6_ADDR_SCOPE_LINKLOCAL:
433  			qdf_mem_copy(ipv6_uc_addr[*count], &ifa->addr.s6_addr,
434  				sizeof(ifa->addr.s6_addr));
435  			ipv6addr_type[*count] = PMO_IPV6_ADDR_UC_TYPE;
436  			scope_array[*count] = ucfg_pmo_ns_addr_scope(scope);
437  			hdd_debug("Index %d scope = %s UC-Address: %pI6",
438  				*count, (scope == IPV6_ADDR_SCOPE_LINKLOCAL) ?
439  				"LINK LOCAL" : "GLOBAL", ipv6_uc_addr[*count]);
440  			*count += 1;
441  			break;
442  		default:
443  			hdd_warn("The Scope %d is not supported", scope);
444  		}
445  	}
446  
447  	read_unlock_bh(&idev->lock);
448  	return 0;
449  }
450  
451  /**
452   * hdd_fill_ipv6_ac_addr() - fill IPv6 anycast addresses
453   * @idev: pointer to net device
454   * @ipv6_ac_addr: destination array to fill IPv6 addresses
455   * @ipv6addr_type: IPv6 Address type
456   * @scope_array: scope of ipv6 addr
457   * @count: number of IPv6 addresses
458   *
459   * This is the IPv6 utility function to populate anycast addresses.
460   *
461   * Return: 0 on success, error number otherwise.
462   */
hdd_fill_ipv6_ac_addr(struct inet6_dev * idev,uint8_t ipv6_ac_addr[][QDF_IPV6_ADDR_SIZE],uint8_t * ipv6addr_type,enum pmo_ns_addr_scope * scope_array,uint32_t * count)463  static int hdd_fill_ipv6_ac_addr(struct inet6_dev *idev,
464  				uint8_t ipv6_ac_addr[][QDF_IPV6_ADDR_SIZE],
465  				uint8_t *ipv6addr_type,
466  				enum pmo_ns_addr_scope *scope_array,
467  				uint32_t *count)
468  {
469  	struct ifacaddr6 *ifaca;
470  	uint32_t scope;
471  
472  	read_lock_bh(&idev->lock);
473  	for (ifaca = idev->ac_list; ifaca; ifaca = ifaca->aca_next) {
474  		if (*count >= PMO_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA) {
475  			read_unlock_bh(&idev->lock);
476  			return -EINVAL;
477  		}
478  		/* For anycast addr no DAD */
479  		scope = ipv6_addr_src_scope(&ifaca->aca_addr);
480  		switch (scope) {
481  		case IPV6_ADDR_SCOPE_GLOBAL:
482  		case IPV6_ADDR_SCOPE_LINKLOCAL:
483  			qdf_mem_copy(ipv6_ac_addr[*count], &ifaca->aca_addr,
484  				sizeof(ifaca->aca_addr));
485  			ipv6addr_type[*count] = PMO_IPV6_ADDR_AC_TYPE;
486  			scope_array[*count] = ucfg_pmo_ns_addr_scope(scope);
487  			hdd_debug("Index %d scope = %s AC-Address: %pI6",
488  				*count, (scope == IPV6_ADDR_SCOPE_LINKLOCAL) ?
489  				"LINK LOCAL" : "GLOBAL", ipv6_ac_addr[*count]);
490  			*count += 1;
491  			break;
492  		default:
493  			hdd_warn("The Scope %d is not supported", scope);
494  		}
495  	}
496  
497  	read_unlock_bh(&idev->lock);
498  	return 0;
499  }
500  
hdd_enable_ns_offload(struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev,enum pmo_offload_trigger trigger)501  void hdd_enable_ns_offload(struct hdd_adapter *adapter,
502  			   struct wlan_objmgr_vdev *vdev,
503  			   enum pmo_offload_trigger trigger)
504  {
505  	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
506  	struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
507  	struct inet6_dev *in6_dev;
508  	struct pmo_ns_req *ns_req;
509  	QDF_STATUS status;
510  	int errno;
511  	uint8_t vdev_id;
512  
513  	hdd_enter();
514  
515  	if (!psoc) {
516  		hdd_err("psoc is NULL");
517  		goto out;
518  	}
519  
520  	in6_dev = __in6_dev_get(adapter->dev);
521  	if (!in6_dev) {
522  		hdd_err("IPv6 dev does not exist. Failed to request NSOffload");
523  		goto out;
524  	}
525  
526  	ns_req = qdf_mem_malloc(sizeof(*ns_req));
527  	if (!ns_req)
528  		goto out;
529  
530  	vdev_id = wlan_vdev_get_id(vdev);
531  
532  	ns_req->psoc = psoc;
533  	ns_req->vdev_id = vdev_id;
534  	ns_req->trigger = trigger;
535  	ns_req->count = 0;
536  
537  	/* check if offload cache and send is required or not */
538  	status = ucfg_pmo_ns_offload_check(psoc, trigger, vdev_id);
539  	if (QDF_IS_STATUS_ERROR(status)) {
540  		hdd_debug("NS offload is not required");
541  		goto free_req;
542  	}
543  
544  	if (ucfg_pmo_get_arp_ns_offload_dynamic_disable(vdev)) {
545  		hdd_debug("Dynamic arp ns offload disabled");
546  		ucfg_pmo_flush_ns_offload_req(vdev);
547  		goto skip_cache_ns;
548  	}
549  
550  	/* Unicast Addresses */
551  	errno = hdd_fill_ipv6_uc_addr(in6_dev, ns_req->ipv6_addr,
552  				      ns_req->ipv6_addr_type, ns_req->scope,
553  				      &ns_req->count);
554  	if (errno) {
555  		hdd_disable_ns_offload(adapter, vdev, trigger);
556  		hdd_debug("Max supported addresses: disabling NS offload");
557  		goto free_req;
558  	}
559  
560  	/* Anycast Addresses */
561  	errno = hdd_fill_ipv6_ac_addr(in6_dev, ns_req->ipv6_addr,
562  				      ns_req->ipv6_addr_type, ns_req->scope,
563  				      &ns_req->count);
564  	if (errno) {
565  		hdd_disable_ns_offload(adapter, vdev, trigger);
566  		hdd_debug("Max supported addresses: disabling NS offload");
567  		goto free_req;
568  	}
569  
570  	/* cache ns request */
571  	status = ucfg_pmo_cache_ns_offload_req(ns_req);
572  	if (QDF_IS_STATUS_ERROR(status)) {
573  		hdd_debug("Failed to cache ns request; status:%d", status);
574  		goto free_req;
575  	}
576  
577  skip_cache_ns:
578  	/* enable ns request */
579  	status = ucfg_pmo_enable_ns_offload_in_fwr(vdev, trigger);
580  	if (QDF_IS_STATUS_ERROR(status)) {
581  		hdd_debug("Failed to enable ns offload; status:%d", status);
582  		goto free_req;
583  	}
584  
585  	hdd_wlan_offload_event(SIR_IPV6_NS_OFFLOAD, SIR_OFFLOAD_ENABLE);
586  free_req:
587  	qdf_mem_free(ns_req);
588  
589  out:
590  	hdd_exit();
591  }
592  
hdd_disable_ns_offload(struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev,enum pmo_offload_trigger trigger)593  void hdd_disable_ns_offload(struct hdd_adapter *adapter,
594  			    struct wlan_objmgr_vdev *vdev,
595  			    enum pmo_offload_trigger trigger)
596  {
597  	QDF_STATUS status;
598  	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
599  
600  	hdd_enter();
601  
602  	status = ucfg_pmo_ns_offload_check(hdd_ctx->psoc, trigger,
603  					   wlan_vdev_get_id(vdev));
604  	if (status != QDF_STATUS_SUCCESS) {
605  		hdd_debug("Flushing of NS offload not required");
606  		goto out;
607  	}
608  
609  	status = ucfg_pmo_flush_ns_offload_req(vdev);
610  	if (status != QDF_STATUS_SUCCESS) {
611  		hdd_err("Failed to flush NS Offload");
612  		goto out;
613  	}
614  
615  	status = ucfg_pmo_disable_ns_offload_in_fwr(vdev, trigger);
616  	if (status != QDF_STATUS_SUCCESS)
617  		hdd_err("Failed to disable NS Offload");
618  	else
619  		hdd_wlan_offload_event(SIR_IPV6_NS_OFFLOAD,
620  			SIR_OFFLOAD_DISABLE);
621  out:
622  	hdd_exit();
623  
624  }
625  
626  #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC)
627  #ifdef WLAN_HDD_MULTI_VDEV_SINGLE_NDEV
hdd_send_mlo_ps_to_fw(struct hdd_adapter * adapter)628  static void hdd_send_mlo_ps_to_fw(struct hdd_adapter *adapter)
629  {
630  	struct wlan_hdd_link_info *link_info;
631  	mac_handle_t mac_handle;
632  
633  	if (!adapter) {
634  		hdd_err_rl("null hdd_adapter pointer");
635  		return;
636  	}
637  
638  	mac_handle = hdd_adapter_get_mac_handle(adapter);
639  
640  	if (!mac_handle) {
641  		hdd_err_rl("null mac_handle pointer");
642  		return;
643  	}
644  
645  	hdd_adapter_for_each_active_link_info(adapter, link_info)
646  		sme_ps_update(mac_handle, link_info->vdev_id);
647  }
648  #else
hdd_send_mlo_ps_to_fw(struct hdd_adapter * adapter)649  static void hdd_send_mlo_ps_to_fw(struct hdd_adapter *adapter)
650  {
651  	int i;
652  	struct hdd_adapter *link_adapter;
653  	struct hdd_mlo_adapter_info *mlo_adapter_info;
654  	mac_handle_t mac_handle;
655  
656  	if (!adapter) {
657  		hdd_err_rl("null hdd_adapter pointer");
658  		return;
659  	}
660  
661  	mac_handle = hdd_adapter_get_mac_handle(adapter);
662  
663  	if (!mac_handle) {
664  		hdd_err_rl("null mac_handle pointer");
665  		return;
666  	}
667  
668  	mlo_adapter_info = &adapter->mlo_adapter_info;
669  	for (i = 0; i < WLAN_MAX_MLD; i++) {
670  		link_adapter = mlo_adapter_info->link_adapter[i];
671  		if (!link_adapter)
672  			continue;
673  		sme_ps_update(mac_handle, link_adapter->deflink->vdev_id);
674  	}
675  }
676  #endif
677  #else
hdd_send_mlo_ps_to_fw(struct hdd_adapter * adapter)678  static inline void hdd_send_mlo_ps_to_fw(struct hdd_adapter *adapter)
679  {}
680  #endif
681  
hdd_send_ps_config_to_fw(struct hdd_adapter * adapter)682  void hdd_send_ps_config_to_fw(struct hdd_adapter *adapter)
683  {
684  	struct hdd_context *hdd_ctx;
685  	bool is_mlo_vdev;
686  
687  	if (hdd_validate_adapter(adapter))
688  		return;
689  
690  	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
691  
692  	is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(adapter->deflink->vdev);
693  
694  	if (!is_mlo_vdev) {
695  		sme_ps_update(hdd_ctx->mac_handle, adapter->deflink->vdev_id);
696  		return;
697  	}
698  
699  	hdd_send_mlo_ps_to_fw(adapter);
700  }
701  
702  /**
703   * __hdd_ipv6_notifier_work_queue() - IPv6 notification work function
704   * @adapter: adapter whose IP address changed
705   *
706   * This function performs the work initially triggered by a callback
707   * from the IPv6 netdev notifier.  Since this means there has been a
708   * change in IPv6 state for the interface, the NS offload is
709   * reconfigured.
710   *
711   * Return: None
712   */
__hdd_ipv6_notifier_work_queue(struct hdd_adapter * adapter)713  static void __hdd_ipv6_notifier_work_queue(struct hdd_adapter *adapter)
714  {
715  	struct hdd_context *hdd_ctx;
716  	int errno;
717  	struct wlan_objmgr_vdev *vdev;
718  
719  	hdd_enter();
720  
721  	errno = hdd_validate_adapter(adapter);
722  	if (errno)
723  		goto exit;
724  
725  	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
726  	errno = wlan_hdd_validate_context(hdd_ctx);
727  	if (errno)
728  		goto exit;
729  
730  	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
731  	if (!vdev)
732  		goto exit;
733  
734  	hdd_enable_ns_offload(adapter, vdev, pmo_ipv6_change_notify);
735  	hdd_enable_icmp_offload(adapter, vdev, pmo_ipv6_change_notify);
736  	hdd_send_ps_config_to_fw(adapter);
737  
738  	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
739  exit:
740  	hdd_exit();
741  }
742  
hdd_ipv6_notifier_work_queue(struct work_struct * work)743  void hdd_ipv6_notifier_work_queue(struct work_struct *work)
744  {
745  	struct hdd_adapter *adapter = container_of(work, struct hdd_adapter,
746  						   ipv6_notifier_work);
747  	struct osif_vdev_sync *vdev_sync;
748  
749  	if (osif_vdev_sync_op_start(adapter->dev, &vdev_sync))
750  		return;
751  
752  	__hdd_ipv6_notifier_work_queue(adapter);
753  
754  	osif_vdev_sync_op_stop(vdev_sync);
755  }
756  #endif /* WLAN_NS_OFFLOAD */
757  
hdd_enable_hw_filter(struct wlan_objmgr_vdev * vdev)758  static void hdd_enable_hw_filter(struct wlan_objmgr_vdev *vdev)
759  {
760  	QDF_STATUS status;
761  
762  	hdd_enter();
763  
764  	status = ucfg_pmo_enable_hw_filter_in_fwr(vdev);
765  	if (status != QDF_STATUS_SUCCESS)
766  		hdd_info("Failed to enable hardware filter");
767  
768  	hdd_exit();
769  }
770  
hdd_disable_hw_filter(struct wlan_objmgr_vdev * vdev)771  static void hdd_disable_hw_filter(struct wlan_objmgr_vdev *vdev)
772  {
773  	QDF_STATUS status;
774  
775  	hdd_enter();
776  
777  	status = ucfg_pmo_disable_hw_filter_in_fwr(vdev);
778  	if (status != QDF_STATUS_SUCCESS)
779  		hdd_info("Failed to disable hardware filter");
780  
781  	hdd_exit();
782  }
783  
hdd_enable_action_frame_patterns(struct wlan_objmgr_vdev * vdev)784  static void hdd_enable_action_frame_patterns(struct wlan_objmgr_vdev *vdev)
785  {
786  	QDF_STATUS status;
787  
788  	hdd_enter();
789  
790  	status = ucfg_pmo_enable_action_frame_patterns(vdev,
791  						       QDF_SYSTEM_SUSPEND);
792  	if (QDF_IS_STATUS_ERROR(status))
793  		hdd_info("Failed to enable action frame patterns");
794  
795  	hdd_exit();
796  }
797  
hdd_disable_action_frame_patterns(struct wlan_objmgr_vdev * vdev)798  static void hdd_disable_action_frame_patterns(struct wlan_objmgr_vdev *vdev)
799  {
800  	QDF_STATUS status;
801  
802  	hdd_enter();
803  
804  	status = ucfg_pmo_disable_action_frame_patterns(vdev);
805  	if (QDF_IS_STATUS_ERROR(status))
806  		hdd_info("Failed to disable action frame patterns");
807  
808  	hdd_exit();
809  }
810  
hdd_enable_host_offloads(struct hdd_adapter * adapter,enum pmo_offload_trigger trigger)811  void hdd_enable_host_offloads(struct hdd_adapter *adapter,
812  	enum pmo_offload_trigger trigger)
813  {
814  	struct wlan_objmgr_vdev *vdev;
815  
816  	hdd_enter();
817  
818  	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
819  					   WLAN_OSIF_POWER_ID);
820  	if (!vdev) {
821  		hdd_err("vdev is NULL");
822  		goto out;
823  	}
824  
825  	if (!ucfg_pmo_is_vdev_supports_offload(vdev)) {
826  		hdd_debug("offload is not supported on vdev opmode %d",
827  			  adapter->device_mode);
828  		goto put_vdev;
829  	}
830  
831  	if (!ucfg_pmo_is_vdev_connected(vdev)) {
832  		hdd_debug("offload is not supported on disconnected vdevs");
833  		goto put_vdev;
834  	}
835  
836  	hdd_debug("enable offloads");
837  	hdd_enable_gtk_offload(vdev);
838  	hdd_enable_arp_offload(adapter, vdev, trigger);
839  	hdd_enable_ns_offload(adapter, vdev, trigger);
840  	hdd_enable_mc_addr_filtering(adapter, trigger);
841  	if (adapter->device_mode == QDF_STA_MODE)
842  		hdd_enable_igmp_offload(adapter, vdev);
843  
844  	if (adapter->device_mode != QDF_NDI_MODE)
845  		hdd_enable_hw_filter(vdev);
846  	hdd_enable_action_frame_patterns(vdev);
847  put_vdev:
848  	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
849  out:
850  	hdd_exit();
851  
852  }
853  
hdd_disable_host_offloads(struct hdd_adapter * adapter,enum pmo_offload_trigger trigger)854  void hdd_disable_host_offloads(struct hdd_adapter *adapter,
855  	enum pmo_offload_trigger trigger)
856  {
857  	struct wlan_objmgr_vdev *vdev;
858  
859  	hdd_enter();
860  
861  	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
862  					   WLAN_OSIF_POWER_ID);
863  	if (!vdev) {
864  		hdd_err("vdev is NULL");
865  		goto out;
866  	}
867  
868  	if (!ucfg_pmo_is_vdev_supports_offload(vdev)) {
869  		hdd_info("offload is not supported on this vdev opmode: %d",
870  				adapter->device_mode);
871  			goto put_vdev;
872  	}
873  
874  	if (!ucfg_pmo_is_vdev_connected(vdev)) {
875  		hdd_info("vdev is not connected");
876  		goto put_vdev;
877  	}
878  
879  	hdd_debug("disable offloads");
880  	hdd_disable_gtk_offload(adapter, vdev);
881  	hdd_disable_arp_offload(adapter, vdev, trigger);
882  	hdd_disable_ns_offload(adapter, vdev, trigger);
883  	hdd_disable_mc_addr_filtering(adapter, trigger);
884  	if (adapter->device_mode == QDF_STA_MODE)
885  		hdd_disable_igmp_offload(adapter, vdev);
886  	if (adapter->device_mode != QDF_NDI_MODE)
887  		hdd_disable_hw_filter(vdev);
888  	hdd_disable_action_frame_patterns(vdev);
889  
890  put_vdev:
891  	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
892  out:
893  	hdd_exit();
894  
895  }
896  
897  /**
898   * hdd_lookup_ifaddr() - Lookup interface address data by name
899   * @adapter: the adapter whose name should be searched for
900   *
901   * return in_ifaddr pointer on success, NULL for failure
902   */
hdd_lookup_ifaddr(struct hdd_adapter * adapter)903  static struct in_ifaddr *hdd_lookup_ifaddr(struct hdd_adapter *adapter)
904  {
905  	struct in_ifaddr *ifa;
906  	struct in_device *in_dev;
907  
908  	if (!adapter) {
909  		hdd_err("adapter is null");
910  		return NULL;
911  	}
912  
913  	in_dev = __in_dev_get_rtnl(adapter->dev);
914  	if (!in_dev) {
915  		hdd_err("Failed to get in_device");
916  		return NULL;
917  	}
918  
919  	/* lookup address data by interface name */
920  	for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
921  		if (!strcmp(adapter->dev->name, ifa->ifa_label))
922  			return ifa;
923  	}
924  
925  	return NULL;
926  }
927  
928  /**
929   * hdd_populate_ipv4_addr() - Populates the adapter's IPv4 address
930   * @adapter: the adapter whose IPv4 address is desired
931   * @ipv4_addr: the address of the array to copy the IPv4 address into
932   *
933   * return: zero for success; non-zero for failure
934   */
hdd_populate_ipv4_addr(struct hdd_adapter * adapter,uint8_t * ipv4_addr)935  static int hdd_populate_ipv4_addr(struct hdd_adapter *adapter,
936  				  uint8_t *ipv4_addr)
937  {
938  	struct in_ifaddr *ifa;
939  	int i;
940  
941  	if (!adapter) {
942  		hdd_err("adapter is null");
943  		return -EINVAL;
944  	}
945  
946  	if (!ipv4_addr) {
947  		hdd_err("ipv4_addr is null");
948  		return -EINVAL;
949  	}
950  
951  	ifa = hdd_lookup_ifaddr(adapter);
952  	if (!ifa || !ifa->ifa_local) {
953  		hdd_err("ipv4 address not found");
954  		return -EINVAL;
955  	}
956  
957  	/* convert u32 to byte array */
958  	for (i = 0; i < 4; i++)
959  		ipv4_addr[i] = (ifa->ifa_local >> i * 8) & 0xff;
960  
961  	return 0;
962  }
963  
hdd_set_grat_arp_keepalive(struct hdd_adapter * adapter)964  int hdd_set_grat_arp_keepalive(struct hdd_adapter *adapter)
965  {
966  	QDF_STATUS status;
967  	int exit_code;
968  	struct hdd_context *hdd_ctx;
969  	struct hdd_station_ctx *sta_ctx;
970  	struct keep_alive_req req = {
971  		.packetType = SIR_KEEP_ALIVE_UNSOLICIT_ARP_RSP,
972  		.dest_macaddr = QDF_MAC_ADDR_BCAST_INIT,
973  	};
974  
975  	if (!adapter) {
976  		hdd_err("adapter is null");
977  		return -EINVAL;
978  	}
979  
980  	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
981  	if (!hdd_ctx) {
982  		hdd_err("hdd_ctx is null");
983  		return -EINVAL;
984  	}
985  
986  	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
987  	if (!sta_ctx) {
988  		hdd_err("sta_ctx is null");
989  		return -EINVAL;
990  	}
991  
992  	exit_code = hdd_populate_ipv4_addr(adapter, req.hostIpv4Addr);
993  	if (exit_code) {
994  		hdd_err("Failed to populate ipv4 address");
995  		return exit_code;
996  	}
997  
998  	/* according to RFC5227, sender/target ip address should be the same */
999  	qdf_mem_copy(&req.destIpv4Addr, &req.hostIpv4Addr,
1000  		     sizeof(req.destIpv4Addr));
1001  
1002  	qdf_copy_macaddr(&req.bssid, &sta_ctx->conn_info.bssid);
1003  	ucfg_mlme_get_sta_keep_alive_period(hdd_ctx->psoc, &req.timePeriod);
1004  	req.sessionId = adapter->deflink->vdev_id;
1005  
1006  	hdd_debug("Setting gratuitous ARP keepalive; ipv4_addr:%u.%u.%u.%u",
1007  		 req.hostIpv4Addr[0], req.hostIpv4Addr[1],
1008  		 req.hostIpv4Addr[2], req.hostIpv4Addr[3]);
1009  
1010  	status = sme_set_keep_alive(hdd_ctx->mac_handle, req.sessionId, &req);
1011  	if (QDF_IS_STATUS_ERROR(status)) {
1012  		hdd_err("Failed to set keepalive");
1013  		return qdf_status_to_os_return(status);
1014  	}
1015  
1016  	return 0;
1017  }
1018  
1019  /**
1020   * __hdd_ipv4_notifier_work_queue() - IPv4 notification work function
1021   * @adapter: adapter whose IP address changed
1022   *
1023   * This function performs the work initially triggered by a callback
1024   * from the IPv4 netdev notifier.  Since this means there has been a
1025   * change in IPv4 state for the interface, the ARP offload is
1026   * reconfigured. Also, Updates the HLP IE info with IP address info
1027   * to fw if LFR3 is enabled
1028   *
1029   * Return: None
1030   */
__hdd_ipv4_notifier_work_queue(struct hdd_adapter * adapter)1031  static void __hdd_ipv4_notifier_work_queue(struct hdd_adapter *adapter)
1032  {
1033  	struct hdd_context *hdd_ctx;
1034  	int errno;
1035  	struct in_ifaddr *ifa;
1036  	enum station_keepalive_method val;
1037  	QDF_STATUS status;
1038  	struct wlan_objmgr_vdev *vdev;
1039  
1040  	hdd_enter();
1041  
1042  	errno = hdd_validate_adapter(adapter);
1043  	if (errno)
1044  		goto exit;
1045  
1046  	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1047  	errno = wlan_hdd_validate_context(hdd_ctx);
1048  	if (errno)
1049  		goto exit;
1050  
1051  	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
1052  	if (!vdev)
1053  		goto exit;
1054  
1055  	hdd_enable_arp_offload(adapter, vdev, pmo_ipv4_change_notify);
1056  	hdd_enable_icmp_offload(adapter, vdev, pmo_ipv4_change_notify);
1057  
1058  	status = ucfg_mlme_get_sta_keepalive_method(hdd_ctx->psoc, &val);
1059  	if (QDF_IS_STATUS_ERROR(status))
1060  		goto vdev_ref;
1061  
1062  	if (val == MLME_STA_KEEPALIVE_GRAT_ARP)
1063  		hdd_set_grat_arp_keepalive(adapter);
1064  
1065  	hdd_debug("FILS Roaming support: %d",
1066  		  hdd_ctx->is_fils_roaming_supported);
1067  
1068  	ifa = hdd_lookup_ifaddr(adapter);
1069  	if (ifa && hdd_ctx->is_fils_roaming_supported)
1070  		sme_send_hlp_ie_info(hdd_ctx->mac_handle,
1071  				     wlan_vdev_get_id(vdev),
1072  				     ifa->ifa_local);
1073  	hdd_send_ps_config_to_fw(adapter);
1074  
1075  vdev_ref:
1076  	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
1077  exit:
1078  	hdd_exit();
1079  }
1080  
hdd_ipv4_notifier_work_queue(struct work_struct * work)1081  void hdd_ipv4_notifier_work_queue(struct work_struct *work)
1082  {
1083  	struct hdd_adapter *adapter = container_of(work, struct hdd_adapter,
1084  						   ipv4_notifier_work);
1085  	struct osif_vdev_sync *vdev_sync;
1086  
1087  	if (osif_vdev_sync_op_start(adapter->dev, &vdev_sync))
1088  		return;
1089  
1090  	__hdd_ipv4_notifier_work_queue(adapter);
1091  
1092  	osif_vdev_sync_op_stop(vdev_sync);
1093  }
1094  
1095  /**
1096   * __wlan_hdd_ipv4_changed() - IPv4 notifier callback function
1097   * @net_dev: the net_device whose IP address changed
1098   *
1099   * This is a callback function that is registered with the kernel via
1100   * register_inetaddr_notifier() which allows the driver to be
1101   * notified when there is an IPv4 address change.
1102   *
1103   * Return: None
1104   */
__wlan_hdd_ipv4_changed(struct net_device * net_dev)1105  static void __wlan_hdd_ipv4_changed(struct net_device *net_dev)
1106  {
1107  	struct in_ifaddr *ifa;
1108  	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(net_dev);
1109  	struct hdd_context *hdd_ctx;
1110  	int errno;
1111  
1112  	hdd_enter_dev(net_dev);
1113  
1114  	errno = hdd_validate_adapter(adapter);
1115  	if (errno || adapter->dev != net_dev)
1116  		goto exit;
1117  
1118  	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1119  	errno = wlan_hdd_validate_context(hdd_ctx);
1120  	if (errno)
1121  		goto exit;
1122  
1123  	if (adapter->device_mode == QDF_STA_MODE ||
1124  	    adapter->device_mode == QDF_P2P_CLIENT_MODE) {
1125  		hdd_debug("invoking sme_dhcp_done_ind");
1126  		sme_dhcp_done_ind(hdd_ctx->mac_handle,
1127  				  adapter->deflink->vdev_id);
1128  
1129  		if (!ucfg_pmo_is_arp_offload_enabled(hdd_ctx->psoc)) {
1130  			hdd_debug("Offload not enabled");
1131  			goto exit;
1132  		}
1133  
1134  		ifa = hdd_lookup_ifaddr(adapter);
1135  		if (ifa && ifa->ifa_local)
1136  			schedule_work(&adapter->ipv4_notifier_work);
1137  	}
1138  
1139  exit:
1140  	hdd_exit();
1141  }
1142  
wlan_hdd_ipv4_changed(struct notifier_block * nb,unsigned long data,void * context)1143  int wlan_hdd_ipv4_changed(struct notifier_block *nb,
1144  			  unsigned long data, void *context)
1145  {
1146  	struct in_ifaddr *ifa = context;
1147  	struct net_device *net_dev = ifa->ifa_dev->dev;
1148  	struct osif_vdev_sync *vdev_sync;
1149  
1150  	if (osif_vdev_sync_op_start(net_dev, &vdev_sync))
1151  		return NOTIFY_DONE;
1152  
1153  	__wlan_hdd_ipv4_changed(net_dev);
1154  
1155  	osif_vdev_sync_op_stop(vdev_sync);
1156  
1157  	return NOTIFY_DONE;
1158  }
1159  
1160  #ifdef FEATURE_RUNTIME_PM
1161  /* For CPU, the enter & exit latency of the deepest LPM mode(CXPC)
1162   * is about ~10ms. so long as required QoS latency is longer than 10ms,
1163   * CPU can enter CXPC mode.
1164   * The vote value is in microseconds.
1165   */
wlan_hdd_is_cpu_cxpc_allowed(struct hdd_context * hdd_ctx,unsigned long vote)1166  static bool wlan_hdd_is_cpu_cxpc_allowed(struct hdd_context *hdd_ctx,
1167  					 unsigned long vote)
1168  {
1169  	if (vote >= hdd_ctx->config->cpu_cxpc_threshold)
1170  		return true;
1171  	else
1172  		return false;
1173  }
1174  
wlan_hdd_pm_qos_notify(struct notifier_block * nb,unsigned long curr_val,void * context)1175  int wlan_hdd_pm_qos_notify(struct notifier_block *nb, unsigned long curr_val,
1176  			   void *context)
1177  {
1178  	struct hdd_context *hdd_ctx = container_of(nb, struct hdd_context,
1179  						   pm_qos_notifier);
1180  	void *hif_ctx;
1181  	bool is_any_sta_connected = false;
1182  
1183  	if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
1184  		hdd_debug_rl("Driver Module closed; skipping pm qos notify");
1185  		return 0;
1186  	}
1187  
1188  	hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1189  	if (!hif_ctx)
1190  		return -EINVAL;
1191  
1192  	is_any_sta_connected = hdd_is_any_sta_connected(hdd_ctx);
1193  
1194  	hdd_debug("PM QOS update: runtime_pm_prevented %d Current value: %ld, is_any_sta_connected %d",
1195  		  hdd_ctx->runtime_pm_prevented, curr_val,
1196  		  is_any_sta_connected);
1197  	qdf_spin_lock_irqsave(&hdd_ctx->pm_qos_lock);
1198  
1199  	if (!hdd_ctx->runtime_pm_prevented &&
1200  	    is_any_sta_connected &&
1201  	    !wlan_hdd_is_cpu_cxpc_allowed(hdd_ctx, curr_val)) {
1202  		hif_rtpm_get(HIF_RTPM_GET_NORESUME, HIF_RTPM_ID_PM_QOS_NOTIFY);
1203  		hdd_ctx->runtime_pm_prevented = true;
1204  	} else if (hdd_ctx->runtime_pm_prevented &&
1205  		   wlan_hdd_is_cpu_cxpc_allowed(hdd_ctx, curr_val)) {
1206  		hif_rtpm_put(HIF_RTPM_PUT_NOIDLE, HIF_RTPM_ID_PM_QOS_NOTIFY);
1207  		hdd_ctx->runtime_pm_prevented = false;
1208  	}
1209  
1210  	qdf_spin_unlock_irqrestore(&hdd_ctx->pm_qos_lock);
1211  
1212  	return NOTIFY_DONE;
1213  }
1214  
1215  /** cpuidle_governor_latency_req() is not exported by upstream kernel **/
1216  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) && \
1217  	defined(__ANDROID_COMMON_KERNEL__))
wlan_hdd_is_cpu_pm_qos_in_progress(struct hdd_context * hdd_ctx)1218  bool wlan_hdd_is_cpu_pm_qos_in_progress(struct hdd_context *hdd_ctx)
1219  {
1220  	long long curr_val_ns;
1221  	long long curr_val_us;
1222  	int max_cpu_num;
1223  
1224  	if (!hdd_is_any_sta_connected(hdd_ctx)) {
1225  		hdd_debug("No active wifi connections. Ignore PM QOS vote");
1226  		return false;
1227  	}
1228  
1229  	max_cpu_num  = nr_cpu_ids - 1;
1230  
1231  	/* Get PM QoS vote from last cpu, as no device votes on that cpu
1232  	 * so by default we get global PM QoS vote from last cpu.
1233  	 */
1234  	curr_val_ns = cpuidle_governor_latency_req(max_cpu_num);
1235  	curr_val_us = curr_val_ns / NSEC_PER_USEC;
1236  	hdd_debug("PM QoS current value: %lld", curr_val_us);
1237  	if (!wlan_hdd_is_cpu_cxpc_allowed(hdd_ctx, curr_val_us))
1238  		return true;
1239  	else
1240  		return false;
1241  }
1242  #endif
1243  #endif
1244  
1245  /**
1246   * hdd_get_ipv4_local_interface() - get ipv4 local interface from iface list
1247   * @adapter: Adapter context for which ARP offload is to be configured
1248   *
1249   * Return:
1250   *	ifa - on successful operation,
1251   *	NULL - on failure of operation
1252   */
hdd_get_ipv4_local_interface(struct hdd_adapter * adapter)1253  static struct in_ifaddr *hdd_get_ipv4_local_interface(
1254  				struct hdd_adapter *adapter)
1255  {
1256  	struct in_ifaddr **ifap = NULL;
1257  	struct in_ifaddr *ifa = NULL;
1258  	struct in_device *in_dev;
1259  
1260  	in_dev = __in_dev_get_rtnl(adapter->dev);
1261  	if (in_dev) {
1262  		for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
1263  			     ifap = &ifa->ifa_next) {
1264  			if (!strcmp(adapter->dev->name, ifa->ifa_label)) {
1265  				/* if match break */
1266  				return ifa;
1267  			}
1268  		}
1269  	}
1270  	ifa = NULL;
1271  
1272  	return ifa;
1273  }
1274  
hdd_enable_arp_offload(struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev,enum pmo_offload_trigger trigger)1275  void hdd_enable_arp_offload(struct hdd_adapter *adapter,
1276  			    struct wlan_objmgr_vdev *vdev,
1277  			    enum pmo_offload_trigger trigger)
1278  {
1279  	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1280  	struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
1281  	QDF_STATUS status;
1282  	struct pmo_arp_req *arp_req;
1283  	struct in_ifaddr *ifa;
1284  	uint8_t vdev_id;
1285  
1286  	hdd_enter();
1287  
1288  	arp_req = qdf_mem_malloc(sizeof(*arp_req));
1289  	if (!arp_req)
1290  		return;
1291  
1292  	vdev_id =  wlan_vdev_get_id(vdev);
1293  
1294  	arp_req->psoc = psoc;
1295  	arp_req->vdev_id = vdev_id;
1296  	arp_req->trigger = trigger;
1297  
1298  	status = ucfg_pmo_check_arp_offload(psoc, trigger, vdev_id);
1299  	if (QDF_IS_STATUS_ERROR(status)) {
1300  		hdd_debug("ARP offload not required");
1301  		goto free_req;
1302  	}
1303  
1304  	if (ucfg_pmo_get_arp_ns_offload_dynamic_disable(vdev)) {
1305  		hdd_debug("Dynamic arp ns offload disabled");
1306  		ucfg_pmo_flush_arp_offload_req(vdev);
1307  		goto skip_cache_arp;
1308  	}
1309  
1310  	ifa = hdd_get_ipv4_local_interface(adapter);
1311  	if (!ifa || !ifa->ifa_local) {
1312  		hdd_info("IP Address is not assigned");
1313  		status = QDF_STATUS_NOT_INITIALIZED;
1314  		goto free_req;
1315  	}
1316  
1317  	arp_req->ipv4_addr = (uint32_t)ifa->ifa_local;
1318  
1319  	status = ucfg_pmo_cache_arp_offload_req(arp_req);
1320  	if (QDF_IS_STATUS_ERROR(status)) {
1321  		hdd_err("failed to cache arp offload req; status:%d", status);
1322  		goto free_req;
1323  	}
1324  
1325  skip_cache_arp:
1326  	status = ucfg_pmo_enable_arp_offload_in_fwr(vdev, trigger);
1327  	if (QDF_IS_STATUS_ERROR(status)) {
1328  		hdd_err("failed arp offload config in fw; status:%d", status);
1329  		goto free_req;
1330  	}
1331  
1332  	hdd_wlan_offload_event(PMO_IPV4_ARP_REPLY_OFFLOAD, PMO_OFFLOAD_ENABLE);
1333  
1334  free_req:
1335  	qdf_mem_free(arp_req);
1336  }
1337  
1338  #ifdef WLAN_FEATURE_ICMP_OFFLOAD
1339  /**
1340   * hdd_fill_ipv4_addr() - fill IPv4 addresses
1341   * @adapter: Adapter context for which ICMP offload is to be configured
1342   * @pmo_icmp_req: pointer to ICMP offload request params
1343   *
1344   * This is the IPv4 utility function to populate address.
1345   *
1346   * Return: 0 on success, error number otherwise.
1347   */
hdd_fill_ipv4_addr(struct hdd_adapter * adapter,struct pmo_icmp_offload * pmo_icmp_req)1348  static int hdd_fill_ipv4_addr(struct hdd_adapter *adapter,
1349  			      struct pmo_icmp_offload *pmo_icmp_req)
1350  {
1351  	struct in_ifaddr *ifa;
1352  	uint8_t ipv4_addr_array[QDF_IPV4_ADDR_SIZE];
1353  	int i;
1354  
1355  	ifa = hdd_get_ipv4_local_interface(adapter);
1356  	if (!ifa || !ifa->ifa_local) {
1357  		hdd_debug("IP Address is not assigned");
1358  		return -EINVAL;
1359  	}
1360  
1361  	/* converting u32 to IPv4 address */
1362  	for (i = 0; i < QDF_IPV4_ADDR_SIZE; i++)
1363  		ipv4_addr_array[i] = (ifa->ifa_local >> i * 8) & 0xff;
1364  
1365  	qdf_mem_copy(pmo_icmp_req->ipv4_addr, &ipv4_addr_array,
1366  		     QDF_IPV4_ADDR_SIZE);
1367  
1368  	return 0;
1369  }
1370  
1371  /**
1372   * hdd_fill_ipv6_addr() - fill IPv6 addresses
1373   * @adapter: Adapter context for which ICMP offload is to be configured
1374   * @pmo_icmp_req: pointer to ICMP offload request params
1375   *
1376   * This is the IPv6 utility function to populate addresses.
1377   *
1378   * Return: 0 on success, error number otherwise.
1379   */
hdd_fill_ipv6_addr(struct hdd_adapter * adapter,struct pmo_icmp_offload * pmo_icmp_req)1380  static int hdd_fill_ipv6_addr(struct hdd_adapter *adapter,
1381  			      struct pmo_icmp_offload *pmo_icmp_req)
1382  {
1383  	struct inet6_dev *in6_dev;
1384  	struct pmo_ns_req *ns_req;
1385  	int i, errno;
1386  
1387  	in6_dev = __in6_dev_get(adapter->dev);
1388  	if (!in6_dev) {
1389  		hdd_err_rl("IPv6 dev does not exist");
1390  		return -EINVAL;
1391  	}
1392  
1393  	ns_req = qdf_mem_malloc(sizeof(*ns_req));
1394  	if (!ns_req)
1395  		return -ENOMEM;
1396  
1397  	ns_req->count = 0;
1398  	/* Unicast Addresses */
1399  	errno = hdd_fill_ipv6_uc_addr(in6_dev, ns_req->ipv6_addr,
1400  				      ns_req->ipv6_addr_type, ns_req->scope,
1401  				      &ns_req->count);
1402  	if (errno) {
1403  		hdd_debug("Reached Max IPv6 supported address %d",
1404  			  ns_req->count);
1405  		goto free_req;
1406  	}
1407  	/* Anycast Addresses */
1408  	errno = hdd_fill_ipv6_ac_addr(in6_dev, ns_req->ipv6_addr,
1409  				      ns_req->ipv6_addr_type, ns_req->scope,
1410  				      &ns_req->count);
1411  	if (errno) {
1412  		hdd_debug("Reached Max IPv6 supported address %d",
1413  			  ns_req->count);
1414  		goto free_req;
1415  	}
1416  
1417  	pmo_icmp_req->ipv6_count = ns_req->count;
1418  	for (i = 0; i < pmo_icmp_req->ipv6_count; i++) {
1419  		qdf_mem_copy(&pmo_icmp_req->ipv6_addr[i], &ns_req->ipv6_addr[i],
1420  			     QDF_IPV6_ADDR_SIZE);
1421  	}
1422  
1423  free_req:
1424  	qdf_mem_free(ns_req);
1425  	return errno;
1426  }
1427  
hdd_enable_icmp_offload(struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev,enum pmo_offload_trigger trigger)1428  void hdd_enable_icmp_offload(struct hdd_adapter *adapter,
1429  			     struct wlan_objmgr_vdev *vdev,
1430  			     enum pmo_offload_trigger trigger)
1431  {
1432  	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1433  	struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
1434  	struct pmo_icmp_offload *pmo_icmp_req;
1435  	bool is_icmp_enable;
1436  	QDF_STATUS status;
1437  	uint8_t vdev_id;
1438  
1439  	is_icmp_enable = ucfg_pmo_is_icmp_offload_enabled(psoc);
1440  	if (!is_icmp_enable) {
1441  		hdd_debug("ICMP Offload not enabled");
1442  		return;
1443  	}
1444  
1445  	pmo_icmp_req = qdf_mem_malloc(sizeof(*pmo_icmp_req));
1446  	if (!pmo_icmp_req)
1447  		return;
1448  
1449  	vdev_id = wlan_vdev_get_id(vdev);
1450  	status = ucfg_pmo_check_icmp_offload(psoc, vdev_id);
1451  	if (QDF_IS_STATUS_ERROR(status))
1452  		goto free_req;
1453  
1454  	pmo_icmp_req->vdev_id = vdev_id;
1455  	pmo_icmp_req->enable = is_icmp_enable;
1456  	pmo_icmp_req->trigger = trigger;
1457  
1458  	switch (trigger) {
1459  	case pmo_ipv4_change_notify:
1460  		if (hdd_fill_ipv4_addr(adapter, pmo_icmp_req)) {
1461  			hdd_debug("Unable to populate IPv4 Address");
1462  			goto free_req;
1463  		}
1464  		break;
1465  	case pmo_ipv6_change_notify:
1466  		if (hdd_fill_ipv6_addr(adapter, pmo_icmp_req)) {
1467  			hdd_debug("Unable to populate IPv6 Address");
1468  			goto free_req;
1469  		}
1470  		break;
1471  	default:
1472  		QDF_DEBUG_PANIC("The trigger %d is not supported", trigger);
1473  		goto free_req;
1474  	}
1475  
1476  	status = ucfg_pmo_config_icmp_offload(psoc, pmo_icmp_req);
1477  	if (QDF_IS_STATUS_ERROR(status))
1478  		hdd_err_rl("icmp offload config in fw failed: %d", status);
1479  
1480  free_req:
1481  	qdf_mem_free(pmo_icmp_req);
1482  }
1483  #endif
1484  
hdd_disable_arp_offload(struct hdd_adapter * adapter,struct wlan_objmgr_vdev * vdev,enum pmo_offload_trigger trigger)1485  void hdd_disable_arp_offload(struct hdd_adapter *adapter,
1486  			     struct wlan_objmgr_vdev *vdev,
1487  			     enum pmo_offload_trigger trigger)
1488  {
1489  	QDF_STATUS status;
1490  	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1491  
1492  	hdd_enter();
1493  
1494  	status = ucfg_pmo_check_arp_offload(hdd_ctx->psoc, trigger,
1495  					    wlan_vdev_get_id(vdev));
1496  	if (status != QDF_STATUS_SUCCESS) {
1497  		hdd_debug("Flushing of ARP offload not required");
1498  		return;
1499  	}
1500  
1501  	status = ucfg_pmo_flush_arp_offload_req(vdev);
1502  	if (status != QDF_STATUS_SUCCESS) {
1503  		hdd_err("Failed to flush arp Offload");
1504  		return;
1505  	}
1506  
1507  	status = ucfg_pmo_disable_arp_offload_in_fwr(vdev, trigger);
1508  	if (status == QDF_STATUS_SUCCESS)
1509  		hdd_wlan_offload_event(PMO_IPV4_ARP_REPLY_OFFLOAD,
1510  			PMO_OFFLOAD_DISABLE);
1511  	else
1512  		hdd_info("fail to disable arp offload");
1513  }
1514  
hdd_enable_mc_addr_filtering(struct hdd_adapter * adapter,enum pmo_offload_trigger trigger)1515  void hdd_enable_mc_addr_filtering(struct hdd_adapter *adapter,
1516  				  enum pmo_offload_trigger trigger)
1517  {
1518  	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1519  	QDF_STATUS status;
1520  
1521  	if (wlan_hdd_validate_context(hdd_ctx))
1522  		return;
1523  
1524  	if (!hdd_cm_is_vdev_associated(adapter->deflink))
1525  		return;
1526  
1527  	status = ucfg_pmo_enable_mc_addr_filtering_in_fwr(
1528  						hdd_ctx->psoc,
1529  						adapter->deflink->vdev_id,
1530  						trigger);
1531  	if (QDF_IS_STATUS_ERROR(status))
1532  		hdd_debug("failed to enable mc list; status:%d", status);
1533  
1534  }
1535  
hdd_disable_mc_addr_filtering(struct hdd_adapter * adapter,enum pmo_offload_trigger trigger)1536  void hdd_disable_mc_addr_filtering(struct hdd_adapter *adapter,
1537  				   enum pmo_offload_trigger trigger)
1538  {
1539  	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1540  	QDF_STATUS status;
1541  
1542  	if (wlan_hdd_validate_context(hdd_ctx))
1543  		return;
1544  
1545  	status = ucfg_pmo_disable_mc_addr_filtering_in_fwr(
1546  						hdd_ctx->psoc,
1547  						adapter->deflink->vdev_id,
1548  						trigger);
1549  	if (QDF_IS_STATUS_ERROR(status))
1550  		hdd_err("failed to disable mc list; status:%d", status);
1551  }
1552  
hdd_cache_mc_addr_list(struct pmo_mc_addr_list_params * mc_list_config)1553  int hdd_cache_mc_addr_list(struct pmo_mc_addr_list_params *mc_list_config)
1554  {
1555  	QDF_STATUS status;
1556  
1557  	status = ucfg_pmo_cache_mc_addr_list(mc_list_config);
1558  
1559  	return qdf_status_to_os_return(status);
1560  }
1561  
hdd_disable_and_flush_mc_addr_list(struct hdd_adapter * adapter,enum pmo_offload_trigger trigger)1562  void hdd_disable_and_flush_mc_addr_list(struct hdd_adapter *adapter,
1563  					enum pmo_offload_trigger trigger)
1564  {
1565  	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1566  	QDF_STATUS status;
1567  
1568  	/* disable mc list first because the mc list is cached in PMO */
1569  	status = ucfg_pmo_disable_mc_addr_filtering_in_fwr(
1570  						hdd_ctx->psoc,
1571  						adapter->deflink->vdev_id,
1572  						trigger);
1573  	if (QDF_IS_STATUS_ERROR(status))
1574  		hdd_debug("failed to disable mc list; status:%d", status);
1575  
1576  	status = ucfg_pmo_flush_mc_addr_list(hdd_ctx->psoc,
1577  					     adapter->deflink->vdev_id);
1578  	if (QDF_IS_STATUS_ERROR(status))
1579  		hdd_debug("failed to flush mc list; status:%d", status);
1580  }
1581  
1582  /**
1583   * hdd_update_conn_state_mask() - record info needed by wma_suspend_req
1584   * @adapter: adapter to get info from
1585   * @conn_state_mask: mask of connection info
1586   *
1587   * currently only need to send connection info.
1588   */
hdd_update_conn_state_mask(struct hdd_adapter * adapter,uint32_t * conn_state_mask)1589  static void hdd_update_conn_state_mask(struct hdd_adapter *adapter,
1590  				       uint32_t *conn_state_mask)
1591  {
1592  	if (hdd_cm_is_vdev_associated(adapter->deflink))
1593  		*conn_state_mask |= (1 << adapter->deflink->vdev_id);
1594  }
1595  
1596  /**
1597   * hdd_suspend_wlan() - Driver suspend function
1598   *
1599   * Return: 0 on success else error code.
1600   */
1601  static int
hdd_suspend_wlan(void)1602  hdd_suspend_wlan(void)
1603  {
1604  	struct hdd_context *hdd_ctx;
1605  	QDF_STATUS status;
1606  	struct hdd_adapter *adapter = NULL, *next_adapter = NULL;
1607  	uint32_t conn_state_mask = 0;
1608  	struct wlan_hdd_link_info *link_info;
1609  
1610  	hdd_info("WLAN being suspended by OS");
1611  
1612  	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1613  	if (!hdd_ctx)
1614  		return -EINVAL;
1615  
1616  	if (cds_is_driver_recovering() || cds_is_driver_in_bad_state()) {
1617  		hdd_info("Recovery in Progress. State: 0x%x Ignore suspend!!!",
1618  			 cds_get_driver_state());
1619  		return -EINVAL;
1620  	}
1621  
1622  	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
1623  					   NET_DEV_HOLD_SUSPEND_WLAN) {
1624  		hdd_adapter_for_each_active_link_info(adapter, link_info) {
1625  			if (wlan_hdd_validate_vdev_id(link_info->vdev_id))
1626  				continue;
1627  
1628  			if (adapter->device_mode == QDF_STA_MODE)
1629  				status = hdd_enable_default_pkt_filters(
1630  						hdd_ctx, link_info->vdev_id);
1631  
1632  			/* Configure supported OffLoads */
1633  			hdd_enable_host_offloads(adapter, pmo_apps_suspend);
1634  			hdd_update_conn_state_mask(adapter, &conn_state_mask);
1635  		}
1636  		hdd_adapter_dev_put_debug(adapter, NET_DEV_HOLD_SUSPEND_WLAN);
1637  	}
1638  
1639  	status = ucfg_pmo_psoc_user_space_suspend_req(hdd_ctx->psoc,
1640  						      QDF_SYSTEM_SUSPEND);
1641  	if (status != QDF_STATUS_SUCCESS)
1642  		return -EAGAIN;
1643  
1644  	hdd_ctx->hdd_wlan_suspended = true;
1645  
1646  	ucfg_dp_suspend_wlan(hdd_ctx->psoc);
1647  
1648  	hdd_configure_sar_sleep_index(hdd_ctx);
1649  
1650  	hdd_wlan_suspend_resume_event(HDD_WLAN_EARLY_SUSPEND);
1651  
1652  	return 0;
1653  }
1654  
1655  /**
1656   * hdd_resume_wlan() - Driver resume function
1657   *
1658   * Return: 0 on success else error code.
1659   */
hdd_resume_wlan(void)1660  static int hdd_resume_wlan(void)
1661  {
1662  	struct hdd_context *hdd_ctx;
1663  	struct hdd_adapter *adapter, *next_adapter = NULL;
1664  	QDF_STATUS status;
1665  	struct wlan_hdd_link_info *link_info;
1666  
1667  	hdd_info("WLAN being resumed by OS");
1668  
1669  	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1670  	if (!hdd_ctx)
1671  		return -EINVAL;
1672  
1673  	if (cds_is_driver_recovering() || cds_is_driver_in_bad_state()) {
1674  		hdd_info("Recovery in Progress. State: 0x%x Ignore resume!!!",
1675  			 cds_get_driver_state());
1676  		return -EINVAL;
1677  	}
1678  
1679  	hdd_ctx->hdd_wlan_suspended = false;
1680  	hdd_wlan_suspend_resume_event(HDD_WLAN_EARLY_RESUME);
1681  
1682  	/*loop through all adapters. Concurrency */
1683  	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
1684  					   NET_DEV_HOLD_RESUME_WLAN) {
1685  		hdd_adapter_for_each_active_link_info(adapter, link_info) {
1686  			if (wlan_hdd_validate_vdev_id(link_info->vdev_id))
1687  				continue;
1688  
1689  			/* Disable supported OffLoads */
1690  			hdd_disable_host_offloads(adapter, pmo_apps_resume);
1691  
1692  			if (adapter->device_mode == QDF_STA_MODE)
1693  				status = hdd_disable_default_pkt_filters(
1694  						hdd_ctx, link_info->vdev_id);
1695  
1696  			hdd_restart_tsf_sync_post_wlan_resume(adapter);
1697  		}
1698  		hdd_adapter_dev_put_debug(adapter, NET_DEV_HOLD_RESUME_WLAN);
1699  	}
1700  
1701  	ucfg_ipa_resume(hdd_ctx->pdev);
1702  	ucfg_dp_resume_wlan(hdd_ctx->psoc);
1703  	status = ucfg_pmo_psoc_user_space_resume_req(hdd_ctx->psoc,
1704  						     QDF_SYSTEM_SUSPEND);
1705  	if (QDF_IS_STATUS_ERROR(status))
1706  		return qdf_status_to_os_return(status);
1707  
1708  	hdd_configure_sar_resume_index(hdd_ctx);
1709  
1710  	return 0;
1711  }
1712  
1713  /**
1714   * hdd_pause_ns() - Network stack pause function
1715   * @hdd_ctx:   hdd context
1716   *
1717   * Return: 0 on success else error code.
1718   */
hdd_pause_ns(struct hdd_context * hdd_ctx)1719  static int hdd_pause_ns(struct hdd_context *hdd_ctx)
1720  {
1721  	struct hdd_adapter *adapter = NULL, *next_adapter = NULL;
1722  
1723  	hdd_debug("Pause NS");
1724  
1725  	if (cds_is_driver_recovering() || cds_is_driver_in_bad_state()) {
1726  		hdd_info("Recovery in Progress. State: 0x%x Ignore suspend!!!",
1727  			 cds_get_driver_state());
1728  		return -EINVAL;
1729  	}
1730  
1731  	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
1732  					   NET_DEV_HOLD_SUSPEND_WLAN) {
1733  		if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id)) {
1734  			hdd_adapter_dev_put_debug(adapter,
1735  						  NET_DEV_HOLD_SUSPEND_WLAN);
1736  			continue;
1737  		}
1738  
1739  		/* stop all TX queues before suspend */
1740  		hdd_debug("Disabling queues for dev mode %s",
1741  			  qdf_opmode_str(adapter->device_mode));
1742  		wlan_hdd_netif_queue_control(adapter,
1743  					     WLAN_STOP_ALL_NETIF_QUEUE,
1744  					     WLAN_CONTROL_PATH);
1745  
1746  		hdd_adapter_dev_put_debug(adapter, NET_DEV_HOLD_SUSPEND_WLAN);
1747  	}
1748  
1749  	return 0;
1750  }
1751  
1752  /**
1753   * hdd_unpause_ns() - Network stack unpause function
1754   * @hdd_ctx:   hdd context
1755   *
1756   * Return: 0 on success else error code.
1757   */
hdd_unpause_ns(struct hdd_context * hdd_ctx)1758  static int hdd_unpause_ns(struct hdd_context *hdd_ctx)
1759  {
1760  	struct hdd_adapter *adapter, *next_adapter = NULL;
1761  
1762  	hdd_debug("Unpause NS");
1763  
1764  	if (cds_is_driver_recovering() || cds_is_driver_in_bad_state()) {
1765  		hdd_info("Recovery in Progress. State: 0x%x Ignore resume!!!",
1766  			 cds_get_driver_state());
1767  		return -EINVAL;
1768  	}
1769  
1770  	/*loop through all adapters. Concurrency */
1771  	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
1772  					   NET_DEV_HOLD_RESUME_WLAN) {
1773  		if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id)) {
1774  			hdd_adapter_dev_put_debug(adapter,
1775  						  NET_DEV_HOLD_RESUME_WLAN);
1776  			continue;
1777  		}
1778  
1779  		/* wake the tx queues */
1780  		hdd_debug("Enabling queues for dev mode %s",
1781  			  qdf_opmode_str(adapter->device_mode));
1782  		wlan_hdd_netif_queue_control(adapter,
1783  					     WLAN_WAKE_ALL_NETIF_QUEUE,
1784  					     WLAN_CONTROL_PATH);
1785  
1786  		hdd_adapter_dev_put_debug(adapter, NET_DEV_HOLD_RESUME_WLAN);
1787  	}
1788  
1789  	return 0;
1790  }
hdd_svc_fw_shutdown_ind(struct device * dev)1791  void hdd_svc_fw_shutdown_ind(struct device *dev)
1792  {
1793  	struct hdd_context *hdd_ctx;
1794  
1795  	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1796  
1797  	hdd_ctx ? wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
1798  					      WLAN_SVC_FW_SHUTDOWN_IND,
1799  					      NULL, 0) : 0;
1800  }
1801  
1802  /**
1803   * wlan_hdd_set_twt_responder() - wrapper to configure twt responder
1804   * in sap_config
1805   * @hdd_ctx: Pointer to hdd context
1806   * @adapter: Pointer to hostapd hdd adapter
1807   *
1808   * Return: none
1809   */
1810  #if defined(WLAN_SUPPORT_TWT) && \
1811  	((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) || \
1812  	  defined(CFG80211_TWT_RESPONDER_SUPPORT))
wlan_hdd_set_twt_responder(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)1813  static void wlan_hdd_set_twt_responder(struct hdd_context *hdd_ctx,
1814  				       struct hdd_adapter *adapter)
1815  {
1816  	bool twt_responder;
1817  
1818  	twt_responder =
1819  		adapter->deflink->session.ap.sap_config.cfg80211_twt_responder;
1820  	wlan_hdd_configure_twt_responder(hdd_ctx, twt_responder);
1821  }
1822  #else
wlan_hdd_set_twt_responder(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)1823  static inline void wlan_hdd_set_twt_responder(struct hdd_context *hdd_ctx,
1824  					      struct hdd_adapter *adapter)
1825  {
1826  }
1827  #endif
1828  
1829  /**
1830   * hdd_ssr_restart_sap() - restart sap on SSR
1831   * @hdd_ctx:   hdd context
1832   *
1833   * Return:     nothing
1834   */
hdd_ssr_restart_sap(struct hdd_context * hdd_ctx)1835  static void hdd_ssr_restart_sap(struct hdd_context *hdd_ctx)
1836  {
1837  	struct hdd_adapter *adapter, *next_adapter = NULL;
1838  
1839  	hdd_enter();
1840  
1841  	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
1842  					   NET_DEV_HOLD_SSR_RESTART_SAP) {
1843  		if (adapter->device_mode != QDF_SAP_MODE)
1844  			goto next_adapter;
1845  
1846  		if (test_bit(SOFTAP_INIT_DONE, &adapter->deflink->link_flags)) {
1847  			hdd_debug("Restart prev SAP session, event_flags 0x%lx, link_flags 0x%lx(%s)",
1848  				  adapter->event_flags,
1849  				  adapter->deflink->link_flags,
1850  				  adapter->dev->name);
1851  			wlan_hdd_set_twt_responder(hdd_ctx, adapter);
1852  			wlan_hdd_start_sap(adapter->deflink, true);
1853  		}
1854  next_adapter:
1855  		hdd_adapter_dev_put_debug(adapter,
1856  					  NET_DEV_HOLD_SSR_RESTART_SAP);
1857  	}
1858  
1859  	hdd_exit();
1860  }
1861  
hdd_wlan_shutdown(void)1862  QDF_STATUS hdd_wlan_shutdown(void)
1863  {
1864  	struct hdd_context *hdd_ctx;
1865  	struct hdd_adapter *adapter;
1866  	struct wlan_objmgr_vdev *vdev;
1867  	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
1868  
1869  	hdd_info("WLAN driver shutting down!");
1870  
1871  	/* Get the HDD context. */
1872  	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1873  	if (!hdd_ctx)
1874  		return QDF_STATUS_E_FAILURE;
1875  
1876  	if (ucfg_ipa_is_enabled()) {
1877  		ucfg_ipa_uc_force_pipe_shutdown(hdd_ctx->pdev);
1878  
1879  		if (pld_is_fw_rejuvenate(hdd_ctx->parent_dev) ||
1880  		    pld_is_pdr(hdd_ctx->parent_dev))
1881  			ucfg_ipa_fw_rejuvenate_send_msg(hdd_ctx->pdev);
1882  	}
1883  
1884  	hdd_set_connection_in_progress(false);
1885  
1886  	hdd_debug("Invoking packetdump deregistration API");
1887  	wlan_deregister_txrx_packetdump(OL_TXRX_PDEV_ID);
1888  
1889  	/* resume wlan threads before adapter reset which does vdev destroy */
1890  	if (hdd_ctx->is_scheduler_suspended) {
1891  		scheduler_resume();
1892  		hdd_ctx->is_scheduler_suspended = false;
1893  		hdd_ctx->is_wiphy_suspended = false;
1894  		hdd_ctx->hdd_wlan_suspended = false;
1895  		ucfg_pmo_resume_all_components(hdd_ctx->psoc,
1896  					       QDF_SYSTEM_SUSPEND);
1897  	}
1898  
1899  	wlan_hdd_rx_thread_resume(hdd_ctx);
1900  
1901  	if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
1902  						PACKET_CAPTURE_MODE_DISABLE) {
1903  		adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
1904  		if (adapter) {
1905  			vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
1906  							   WLAN_OSIF_POWER_ID);
1907  			if (vdev) {
1908  				ucfg_pkt_capture_resume_mon_thread(vdev);
1909  				hdd_objmgr_put_vdev_by_user(
1910  					vdev, WLAN_OSIF_POWER_ID);
1911  			} else {
1912  				hdd_err("vdev is NULL");
1913  			}
1914  		}
1915  	}
1916  
1917  	hdd_reset_all_adapters(hdd_ctx);
1918  
1919  	ucfg_ipa_uc_ssr_cleanup(hdd_ctx->pdev);
1920  
1921  	/* Flush cached rx frame queue */
1922  	if (soc)
1923  		cdp_flush_cache_rx_queue(soc);
1924  
1925  	/* De-register the HDD callbacks */
1926  	hdd_deregister_cb(hdd_ctx);
1927  
1928  	hdd_wlan_stop_modules(hdd_ctx, false);
1929  
1930  	hdd_lpass_notify_stop(hdd_ctx);
1931  
1932  	qdf_set_smmu_fault_state(false);
1933  	hdd_info("WLAN driver shutdown complete");
1934  
1935  	return QDF_STATUS_SUCCESS;
1936  }
1937  
1938  #ifdef FEATURE_WLAN_DIAG_SUPPORT
1939  /**
1940   * hdd_wlan_ssr_reinit_event() - send ssr reinit state
1941   *
1942   * This Function send send ssr reinit state diag event
1943   *
1944   * Return: void.
1945   */
hdd_wlan_ssr_reinit_event(void)1946  static void hdd_wlan_ssr_reinit_event(void)
1947  {
1948  	WLAN_HOST_DIAG_EVENT_DEF(ssr_reinit, struct host_event_wlan_ssr_reinit);
1949  	qdf_mem_zero(&ssr_reinit, sizeof(ssr_reinit));
1950  	ssr_reinit.status = SSR_SUB_SYSTEM_REINIT;
1951  	WLAN_HOST_DIAG_EVENT_REPORT(&ssr_reinit,
1952  					EVENT_WLAN_SSR_REINIT_SUBSYSTEM);
1953  }
1954  #else
hdd_wlan_ssr_reinit_event(void)1955  static inline void hdd_wlan_ssr_reinit_event(void)
1956  {
1957  
1958  }
1959  #endif
1960  
1961  #ifdef WLAN_FEATURE_DBAM_CONFIG
1962  /**
1963   * hdd_restore_dbam_config() - restore and send dbam config to fw
1964   * @hdd_ctx: HDD context
1965   *
1966   * This function is used to send  store dbam config to fw
1967   * in case of wlan re-init
1968   *
1969   * Return: void
1970   */
hdd_restore_dbam_config(struct hdd_context * hdd_ctx)1971  static void hdd_restore_dbam_config(struct hdd_context *hdd_ctx)
1972  {
1973  	struct hdd_adapter *adapter, *next_adapter = NULL;
1974  	wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_ADAPTER;
1975  
1976  	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
1977  					   dbgid) {
1978  		if (hdd_is_interface_up(adapter) &&
1979  		    adapter->is_dbam_configured)
1980  			hdd_send_dbam_config(adapter, hdd_ctx->dbam_mode);
1981  		hdd_adapter_dev_put_debug(adapter, dbgid);
1982  	}
1983  }
1984  #else
hdd_restore_dbam_config(struct hdd_context * hdd_ctx)1985  static inline void hdd_restore_dbam_config(struct hdd_context *hdd_ctx)
1986  {
1987  }
1988  #endif
1989  
1990  /**
1991   * hdd_restore_dual_sta_config() - Restore dual sta configuration
1992   * @hdd_ctx: pointer to struct hdd_context
1993   *
1994   * Return: None
1995   */
hdd_restore_dual_sta_config(struct hdd_context * hdd_ctx)1996  static void hdd_restore_dual_sta_config(struct hdd_context *hdd_ctx)
1997  {
1998  	QDF_STATUS status;
1999  	struct hdd_dual_sta_policy *sta_policy;
2000  
2001  	sta_policy = &hdd_ctx->dual_sta_policy;
2002  
2003  	hdd_debug("Restore dual sta config: Primary vdev_id:%d, sta policy:%d",
2004  		  sta_policy->primary_vdev_id,
2005  		  sta_policy->dual_sta_policy);
2006  
2007  	status =
2008  		ucfg_mlme_set_primary_interface(hdd_ctx->psoc,
2009  						sta_policy->primary_vdev_id);
2010  	if (QDF_IS_STATUS_ERROR(status))
2011  		hdd_err("could not set primary interface, %d", status);
2012  
2013  	status =
2014  		ucfg_mlme_set_dual_sta_policy(hdd_ctx->psoc,
2015  					      sta_policy->dual_sta_policy);
2016  	if (QDF_IS_STATUS_ERROR(status))
2017  		hdd_err("failed to set mlme dual sta config");
2018  }
2019  
2020  /**
2021   * hdd_send_default_scan_ies() - send default scan ies to fw
2022   * @hdd_ctx: HDD context
2023   *
2024   * This function is used to send default scan ies to fw
2025   * in case of wlan re-init
2026   *
2027   * Return: void
2028   */
hdd_send_default_scan_ies(struct hdd_context * hdd_ctx)2029  static void hdd_send_default_scan_ies(struct hdd_context *hdd_ctx)
2030  {
2031  	struct hdd_adapter *adapter, *next_adapter = NULL;
2032  
2033  	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
2034  					   NET_DEV_HOLD_SEND_DEFAULT_SCAN_IES) {
2035  		if (hdd_is_interface_up(adapter) &&
2036  		    (adapter->device_mode == QDF_STA_MODE ||
2037  		    adapter->device_mode == QDF_P2P_DEVICE_MODE) &&
2038  		    adapter->scan_info.default_scan_ies) {
2039  			sme_set_default_scan_ie(hdd_ctx->mac_handle,
2040  				      adapter->deflink->vdev_id,
2041  				      adapter->scan_info.default_scan_ies,
2042  				      adapter->scan_info.default_scan_ies_len);
2043  		}
2044  		hdd_adapter_dev_put_debug(adapter,
2045  					  NET_DEV_HOLD_SEND_DEFAULT_SCAN_IES);
2046  	}
2047  }
2048  
2049  /**
2050   * hdd_restore_sar_config() - Restore the saved SAR config after SSR
2051   * @hdd_ctx: HDD context
2052   *
2053   * Restore the SAR config that was lost during SSR.
2054   *
2055   * Return: None
2056   */
hdd_restore_sar_config(struct hdd_context * hdd_ctx)2057  static void hdd_restore_sar_config(struct hdd_context *hdd_ctx)
2058  {
2059  	QDF_STATUS status;
2060  
2061  	if (!hdd_ctx->sar_cmd_params)
2062  		return;
2063  
2064  	status = sme_set_sar_power_limits(hdd_ctx->mac_handle,
2065  					  hdd_ctx->sar_cmd_params);
2066  	if (QDF_IS_STATUS_ERROR(status))
2067  		hdd_err("Unable to configured SAR after SSR");
2068  }
2069  
hdd_handle_cached_commands(void)2070  void hdd_handle_cached_commands(void)
2071  {
2072  	struct net_device *net_dev;
2073  	struct hdd_adapter *adapter = NULL;
2074  	struct hdd_context *hdd_ctx;
2075  	struct osif_vdev_sync *vdev_sync_arr = osif_get_vdev_sync_arr();
2076  	struct osif_vdev_sync *vdev_sync;
2077  	int i;
2078  	uint8_t cmd_id;
2079  
2080  	/* Get the HDD context */
2081  	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
2082  	if (!hdd_ctx)
2083  		return;
2084  
2085  	for (i = 0; i < WLAN_MAX_VDEVS; i++) {
2086  		vdev_sync = vdev_sync_arr + i;
2087  		if (!vdev_sync || !vdev_sync->in_use)
2088  			continue;
2089  
2090  		cmd_id = osif_vdev_get_cached_cmd(vdev_sync);
2091  		net_dev = vdev_sync->net_dev;
2092  		if (net_dev) {
2093  			adapter = WLAN_HDD_GET_PRIV_PTR(
2094  					(struct net_device *)net_dev);
2095  			if (!adapter)
2096  				continue;
2097  		} else {
2098  			continue;
2099  		}
2100  
2101  		switch (cmd_id) {
2102  		case NO_COMMAND:
2103  			break;
2104  		case INTERFACE_DOWN:
2105  			hdd_debug("Handling cached interface down command for %s",
2106  				  adapter->dev->name);
2107  
2108  			if (adapter->device_mode == QDF_SAP_MODE ||
2109  			    adapter->device_mode == QDF_P2P_GO_MODE)
2110  				hdd_hostapd_stop_no_trans(net_dev);
2111  			else
2112  				hdd_stop_no_trans(net_dev);
2113  
2114  			osif_vdev_cache_command(vdev_sync, NO_COMMAND);
2115  			break;
2116  		default:
2117  			break;
2118  		}
2119  	}
2120  }
2121  
hdd_wlan_re_init(void)2122  QDF_STATUS hdd_wlan_re_init(void)
2123  {
2124  	struct hdd_context *hdd_ctx = NULL;
2125  	struct hdd_adapter *adapter;
2126  	int ret;
2127  	bool bug_on_reinit_failure = CFG_BUG_ON_REINIT_FAILURE_DEFAULT;
2128  	bool value;
2129  
2130  	hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT);
2131  
2132  	/* Get the HDD context */
2133  	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
2134  	if (!hdd_ctx)
2135  		goto err_ctx_null;
2136  
2137  	bug_on_reinit_failure = hdd_ctx->config->bug_on_reinit_failure;
2138  
2139  	adapter = hdd_get_first_valid_adapter(hdd_ctx);
2140  	if (!adapter)
2141  		hdd_err("Failed to get adapter");
2142  
2143  	ret = hdd_wlan_start_modules(hdd_ctx, true);
2144  	if (ret) {
2145  		hdd_err("Failed to start wlan after error");
2146  		goto err_re_init;
2147  	}
2148  
2149  	hdd_update_hw_sw_info(hdd_ctx);
2150  
2151  	wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
2152  				WLAN_SVC_FW_CRASHED_IND, NULL, 0);
2153  
2154  	/* Restart all adapters */
2155  	hdd_start_all_adapters(hdd_ctx, false);
2156  
2157  	hdd_init_scan_reject_params(hdd_ctx);
2158  	hdd_ctx->bt_coex_mode_set = false;
2159  
2160  	/* Allow the phone to go to sleep */
2161  	hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT);
2162  	/* set chip power save failure detected callback */
2163  	sme_set_chip_pwr_save_fail_cb(hdd_ctx->mac_handle,
2164  				      hdd_chip_pwr_save_fail_detected_cb);
2165  
2166  	hdd_restore_thermal_mitigation_config(hdd_ctx);
2167  	hdd_restore_sar_config(hdd_ctx);
2168  
2169  	hdd_send_default_scan_ies(hdd_ctx);
2170  	hdd_restore_dual_sta_config(hdd_ctx);
2171  	hdd_restore_dbam_config(hdd_ctx);
2172  	hdd_info("WLAN host driver reinitiation completed!");
2173  
2174  	ucfg_mlme_get_sap_internal_restart(hdd_ctx->psoc, &value);
2175  	if (value)
2176  		hdd_ssr_restart_sap(hdd_ctx);
2177  	hdd_wlan_ssr_reinit_event();
2178  
2179  	if (hdd_ctx->is_wiphy_suspended)
2180  		hdd_ctx->is_wiphy_suspended = false;
2181  
2182  	if (hdd_ctx->hdd_wlan_suspended)
2183  		hdd_ctx->hdd_wlan_suspended = false;
2184  
2185  	return QDF_STATUS_SUCCESS;
2186  
2187  err_re_init:
2188  	qdf_dp_trace_deinit();
2189  
2190  err_ctx_null:
2191  	/* Allow the phone to go to sleep */
2192  	hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT);
2193  	if (bug_on_reinit_failure)
2194  		QDF_BUG(0);
2195  	return -EPERM;
2196  }
2197  
wlan_hdd_set_powersave(struct wlan_hdd_link_info * link_info,bool allow_power_save,uint32_t timeout)2198  int wlan_hdd_set_powersave(struct wlan_hdd_link_info *link_info,
2199  			   bool allow_power_save, uint32_t timeout)
2200  {
2201  	struct hdd_adapter *adapter = link_info->adapter;
2202  	struct hdd_context *hdd_ctx;
2203  	QDF_STATUS status;
2204  	struct hdd_station_ctx *sta_ctx;
2205  
2206  	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2207  	if (!hdd_ctx) {
2208  		hdd_err("hdd context is NULL");
2209  		return -EINVAL;
2210  	}
2211  
2212  	if (wlan_hdd_validate_vdev_id(link_info->vdev_id))
2213  		return -EINVAL;
2214  
2215  	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
2216  
2217  	status = sme_ps_set_powersave(
2218  				hdd_ctx->mac_handle, link_info->vdev_id,
2219  				allow_power_save, timeout,
2220  				sta_ctx->ap_supports_immediate_power_save);
2221  	if (!allow_power_save && adapter->device_mode == QDF_STA_MODE)
2222  		hdd_twt_del_dialog_in_ps_disable(hdd_ctx,
2223  						 &sta_ctx->conn_info.bssid,
2224  						 link_info->vdev_id);
2225  
2226  	return qdf_status_to_os_return(status);
2227  }
2228  
wlan_hdd_print_suspend_fail_stats(struct hdd_context * hdd_ctx)2229  static void wlan_hdd_print_suspend_fail_stats(struct hdd_context *hdd_ctx)
2230  {
2231  	struct suspend_resume_stats *stats = &hdd_ctx->suspend_resume_stats;
2232  
2233  	hdd_err("ipa:%d, radar:%d, roam:%d, scan:%d, initial_wakeup:%d",
2234  		stats->suspend_fail[SUSPEND_FAIL_IPA],
2235  		stats->suspend_fail[SUSPEND_FAIL_RADAR],
2236  		stats->suspend_fail[SUSPEND_FAIL_ROAM],
2237  		stats->suspend_fail[SUSPEND_FAIL_SCAN],
2238  		stats->suspend_fail[SUSPEND_FAIL_INITIAL_WAKEUP]);
2239  }
2240  
wlan_hdd_inc_suspend_stats(struct hdd_context * hdd_ctx,enum suspend_fail_reason reason)2241  void wlan_hdd_inc_suspend_stats(struct hdd_context *hdd_ctx,
2242  				enum suspend_fail_reason reason)
2243  {
2244  	wlan_hdd_print_suspend_fail_stats(hdd_ctx);
2245  	hdd_ctx->suspend_resume_stats.suspend_fail[reason]++;
2246  	wlan_hdd_print_suspend_fail_stats(hdd_ctx);
2247  }
2248  
2249  #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
2250  static inline void
hdd_sched_scan_results(struct wiphy * wiphy,uint64_t reqid)2251  hdd_sched_scan_results(struct wiphy *wiphy, uint64_t reqid)
2252  {
2253  	cfg80211_sched_scan_results(wiphy);
2254  }
2255  #else
2256  static inline void
hdd_sched_scan_results(struct wiphy * wiphy,uint64_t reqid)2257  hdd_sched_scan_results(struct wiphy *wiphy, uint64_t reqid)
2258  {
2259  	cfg80211_sched_scan_results(wiphy, reqid);
2260  }
2261  #endif
2262  
2263  /**
2264   * __wlan_hdd_cfg80211_resume_wlan() - cfg80211 resume callback
2265   * @wiphy: Pointer to wiphy
2266   *
2267   * This API is called when cfg80211 driver resumes driver updates
2268   * latest sched_scan scan result(if any) to cfg80211 database
2269   *
2270   * Return: integer status
2271   */
__wlan_hdd_cfg80211_resume_wlan(struct wiphy * wiphy)2272  static int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
2273  {
2274  	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
2275  	QDF_STATUS status = QDF_STATUS_SUCCESS;
2276  	struct hdd_adapter *adapter;
2277  	struct wlan_objmgr_vdev *vdev;
2278  	int exit_code;
2279  
2280  	hdd_enter();
2281  
2282  	if (cds_is_driver_recovering()) {
2283  		hdd_debug("Driver is recovering; Skipping resume");
2284  		exit_code = 0;
2285  		goto exit_with_code;
2286  	}
2287  
2288  	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam() ||
2289  	    QDF_GLOBAL_MONITOR_MODE == hdd_get_conparam()) {
2290  		hdd_err("Command not allowed in mode %d",
2291  			hdd_get_conparam());
2292  		exit_code = -EINVAL;
2293  		goto exit_with_code;
2294  	}
2295  
2296  	if (ucfg_pmo_get_suspend_mode(hdd_ctx->psoc) == PMO_SUSPEND_NONE) {
2297  		hdd_info_rl("Suspend is not supported");
2298  		return -EINVAL;
2299  	}
2300  
2301  	if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
2302  		hdd_debug("Driver is not enabled; Skipping resume");
2303  		exit_code = 0;
2304  		goto exit_with_code;
2305  	}
2306  
2307  	status = hdd_resume_wlan();
2308  	if (status != QDF_STATUS_SUCCESS) {
2309  		exit_code = 0;
2310  		goto exit_with_code;
2311  	}
2312  	/* Resume control path scheduler */
2313  	if (hdd_ctx->is_scheduler_suspended) {
2314  		scheduler_resume();
2315  		hdd_ctx->is_scheduler_suspended = false;
2316  	}
2317  	/* Resume all components registered to pmo */
2318  	status = ucfg_pmo_resume_all_components(hdd_ctx->psoc,
2319  						QDF_SYSTEM_SUSPEND);
2320  
2321  	/* Unpause NS no matter of the return value of pmo_resume */
2322  	hdd_unpause_ns(hdd_ctx);
2323  
2324  	if (status != QDF_STATUS_SUCCESS) {
2325  		exit_code = 0;
2326  		goto exit_with_code;
2327  	}
2328  	/* Resume tlshim Rx thread */
2329  	if (ucfg_dp_is_rx_common_thread_enabled(hdd_ctx->psoc))
2330  		wlan_hdd_rx_thread_resume(hdd_ctx);
2331  
2332  	if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
2333  						PACKET_CAPTURE_MODE_DISABLE) {
2334  		adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
2335  		if (adapter) {
2336  			vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
2337  							   WLAN_OSIF_POWER_ID);
2338  			if (vdev) {
2339  				ucfg_pkt_capture_resume_mon_thread(vdev);
2340  				hdd_objmgr_put_vdev_by_user(
2341  					vdev, WLAN_OSIF_POWER_ID);
2342  			} else {
2343  				hdd_err("vdev is NULL");
2344  			}
2345  		}
2346  	}
2347  
2348  	ucfg_pmo_notify_system_resume(hdd_ctx->psoc);
2349  	wlan_hdd_resume_pmo_twt(hdd_ctx);
2350  
2351  	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
2352  		   TRACE_CODE_HDD_CFG80211_RESUME_WLAN,
2353  		   NO_SESSION, hdd_ctx->is_wiphy_suspended);
2354  
2355  	hdd_ctx->is_wiphy_suspended = false;
2356  
2357  	hdd_ctx->suspend_resume_stats.resumes++;
2358  	exit_code = 0;
2359  
2360  exit_with_code:
2361  	hdd_exit();
2362  	return exit_code;
2363  }
2364  
_wlan_hdd_cfg80211_resume_wlan(struct wiphy * wiphy)2365  static int _wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
2366  {
2367  	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
2368  	qdf_runtime_lock_t *suspend_lock;
2369  	int errno;
2370  
2371  	if (!hdd_ctx) {
2372  		hdd_err_rl("hdd context is null");
2373  		return -ENODEV;
2374  	}
2375  
2376  	/* If Wifi is off, return success for system resume */
2377  	if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
2378  		hdd_debug("Driver Modules not Enabled ");
2379  		return 0;
2380  	}
2381  
2382  	/*
2383  	 * Return success if recovery is in progress, otherwise, linux kernel
2384  	 * will shutdown all interfaces in wiphy_resume.
2385  	 */
2386  	if (cds_is_driver_recovering()) {
2387  		hdd_debug("Recovery in progress");
2388  		return 0;
2389  	}
2390  
2391  	errno = wlan_hdd_validate_context(hdd_ctx);
2392  	if (errno)
2393  		return errno;
2394  
2395  	suspend_lock = &hdd_ctx->runtime_context.system_suspend;
2396  	errno = qdf_runtime_pm_allow_suspend(suspend_lock);
2397  	if (errno)
2398  		return errno;
2399  
2400  	errno = __wlan_hdd_cfg80211_resume_wlan(wiphy);
2401  
2402  	/* It may happen during cfg80211 suspend this timer is stopped.
2403  	 * This means that if
2404  	 * 1) work was queued in the workqueue, it was removed from the
2405  	 *    workqueue and suspend proceeded.
2406  	 * 2) The work was scheduled and cfg80211 suspend waited for this
2407  	 *    work to complete and then suspend proceeded.
2408  	 * So here in cfg80211 resume, check if no interface is up and
2409  	 * the module state is enabled then trigger idle timer start.
2410  	 */
2411  	if (!hdd_is_any_interface_open(hdd_ctx) &&
2412  	    hdd_ctx->driver_status == DRIVER_MODULES_ENABLED)
2413  		hdd_psoc_idle_timer_start(hdd_ctx);
2414  
2415  	return errno;
2416  }
2417  
wlan_hdd_cfg80211_resume_wlan(struct wiphy * wiphy)2418  int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
2419  {
2420  	struct osif_psoc_sync *psoc_sync;
2421  	int errno;
2422  
2423  	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
2424  	if (errno)
2425  		return errno;
2426  
2427  	errno = _wlan_hdd_cfg80211_resume_wlan(wiphy);
2428  
2429  	osif_psoc_sync_op_stop(psoc_sync);
2430  
2431  	return errno;
2432  }
2433  
hdd_suspend_cb(void)2434  static void hdd_suspend_cb(void)
2435  {
2436  	struct hdd_context *hdd_ctx;
2437  
2438  	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
2439  	if (!hdd_ctx)
2440  		return;
2441  
2442  	complete(&hdd_ctx->mc_sus_event_var);
2443  }
2444  
2445  /**
2446   * __wlan_hdd_cfg80211_suspend_wlan() - cfg80211 suspend callback
2447   * @wiphy: Pointer to wiphy
2448   * @wow: Pointer to wow
2449   *
2450   * This API is called when cfg80211 driver suspends
2451   *
2452   * Return: integer status
2453   */
__wlan_hdd_cfg80211_suspend_wlan(struct wiphy * wiphy,struct cfg80211_wowlan * wow)2454  static int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
2455  				     struct cfg80211_wowlan *wow)
2456  {
2457  	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
2458  	struct hdd_adapter *adapter, *next_adapter = NULL;
2459  	mac_handle_t mac_handle;
2460  	struct wlan_objmgr_vdev *vdev;
2461  	enum pmo_suspend_mode mode;
2462  	int rc;
2463  	wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_CFG80211_SUSPEND_WLAN;
2464  	struct hdd_ap_ctx *ap_ctx;
2465  	struct hdd_hostapd_state *hapd_state;
2466  	struct csr_del_sta_params params = {
2467  		.peerMacAddr = QDF_MAC_ADDR_BCAST_INIT,
2468  		.reason_code = REASON_DEAUTH_NETWORK_LEAVING,
2469  		.subtype = SIR_MAC_MGMT_DEAUTH,
2470  	};
2471  	struct wlan_hdd_link_info *link_info;
2472  
2473  	hdd_enter();
2474  
2475  	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam() ||
2476  	    QDF_GLOBAL_MONITOR_MODE == hdd_get_conparam()) {
2477  		hdd_err_rl("Command not allowed in mode %d",
2478  			   hdd_get_conparam());
2479  		return -EINVAL;
2480  	}
2481  
2482  	rc = wlan_hdd_validate_context(hdd_ctx);
2483  	if (0 != rc) {
2484  		if (pld_is_low_power_mode(hdd_ctx->parent_dev))
2485  			hdd_debug("low power mode (Deep Sleep/Hibernate)");
2486  		else
2487  			return rc;
2488  	}
2489  
2490  	if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
2491  		hdd_debug("Driver Modules not Enabled ");
2492  		return 0;
2493  	}
2494  
2495  	mode = ucfg_pmo_get_suspend_mode(hdd_ctx->psoc);
2496  	if (mode == PMO_SUSPEND_NONE) {
2497  		hdd_info_rl("Suspend is not supported");
2498  		return -EINVAL;
2499  	} else if (mode == PMO_SUSPEND_SHUTDOWN) {
2500  		hdd_info_rl("shutdown suspend should complete in prepare");
2501  		return -EINVAL;
2502  	}
2503  
2504  	mac_handle = hdd_ctx->mac_handle;
2505  
2506  	/* If RADAR detection is in progress (HDD), prevent suspend. The flag
2507  	 * "dfs_cac_block_tx" is set to true when RADAR is found and stay true
2508  	 * until CAC is done for a SoftAP which is in started state.
2509  	 */
2510  	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
2511  					   dbgid) {
2512  		hdd_adapter_for_each_active_link_info(adapter, link_info) {
2513  			if (wlan_hdd_validate_vdev_id(link_info->vdev_id))
2514  				continue;
2515  
2516  			if (QDF_SAP_MODE == adapter->device_mode) {
2517  				hapd_state =
2518  					WLAN_HDD_GET_HOSTAP_STATE_PTR(link_info);
2519  				ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
2520  				if (BSS_START == hapd_state->bss_state &&
2521  				    true == ap_ctx->dfs_cac_block_tx) {
2522  					hdd_err("RADAR detection in progress, do not allow suspend");
2523  					wlan_hdd_inc_suspend_stats(hdd_ctx,
2524  							   SUSPEND_FAIL_RADAR);
2525  					hdd_adapter_dev_put_debug(adapter,
2526  								  dbgid);
2527  					if (next_adapter)
2528  						hdd_adapter_dev_put_debug(
2529  								next_adapter,
2530  								dbgid);
2531  					return -EAGAIN;
2532  				} else if (!ucfg_pmo_get_enable_sap_suspend(
2533  					   hdd_ctx->psoc)) {
2534  					/* return -EOPNOTSUPP if SAP
2535  					 * does not support suspend
2536  					 */
2537  					hdd_err("SAP does not support suspend!!");
2538  					hdd_adapter_dev_put_debug(adapter,
2539  								  dbgid);
2540  					if (next_adapter)
2541  						hdd_adapter_dev_put_debug(
2542  								next_adapter,
2543  								dbgid);
2544  					return -EOPNOTSUPP;
2545  				} else if (ucfg_pmo_get_disconnect_sap_tdls_in_wow(
2546  					   hdd_ctx->psoc)) {
2547  					hdd_softap_deauth_all_sta(adapter,
2548  								  hapd_state,
2549  								  &params);
2550  				}
2551  			} else if (QDF_P2P_GO_MODE == adapter->device_mode) {
2552  				hapd_state =
2553  					WLAN_HDD_GET_HOSTAP_STATE_PTR(link_info);
2554  				if (!ucfg_pmo_get_enable_sap_suspend(
2555  					   hdd_ctx->psoc)) {
2556  					/* return -EOPNOTSUPP if GO
2557  					 * does not support suspend
2558  					 */
2559  					hdd_err("GO does not support suspend!!");
2560  					hdd_adapter_dev_put_debug(adapter,
2561  								  dbgid);
2562  					if (next_adapter)
2563  						hdd_adapter_dev_put_debug(
2564  								next_adapter,
2565  								dbgid);
2566  					return -EOPNOTSUPP;
2567  				} else if (ucfg_pmo_get_disconnect_sap_tdls_in_wow(
2568  					   hdd_ctx->psoc)) {
2569  					hdd_softap_deauth_all_sta(adapter,
2570  								  hapd_state,
2571  								  &params);
2572  				}
2573  			} else if (QDF_TDLS_MODE == adapter->device_mode &&
2574  				   ucfg_pmo_get_disconnect_sap_tdls_in_wow(
2575  								hdd_ctx->psoc)) {
2576  				vdev = hdd_objmgr_get_vdev_by_user(link_info,
2577  								   WLAN_TDLS_NB_ID);
2578  				if (vdev) {
2579  					ucfg_tdls_teardown_links_sync(hdd_ctx->psoc,
2580  								      vdev);
2581  					hdd_objmgr_put_vdev_by_user(vdev,
2582  								    WLAN_TDLS_NB_ID);
2583  				}
2584  			}
2585  		}
2586  		hdd_adapter_dev_put_debug(adapter, dbgid);
2587  	}
2588  	/* p2p cleanup task based on scheduler */
2589  	ucfg_p2p_cleanup_tx_by_psoc(hdd_ctx->psoc);
2590  	ucfg_p2p_cleanup_roc_by_psoc(hdd_ctx->psoc);
2591  
2592  	if (hdd_is_connection_in_progress(NULL, NULL)) {
2593  		hdd_err_rl("Connection is in progress, rejecting suspend");
2594  		return -EINVAL;
2595  	}
2596  
2597  	/* flush any pending powersave timers */
2598  	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
2599  					   dbgid) {
2600  		hdd_adapter_for_each_active_link_info(adapter, link_info) {
2601  			if (wlan_hdd_validate_vdev_id(link_info->vdev_id))
2602  				continue;
2603  
2604  			sme_ps_timer_flush_sync(mac_handle, link_info->vdev_id);
2605  		}
2606  		hdd_adapter_dev_put_debug(adapter, dbgid);
2607  	}
2608  
2609  	hdd_pause_ns(hdd_ctx);
2610  
2611  	/*
2612  	 * Suspend all components registered to pmo, abort ongoing scan and
2613  	 * don't allow new scan any more before scheduler thread suspended.
2614  	 */
2615  	if (ucfg_pmo_suspend_all_components(hdd_ctx->psoc,
2616  					    QDF_SYSTEM_SUSPEND)) {
2617  		hdd_err("Some components not ready to suspend!");
2618  		return -EAGAIN;
2619  	}
2620  
2621  	wlan_hdd_suspend_pmo_twt(hdd_ctx);
2622  
2623  	/*
2624  	 * Suspend IPA early before proceeding to suspend other entities like
2625  	 * firmware to avoid any race conditions.
2626  	 */
2627  	if (ucfg_ipa_suspend(hdd_ctx->pdev)) {
2628  		hdd_err("IPA not ready to suspend!");
2629  		wlan_hdd_inc_suspend_stats(hdd_ctx, SUSPEND_FAIL_IPA);
2630  		goto resume_all_components;
2631  	}
2632  
2633  	/* Suspend control path scheduler */
2634  	scheduler_register_hdd_suspend_callback(hdd_suspend_cb);
2635  	scheduler_set_event_mask(MC_SUSPEND_EVENT);
2636  	scheduler_wake_up_controller_thread();
2637  
2638  	/* Wait for suspend confirmation from scheduler */
2639  	rc = wait_for_completion_timeout(&hdd_ctx->mc_sus_event_var,
2640  		msecs_to_jiffies(WLAN_WAIT_TIME_MCTHREAD_SUSPEND));
2641  	if (!rc) {
2642  		scheduler_clear_event_mask(MC_SUSPEND_EVENT);
2643  		hdd_err("Failed to stop mc thread");
2644  		goto resume_tx;
2645  	}
2646  	hdd_ctx->is_scheduler_suspended = true;
2647  
2648  	if (ucfg_dp_is_rx_common_thread_enabled(hdd_ctx->psoc)) {
2649  		if (wlan_hdd_rx_thread_suspend(hdd_ctx))
2650  			goto resume_ol_rx;
2651  	}
2652  
2653  	if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
2654  						PACKET_CAPTURE_MODE_DISABLE) {
2655  		adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
2656  		if (adapter) {
2657  			vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
2658  							   WLAN_OSIF_POWER_ID);
2659  			if (!vdev) {
2660  				hdd_err("vdev is NULL");
2661  				goto resume_dp_thread;
2662  			}
2663  			if (ucfg_pkt_capture_suspend_mon_thread(vdev)) {
2664  				hdd_objmgr_put_vdev_by_user(
2665  					vdev, WLAN_OSIF_POWER_ID);
2666  				goto resume_dp_thread;
2667  			}
2668  			hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
2669  		}
2670  	}
2671  
2672  	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
2673  		   TRACE_CODE_HDD_CFG80211_SUSPEND_WLAN,
2674  		   NO_SESSION, hdd_ctx->is_wiphy_suspended);
2675  
2676  	if (hdd_suspend_wlan() < 0) {
2677  		hdd_err("Failed to suspend WLAN");
2678  		goto resume_dp_thread;
2679  	}
2680  
2681  	hdd_ctx->is_wiphy_suspended = true;
2682  
2683  	hdd_exit();
2684  	return 0;
2685  
2686  resume_dp_thread:
2687  	/* Resume packet capture MON thread */
2688  	if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
2689  						PACKET_CAPTURE_MODE_DISABLE) {
2690  		adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
2691  		if (adapter) {
2692  			vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
2693  							   WLAN_OSIF_POWER_ID);
2694  			if (vdev) {
2695  				ucfg_pkt_capture_resume_mon_thread(vdev);
2696  				hdd_objmgr_put_vdev_by_user(
2697  					vdev, WLAN_OSIF_POWER_ID);
2698  			} else {
2699  				hdd_err("vdev is NULL");
2700  			}
2701  		}
2702  	}
2703  
2704  resume_ol_rx:
2705  	/* Resume tlshim Rx thread */
2706  	wlan_hdd_rx_thread_resume(hdd_ctx);
2707  	scheduler_resume();
2708  	hdd_ctx->is_scheduler_suspended = false;
2709  resume_tx:
2710  	hdd_resume_wlan();
2711  resume_all_components:
2712  	ucfg_pmo_resume_all_components(hdd_ctx->psoc, QDF_SYSTEM_SUSPEND);
2713  	hdd_unpause_ns(hdd_ctx);
2714  
2715  	return -ETIME;
2716  
2717  }
2718  
_wlan_hdd_cfg80211_suspend_wlan(struct wiphy * wiphy,struct cfg80211_wowlan * wow)2719  static int _wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
2720  					   struct cfg80211_wowlan *wow)
2721  {
2722  	void *hif_ctx;
2723  	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
2724  	qdf_runtime_lock_t *suspend_lock;
2725  	int errno;
2726  
2727  	if (!hdd_ctx) {
2728  		hdd_err_rl("hdd context is null");
2729  		return -ENODEV;
2730  	}
2731  
2732  	/* If Wifi is off, return success for system suspend */
2733  	if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
2734  		hdd_debug("Driver Modules not Enabled ");
2735  		return 0;
2736  	}
2737  
2738  	errno = wlan_hdd_validate_context(hdd_ctx);
2739  	if (0 != errno) {
2740  		if (pld_is_low_power_mode(hdd_ctx->parent_dev))
2741  			hdd_debug("low power mode (Deep Sleep/Hibernate)");
2742  		else
2743  			return errno;
2744  	}
2745  
2746  	hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
2747  	if (!hif_ctx)
2748  		return -EINVAL;
2749  
2750  	suspend_lock = &hdd_ctx->runtime_context.system_suspend;
2751  	errno = qdf_runtime_pm_prevent_suspend_sync(suspend_lock);
2752  	if (errno)
2753  		return errno;
2754  
2755  	errno = __wlan_hdd_cfg80211_suspend_wlan(wiphy, wow);
2756  	if (errno) {
2757  		qdf_runtime_pm_allow_suspend(suspend_lock);
2758  		return errno;
2759  	}
2760  
2761  	return errno;
2762  }
2763  
wlan_hdd_cfg80211_suspend_wlan(struct wiphy * wiphy,struct cfg80211_wowlan * wow)2764  int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
2765  				   struct cfg80211_wowlan *wow)
2766  {
2767  	struct osif_psoc_sync *psoc_sync;
2768  	int errno;
2769  	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
2770  
2771  	errno = wlan_hdd_validate_context(hdd_ctx);
2772  	if (0 != errno) {
2773  		if (pld_is_low_power_mode(hdd_ctx->parent_dev))
2774  			hdd_debug("low power mode (Deep Sleep/Hibernate)");
2775  		else
2776  			return errno;
2777  	}
2778  
2779  	/*
2780  	 * Flush the idle shutdown before ops start.This is done here to avoid
2781  	 * the deadlock as idle shutdown waits for the dsc ops
2782  	 * to complete.
2783  	 */
2784  	hdd_psoc_idle_timer_stop(hdd_ctx);
2785  
2786  	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
2787  	if (errno)
2788  		return errno;
2789  
2790  	errno = _wlan_hdd_cfg80211_suspend_wlan(wiphy, wow);
2791  
2792  	osif_psoc_sync_op_stop(psoc_sync);
2793  
2794  	return errno;
2795  }
2796  
2797  /**
2798   * hdd_stop_dhcp_ind() - API to stop DHCP sequence
2799   * @link_info: Link  info pointer in HDD adapter
2800   * @mac: mac address
2801   *
2802   * Release the wakelock held for DHCP process and allow
2803   * the runtime pm to continue
2804   *
2805   * Return: None
2806   */
hdd_stop_dhcp_ind(struct wlan_hdd_link_info * link_info,uint8_t * mac)2807  static void hdd_stop_dhcp_ind(struct wlan_hdd_link_info *link_info,
2808  			      uint8_t *mac)
2809  {
2810  	struct hdd_adapter *adapter = link_info->adapter;
2811  	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2812  
2813  	hdd_debug("DHCP stop indicated through power save");
2814  	sme_dhcp_stop_ind(hdd_ctx->mac_handle, adapter->device_mode,
2815  			  mac, link_info->vdev_id);
2816  	hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DHCP);
2817  	qdf_runtime_pm_allow_suspend(&hdd_ctx->runtime_context.connect);
2818  }
2819  
2820  /**
2821   * hdd_start_dhcp_ind() - API to start DHCP sequence
2822   * @link_info: Link info pointer in HDD adapter
2823   * @mac: mac address
2824   *
2825   * Prevent APPS suspend and the runtime suspend during
2826   * DHCP sequence
2827   *
2828   * Return: None
2829   */
2830  static void
hdd_start_dhcp_ind(struct wlan_hdd_link_info * link_info,uint8_t * mac)2831  hdd_start_dhcp_ind(struct wlan_hdd_link_info *link_info, uint8_t *mac)
2832  {
2833  	struct hdd_adapter *adapter = link_info->adapter;
2834  	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2835  
2836  	hdd_debug("DHCP start indicated through power save");
2837  	qdf_runtime_pm_prevent_suspend(&hdd_ctx->runtime_context.connect);
2838  	hdd_prevent_suspend_timeout(HDD_WAKELOCK_TIMEOUT_CONNECT,
2839  				    WIFI_POWER_EVENT_WAKELOCK_DHCP);
2840  	sme_dhcp_start_ind(hdd_ctx->mac_handle, adapter->device_mode,
2841  			   mac, link_info->vdev_id);
2842  }
2843  
wlan_hdd_set_ps(struct wlan_hdd_link_info * link_info,uint8_t * mac,bool allow_power_save,int timeout)2844  static int wlan_hdd_set_ps(struct wlan_hdd_link_info *link_info,
2845  			   uint8_t *mac, bool allow_power_save, int timeout)
2846  {
2847  	int status;
2848  	struct hdd_adapter *adapter = link_info->adapter;
2849  
2850  	status = wlan_hdd_set_powersave(link_info, allow_power_save, timeout);
2851  
2852  	if (!hdd_cm_is_vdev_associated(link_info)) {
2853  		hdd_debug("vdev[%d] mode %d disconnected ignore dhcp protection",
2854  			  link_info->vdev_id, adapter->device_mode);
2855  		return status;
2856  	}
2857  
2858  	hdd_debug("vdev[%d] mode %d enable dhcp protection",
2859  		  link_info->vdev_id, adapter->device_mode);
2860  	allow_power_save ? hdd_stop_dhcp_ind(link_info, mac) :
2861  			   hdd_start_dhcp_ind(link_info, mac);
2862  
2863  	return status;
2864  }
2865  
2866  #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC)
2867  #ifdef WLAN_HDD_MULTI_VDEV_SINGLE_NDEV
wlan_hdd_set_mlo_ps(struct hdd_adapter * adapter,bool allow_power_save,int timeout,int link_id)2868  int wlan_hdd_set_mlo_ps(struct hdd_adapter *adapter,
2869  			bool allow_power_save, int timeout,
2870  			int link_id)
2871  {
2872  	struct wlan_hdd_link_info *link_info;
2873  	int status = -EINVAL;
2874  
2875  	hdd_adapter_for_each_active_link_info(adapter, link_info) {
2876  		if (link_id >= 0 &&
2877  		    wlan_vdev_get_link_id(link_info->vdev) != link_id)
2878  			continue;
2879  
2880  		status = wlan_hdd_set_ps(link_info,
2881  					 link_info->link_addr.bytes,
2882  					 allow_power_save, timeout);
2883  		if (status)
2884  			break;
2885  	}
2886  
2887  	return status;
2888  }
2889  #else
wlan_hdd_set_mlo_ps(struct hdd_adapter * adapter,bool allow_power_save,int timeout,int link_id)2890  int wlan_hdd_set_mlo_ps(struct hdd_adapter *adapter,
2891  			bool allow_power_save, int timeout,
2892  			int link_id)
2893  {
2894  	struct hdd_adapter *link_adapter;
2895  	struct hdd_mlo_adapter_info *mlo_adapter_info;
2896  	int i, status = -EINVAL;
2897  
2898  	mlo_adapter_info = &adapter->mlo_adapter_info;
2899  	for (i = 0; i < WLAN_MAX_MLD; i++) {
2900  		link_adapter = mlo_adapter_info->link_adapter[i];
2901  		if (!link_adapter)
2902  			continue;
2903  
2904  		if (link_id >= 0 &&
2905  		    wlan_vdev_get_link_id(link_adapter->deflink->vdev) !=
2906  		    link_id)
2907  			continue;
2908  
2909  		status = wlan_hdd_set_ps(link_adapter->deflink,
2910  					 link_adapter->mac_addr.bytes,
2911  					 allow_power_save, timeout);
2912  		if (status)
2913  			break;
2914  	}
2915  
2916  	if (i == WLAN_MAX_MLD && link_id >= 0)
2917  		hdd_err("No link adapter found for link id: %d", link_id);
2918  
2919  	return status;
2920  }
2921  #endif
2922  #endif
2923  
2924  /**
2925   * __wlan_hdd_cfg80211_set_power_mgmt() - set cfg80211 power management config
2926   * @wiphy: Pointer to wiphy
2927   * @dev: Pointer to network device
2928   * @allow_power_save: is wlan allowed to go into power save mode
2929   * @timeout: Timeout value in ms
2930   *
2931   * Return: 0 for success, non-zero for failure
2932   */
__wlan_hdd_cfg80211_set_power_mgmt(struct wiphy * wiphy,struct net_device * dev,bool allow_power_save,int timeout)2933  static int __wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
2934  					      struct net_device *dev,
2935  					      bool allow_power_save,
2936  					      int timeout)
2937  {
2938  	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2939  	struct hdd_context *hdd_ctx;
2940  	int status;
2941  	struct wlan_hdd_link_info *link_info = adapter->deflink;
2942  
2943  	hdd_enter();
2944  
2945  	if (timeout < 0) {
2946  		hdd_debug("User space timeout: %d; Enter full power or power save: %d",
2947  			  timeout, allow_power_save);
2948  		timeout = 0;
2949  	}
2950  
2951  	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2952  		hdd_err("Command not allowed in FTM mode");
2953  		return -EINVAL;
2954  	}
2955  
2956  	if (wlan_hdd_validate_vdev_id(link_info->vdev_id))
2957  		return -EINVAL;
2958  
2959  	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
2960  		   TRACE_CODE_HDD_CFG80211_SET_POWER_MGMT,
2961  		   link_info->vdev_id, timeout);
2962  
2963  	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2964  	status = wlan_hdd_validate_context(hdd_ctx);
2965  
2966  	if (0 != status)
2967  		return status;
2968  
2969  	if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
2970  		hdd_debug("Driver Module not enabled return success");
2971  		return 0;
2972  	}
2973  
2974  	/* Flush any scheduled inet change notifier work
2975  	 * This is to make sure set power save request
2976  	 * sent to FW are serialized to avoid race condition
2977  	 */
2978  	flush_work(&adapter->ipv4_notifier_work);
2979  	hdd_adapter_flush_ipv6_notifier_work(adapter);
2980  
2981  	if (hdd_adapter_is_ml_adapter(adapter)) {
2982  		status = wlan_hdd_set_mlo_ps(adapter, allow_power_save,
2983  					     timeout, -1);
2984  		goto exit;
2985  	}
2986  
2987  	status = wlan_hdd_set_ps(link_info, adapter->mac_addr.bytes,
2988  				 allow_power_save, timeout);
2989  
2990  exit:
2991  	/* Cache the powersave state for success case */
2992  	if (!status)
2993  		adapter->allow_power_save = allow_power_save;
2994  
2995  	hdd_exit();
2996  	return status;
2997  }
2998  
wlan_hdd_cfg80211_set_power_mgmt(struct wiphy * wiphy,struct net_device * dev,bool allow_power_save,int timeout)2999  int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
3000  				     struct net_device *dev,
3001  				     bool allow_power_save,
3002  				     int timeout)
3003  {
3004  	int errno;
3005  	struct osif_vdev_sync *vdev_sync;
3006  
3007  	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
3008  	if (errno)
3009  		return errno;
3010  
3011  	errno = __wlan_hdd_cfg80211_set_power_mgmt(wiphy, dev, allow_power_save,
3012  						   timeout);
3013  
3014  	osif_vdev_sync_op_stop(vdev_sync);
3015  
3016  	return errno;
3017  }
3018  
3019  /**
3020   * __wlan_hdd_cfg80211_set_txpower() - set TX power
3021   * @wiphy: Pointer to wiphy
3022   * @wdev: Pointer to network device
3023   * @type: TX power setting type
3024   * @mbm: TX power in mBm
3025   *
3026   * Return: 0 for success, non-zero for failure
3027   */
__wlan_hdd_cfg80211_set_txpower(struct wiphy * wiphy,struct wireless_dev * wdev,enum nl80211_tx_power_setting type,int mbm)3028  static int __wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
3029  					   struct wireless_dev *wdev,
3030  					   enum nl80211_tx_power_setting type,
3031  					   int mbm)
3032  {
3033  	struct hdd_context *hdd_ctx = (struct hdd_context *) wiphy_priv(wiphy);
3034  	mac_handle_t mac_handle;
3035  	struct hdd_adapter *adapter;
3036  	struct qdf_mac_addr bssid = QDF_MAC_ADDR_BCAST_INIT;
3037  	struct qdf_mac_addr selfmac;
3038  	QDF_STATUS status;
3039  	int errno;
3040  	int dbm;
3041  
3042  	hdd_enter();
3043  
3044  	if (!wdev) {
3045  		hdd_err("wdev is null, set tx power failed");
3046  		return -EIO;
3047  	}
3048  
3049  	adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
3050  
3051  	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3052  		hdd_err("Command not allowed in FTM mode");
3053  		return -EINVAL;
3054  	}
3055  
3056  	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
3057  		   TRACE_CODE_HDD_CFG80211_SET_TXPOWER,
3058  		   NO_SESSION, type);
3059  
3060  	errno = wlan_hdd_validate_context(hdd_ctx);
3061  	if (errno)
3062  		return errno;
3063  
3064  	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
3065  		return -EINVAL;
3066  
3067  	if (adapter->device_mode == QDF_SAP_MODE ||
3068  	    adapter->device_mode == QDF_P2P_GO_MODE) {
3069  		qdf_copy_macaddr(&bssid, &adapter->mac_addr);
3070  	} else {
3071  		struct hdd_station_ctx *sta_ctx =
3072  			WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
3073  
3074  		if (hdd_cm_is_vdev_associated(adapter->deflink))
3075  			qdf_copy_macaddr(&bssid, &sta_ctx->conn_info.bssid);
3076  	}
3077  
3078  	qdf_copy_macaddr(&selfmac, &adapter->mac_addr);
3079  
3080  	mac_handle = hdd_ctx->mac_handle;
3081  
3082  	dbm = MBM_TO_DBM(mbm);
3083  
3084  	/*
3085  	 * the original implementation of this function expected power
3086  	 * values in dBm instead of mBm. If the conversion from mBm to
3087  	 * dBm is zero, then assume dBm was passed.
3088  	 */
3089  	if (!dbm)
3090  		dbm = mbm;
3091  
3092  	status = ucfg_mlme_set_current_tx_power_level(hdd_ctx->psoc, dbm);
3093  	if (QDF_IS_STATUS_ERROR(status)) {
3094  		hdd_err("sme_cfg_set_int failed for tx power %d, %d",
3095  			dbm, status);
3096  		return -EIO;
3097  	}
3098  
3099  	hdd_debug("Set tx power level %d dbm", dbm);
3100  
3101  	switch (type) {
3102  	/* Automatically determine transmit power */
3103  	case NL80211_TX_POWER_AUTOMATIC:
3104  	case NL80211_TX_POWER_LIMITED:
3105  	/* Limit TX power by the mBm parameter */
3106  		status = sme_set_max_tx_power(mac_handle, bssid, selfmac, dbm);
3107  		if (QDF_IS_STATUS_ERROR(status)) {
3108  			hdd_err("Setting maximum tx power failed, %d", status);
3109  			return -EIO;
3110  		}
3111  		break;
3112  
3113  	case NL80211_TX_POWER_FIXED:    /* Fix TX power to the mBm parameter */
3114  		status = sme_set_tx_power(mac_handle, adapter->deflink->vdev_id,
3115  					  bssid, adapter->device_mode, dbm);
3116  		if (QDF_IS_STATUS_ERROR(status)) {
3117  			hdd_err("Setting tx power failed, %d", status);
3118  			return -EIO;
3119  		}
3120  		break;
3121  	default:
3122  		hdd_err("Invalid power setting type %d", type);
3123  		return -EIO;
3124  	}
3125  
3126  	hdd_exit();
3127  	return 0;
3128  }
3129  
wlan_hdd_cfg80211_set_txpower(struct wiphy * wiphy,struct wireless_dev * wdev,enum nl80211_tx_power_setting type,int mbm)3130  int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
3131  				  struct wireless_dev *wdev,
3132  				  enum nl80211_tx_power_setting type,
3133  				  int mbm)
3134  {
3135  	struct osif_psoc_sync *psoc_sync;
3136  	int errno;
3137  
3138  	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
3139  	if (errno)
3140  		return errno;
3141  
3142  	errno = __wlan_hdd_cfg80211_set_txpower(wiphy, wdev, type, mbm);
3143  
3144  	osif_psoc_sync_op_stop(psoc_sync);
3145  
3146  	return errno;
3147  }
3148  
3149  #define WLAN_HDD_TX_POWER_CACHE_EXPIRY_TIME 350
3150  
3151  static QDF_STATUS
wlan_hdd_tx_power_request_needed(struct hdd_adapter * adapter)3152  wlan_hdd_tx_power_request_needed(struct hdd_adapter *adapter)
3153  {
3154  	uint32_t tx_pwr_cached_duration;
3155  
3156  	tx_pwr_cached_duration =
3157  			qdf_system_ticks_to_msecs(qdf_system_ticks()) -
3158  			adapter->tx_power.tx_pwr_cached_timestamp;
3159  
3160  	if (tx_pwr_cached_duration <= WLAN_HDD_TX_POWER_CACHE_EXPIRY_TIME)
3161  		return QDF_STATUS_E_ALREADY;
3162  
3163  	return QDF_STATUS_SUCCESS;
3164  }
3165  
wlan_hdd_get_tx_power(struct hdd_adapter * adapter,int * dbm)3166  static int wlan_hdd_get_tx_power(struct hdd_adapter *adapter, int *dbm)
3167  {
3168  	struct wlan_objmgr_vdev *vdev;
3169  	int ret;
3170  
3171  	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
3172  					   WLAN_OSIF_POWER_ID);
3173  	if (!vdev) {
3174  		hdd_info("vdev is NULL");
3175  		return -EINVAL;
3176  	}
3177  
3178  	ret = wlan_cfg80211_mc_cp_stats_get_tx_power(vdev, dbm);
3179  	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
3180  	hdd_debug("power: %d", *dbm);
3181  	return ret;
3182  }
3183  
3184  #ifdef FEATURE_ANI_LEVEL_REQUEST
hdd_get_ani_level_cb(struct wmi_host_ani_level_event * ani,uint8_t num,void * context)3185  static void hdd_get_ani_level_cb(struct wmi_host_ani_level_event *ani,
3186  				 uint8_t num, void *context)
3187  {
3188  	struct osif_request *request;
3189  	struct ani_priv *priv;
3190  	uint8_t min_recv_freqs = QDF_MIN(num, MAX_NUM_FREQS_FOR_ANI_LEVEL);
3191  
3192  	request = osif_request_get(context);
3193  	if (!request) {
3194  		hdd_err("Obsolete request");
3195  		return;
3196  	}
3197  
3198  	/* propagate response back to requesting thread */
3199  	priv = osif_request_priv(request);
3200  	priv->ani = qdf_mem_malloc(min_recv_freqs *
3201  				   sizeof(struct wmi_host_ani_level_event));
3202  	if (!priv->ani)
3203  		goto complete;
3204  
3205  	priv->num_freq = min_recv_freqs;
3206  	qdf_mem_copy(priv->ani, ani,
3207  		     min_recv_freqs * sizeof(struct wmi_host_ani_level_event));
3208  
3209  complete:
3210  	osif_request_complete(request);
3211  	osif_request_put(request);
3212  }
3213  
3214  /**
3215   * wlan_hdd_get_ani_level_dealloc() - Dealloc mem allocated in priv data
3216   * @priv: the priv data
3217   *
3218   * Return: None
3219   */
wlan_hdd_get_ani_level_dealloc(void * priv)3220  static void wlan_hdd_get_ani_level_dealloc(void *priv)
3221  {
3222  	struct ani_priv *ani = priv;
3223  
3224  	if (ani->ani)
3225  		qdf_mem_free(ani->ani);
3226  }
3227  
wlan_hdd_get_ani_level(struct hdd_adapter * adapter,struct wmi_host_ani_level_event * ani,uint32_t * parsed_freqs,uint8_t num_freqs)3228  QDF_STATUS wlan_hdd_get_ani_level(struct hdd_adapter *adapter,
3229  				  struct wmi_host_ani_level_event *ani,
3230  				  uint32_t *parsed_freqs,
3231  				  uint8_t num_freqs)
3232  {
3233  	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3234  	int ret;
3235  	QDF_STATUS status;
3236  	void *cookie;
3237  	struct osif_request *request;
3238  	struct ani_priv *priv;
3239  	static const struct osif_request_params params = {
3240  		.priv_size = sizeof(*priv),
3241  		.timeout_ms = 1000,
3242  		.dealloc = wlan_hdd_get_ani_level_dealloc,
3243  	};
3244  
3245  	if (!hdd_ctx) {
3246  		hdd_err("Invalid HDD context");
3247  		return QDF_STATUS_E_INVAL;
3248  	}
3249  
3250  	request = osif_request_alloc(&params);
3251  	if (!request) {
3252  		hdd_err("Request allocation failure");
3253  		return QDF_STATUS_E_NOMEM;
3254  	}
3255  	cookie = osif_request_cookie(request);
3256  
3257  	status = sme_get_ani_level(hdd_ctx->mac_handle, parsed_freqs,
3258  				   num_freqs, hdd_get_ani_level_cb, cookie);
3259  
3260  	if (QDF_IS_STATUS_ERROR(status)) {
3261  		hdd_err("Unable to retrieve ani level");
3262  		goto complete;
3263  	} else {
3264  		/* request was sent -- wait for the response */
3265  		ret = osif_request_wait_for_response(request);
3266  		if (ret) {
3267  			hdd_err("SME timed out while retrieving ANI level");
3268  			status = QDF_STATUS_E_TIMEOUT;
3269  			goto complete;
3270  		}
3271  	}
3272  
3273  	priv = osif_request_priv(request);
3274  
3275  	qdf_mem_copy(ani, priv->ani, sizeof(struct wmi_host_ani_level_event) *
3276  		     priv->num_freq);
3277  
3278  complete:
3279  	/*
3280  	 * either we never sent a request, we sent a request and
3281  	 * received a response or we sent a request and timed out.
3282  	 * regardless we are done with the request.
3283  	 */
3284  	osif_request_put(request);
3285  
3286  	hdd_exit();
3287  	return status;
3288  }
3289  #endif
3290  
3291  /**
3292   * __wlan_hdd_cfg80211_get_txpower() - get TX power
3293   * @wiphy: Pointer to wiphy
3294   * @wdev: Pointer to network device
3295   * @dbm: Pointer to TX power in dbm
3296   *
3297   * Return: 0 for success, non-zero for failure
3298   */
__wlan_hdd_cfg80211_get_txpower(struct wiphy * wiphy,struct wireless_dev * wdev,int * dbm)3299  static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
3300  				  struct wireless_dev *wdev,
3301  				  int *dbm)
3302  {
3303  
3304  	struct hdd_context *hdd_ctx = (struct hdd_context *) wiphy_priv(wiphy);
3305  	struct net_device *ndev = wdev->netdev;
3306  	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
3307  	QDF_STATUS status;
3308  	int ret;
3309  	static bool is_rate_limited;
3310  	struct wlan_objmgr_vdev *vdev;
3311  
3312  	hdd_enter_dev(ndev);
3313  
3314  	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3315  		hdd_err("Command not allowed in FTM mode");
3316  		return -EINVAL;
3317  	}
3318  
3319  	*dbm = 0;
3320  
3321  	ret = wlan_hdd_validate_context(hdd_ctx);
3322  	if (ret)
3323  		return ret;
3324  
3325  	/* Validate adapter sessionId */
3326  	ret = wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id);
3327  	if (ret)
3328  		return ret;
3329  	switch (adapter->device_mode) {
3330  	case QDF_STA_MODE:
3331  	case QDF_P2P_CLIENT_MODE:
3332  		if (hdd_cm_is_vdev_roaming(adapter->deflink)) {
3333  			hdd_debug("Roaming is in progress, rej this req");
3334  			return -EINVAL;
3335  		}
3336  		if (!hdd_cm_is_vdev_associated(adapter->deflink)) {
3337  			hdd_debug("Not associated");
3338  			return 0;
3339  		}
3340  		break;
3341  	case QDF_SAP_MODE:
3342  	case QDF_P2P_GO_MODE:
3343  		if (!test_bit(SOFTAP_BSS_STARTED,
3344  			      &adapter->deflink->link_flags)) {
3345  			hdd_debug("SAP is not started yet");
3346  			return 0;
3347  		}
3348  		break;
3349  	default:
3350  		hdd_debug_rl("Current interface is not supported for get tx_power");
3351  		return 0;
3352  	}
3353  
3354  	HDD_IS_RATE_LIMIT_REQ(is_rate_limited,
3355  			      hdd_ctx->config->nb_commands_interval);
3356  	if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED ||
3357  	    is_rate_limited) {
3358  		/* Send cached data to upperlayer*/
3359  		vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
3360  						   WLAN_OSIF_POWER_ID);
3361  		if (!vdev) {
3362  			hdd_err("vdev is NULL");
3363  			return -EINVAL;
3364  		}
3365  		ucfg_mc_cp_stats_get_tx_power(vdev, dbm);
3366  		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
3367  		hdd_debug("Modules not enabled/rate limited, cached tx power = %d",
3368  			  *dbm);
3369  		return 0;
3370  	}
3371  
3372  	status = wlan_hdd_tx_power_request_needed(adapter);
3373  	if (status == QDF_STATUS_E_ALREADY) {
3374  		/* TX_POWER is sent by STATION_STATS by firmware and
3375  		 * is copied into the adapter. So, return cached value.
3376  		 */
3377  		*dbm = adapter->tx_power.tx_pwr;
3378  		hdd_nofl_debug("cached tx_power: %d", *dbm);
3379  		return 0;
3380  	}
3381  
3382  	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
3383  		   TRACE_CODE_HDD_CFG80211_GET_TXPOWER,
3384  		   adapter->deflink->vdev_id, adapter->device_mode);
3385  
3386  	return wlan_hdd_get_tx_power(adapter, dbm);
3387  }
3388  
wlan_hdd_cfg80211_get_txpower(struct wiphy * wiphy,struct wireless_dev * wdev,int * dbm)3389  int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
3390  					 struct wireless_dev *wdev,
3391  					 int *dbm)
3392  {
3393  	struct osif_psoc_sync *psoc_sync;
3394  	int errno;
3395  
3396  	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
3397  	if (errno)
3398  		return errno;
3399  
3400  	errno = __wlan_hdd_cfg80211_get_txpower(wiphy, wdev, dbm);
3401  
3402  	osif_psoc_sync_op_stop(psoc_sync);
3403  
3404  	return errno;
3405  }
3406  
3407  /**
3408   * hdd_convert_opm_mode() - convert opm with equivalent wma opm
3409   * @opm_mode: Optimized power management mode
3410   *
3411   * Return: enum wma_sta_ps_scheme_cfg
3412   */
3413  static enum wma_sta_ps_scheme_cfg
hdd_convert_opm_mode(enum qca_wlan_vendor_opm_mode opm_mode)3414  hdd_convert_opm_mode(enum qca_wlan_vendor_opm_mode opm_mode)
3415  {
3416  	switch (opm_mode) {
3417  	case QCA_WLAN_VENDOR_OPM_MODE_DISABLE:
3418  		return WMA_STA_PS_OPM_CONSERVATIVE;
3419  	case QCA_WLAN_VENDOR_OPM_MODE_ENABLE:
3420  		return WMA_STA_PS_OPM_AGGRESSIVE;
3421  	case QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED:
3422  		return WMA_STA_PS_USER_DEF;
3423  	default:
3424  		hdd_err("Invalid opm_mode: %d", opm_mode);
3425  		return WMA_STA_PS_OPM_CONSERVATIVE;
3426  	}
3427  }
3428  
hdd_set_power_config(struct hdd_context * hddctx,struct hdd_adapter * adapter,enum qca_wlan_vendor_opm_mode * opm_mode)3429  int hdd_set_power_config(struct hdd_context *hddctx,
3430  			 struct hdd_adapter *adapter,
3431  			 enum qca_wlan_vendor_opm_mode *opm_mode)
3432  {
3433  	QDF_STATUS status;
3434  
3435  	if (adapter->device_mode != QDF_STA_MODE &&
3436  	    adapter->device_mode != QDF_P2P_CLIENT_MODE) {
3437  		hdd_info("Advanced power save only allowed in STA/P2P-Client modes:%d",
3438  			 adapter->device_mode);
3439  		return -EINVAL;
3440  	}
3441  
3442  	if (*opm_mode > QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED ||
3443  	    *opm_mode < QCA_WLAN_VENDOR_OPM_MODE_DISABLE) {
3444  		hdd_err("invalid power value: %d", *opm_mode);
3445  		return -EINVAL;
3446  	}
3447  
3448  	if (ucfg_pmo_get_max_ps_poll(hddctx->psoc)) {
3449  		hdd_info("Disable advanced power save since max ps poll is enabled");
3450  		*opm_mode = QCA_WLAN_VENDOR_OPM_MODE_DISABLE;
3451  	}
3452  
3453  	status = wma_set_power_config(adapter->deflink->vdev_id,
3454  				      hdd_convert_opm_mode(*opm_mode));
3455  	if (status != QDF_STATUS_SUCCESS) {
3456  		hdd_err("failed to configure power: %d", status);
3457  		return -EINVAL;
3458  	}
3459  
3460  	return 0;
3461  }
3462  
hdd_set_power_config_params(struct hdd_context * hddctx,struct hdd_adapter * adapter,uint16_t ps_ito,uint16_t spec_wake)3463  int hdd_set_power_config_params(struct hdd_context *hddctx,
3464  				struct hdd_adapter *adapter,
3465  				uint16_t ps_ito, uint16_t spec_wake)
3466  {
3467  	QDF_STATUS status;
3468  
3469  	status = wma_set_power_config_ito(adapter->deflink->vdev_id, ps_ito);
3470  	if (status != QDF_STATUS_SUCCESS) {
3471  		hdd_err("failed to configure power ito: %d", status);
3472  		return -EINVAL;
3473  	}
3474  
3475  	status = wma_set_power_config_spec_wake(adapter->deflink->vdev_id,
3476  						spec_wake);
3477  	if (status != QDF_STATUS_SUCCESS) {
3478  		hdd_err("failed to configure power spec wake: %d", status);
3479  		return -EINVAL;
3480  	}
3481  
3482  	return 0;
3483  }
3484  
3485  #ifdef WLAN_SUSPEND_RESUME_TEST
3486  static struct net_device *g_dev;
3487  static struct wiphy *g_wiphy;
3488  static enum wow_resume_trigger g_resume_trigger;
3489  
3490  #define HDD_FA_SUSPENDED_BIT (0)
3491  static unsigned long fake_apps_state;
3492  
3493  /**
3494   * __hdd_wlan_fake_apps_resume() - The core logic for
3495   *	hdd_wlan_fake_apps_resume() skipping the call to hif_fake_apps_resume(),
3496   *	which is only need for non-irq resume
3497   * @wiphy: the kernel wiphy struct for the device being resumed
3498   * @dev: the kernel net_device struct for the device being resumed
3499   *
3500   * Return: none, calls QDF_BUG() on failure
3501   */
__hdd_wlan_fake_apps_resume(struct wiphy * wiphy,struct net_device * dev)3502  static void __hdd_wlan_fake_apps_resume(struct wiphy *wiphy,
3503  					struct net_device *dev)
3504  {
3505  	struct hif_opaque_softc *hif_ctx;
3506  	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3507  	qdf_device_t qdf_dev;
3508  
3509  	if (wlan_hdd_validate_context(hdd_ctx))
3510  		return;
3511  
3512  	if (!hdd_ctx->config->is_unit_test_framework_enabled) {
3513  		hdd_warn_rl("UT framework is disabled");
3514  		return;
3515  	}
3516  
3517  	hdd_info("Unit-test resume WLAN");
3518  
3519  	qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
3520  	if (!qdf_dev) {
3521  		QDF_BUG(0);
3522  		return;
3523  	}
3524  
3525  	hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
3526  	if (!hif_ctx)
3527  		return;
3528  
3529  	if (!test_and_clear_bit(HDD_FA_SUSPENDED_BIT, &fake_apps_state)) {
3530  		hdd_alert("Not unit-test suspended; Nothing to do");
3531  		return;
3532  	}
3533  
3534  	/* simulate kernel disable irqs */
3535  	QDF_BUG(!hif_apps_wake_irq_disable(hif_ctx));
3536  
3537  	QDF_BUG(!wlan_hdd_bus_resume_noirq());
3538  
3539  	/* simulate kernel enable irqs */
3540  	QDF_BUG(!hif_apps_irqs_enable(hif_ctx));
3541  
3542  	QDF_BUG(!wlan_hdd_bus_resume(QDF_UNIT_TEST_WOW_SUSPEND));
3543  
3544  	QDF_BUG(!wlan_hdd_cfg80211_resume_wlan(wiphy));
3545  
3546  	if (g_resume_trigger == WOW_RESUME_TRIGGER_HTC_WAKEUP)
3547  		hif_vote_link_down(hif_ctx);
3548  
3549  	dev->watchdog_timeo = HDD_TX_TIMEOUT;
3550  
3551  	hdd_alert("Unit-test resume succeeded");
3552  
3553  	hdd_info("allow rtpm wow for wow unit test");
3554  	qdf_runtime_pm_allow_suspend(&hdd_ctx->runtime_context.wow_unit_test);
3555  }
3556  
3557  /**
3558   * hdd_wlan_fake_apps_resume_irq_callback() - Irq callback function for resuming
3559   *	from unit-test initiated suspend from irq wakeup signal
3560   *
3561   * Resume wlan after getting very 1st CE interrupt from target
3562   *
3563   * Return: none
3564   */
hdd_wlan_fake_apps_resume_irq_callback(void)3565  static void hdd_wlan_fake_apps_resume_irq_callback(void)
3566  {
3567  	hdd_info("Trigger unit-test resume WLAN");
3568  
3569  	QDF_BUG(g_wiphy);
3570  	QDF_BUG(g_dev);
3571  	__hdd_wlan_fake_apps_resume(g_wiphy, g_dev);
3572  	g_wiphy = NULL;
3573  	g_dev = NULL;
3574  }
3575  
hdd_wlan_fake_apps_suspend(struct wiphy * wiphy,struct net_device * dev,enum wow_interface_pause pause_setting,enum wow_resume_trigger resume_setting)3576  int hdd_wlan_fake_apps_suspend(struct wiphy *wiphy, struct net_device *dev,
3577  			       enum wow_interface_pause pause_setting,
3578  			       enum wow_resume_trigger resume_setting)
3579  {
3580  	int errno;
3581  	qdf_device_t qdf_dev;
3582  	struct hif_opaque_softc *hif_ctx;
3583  	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3584  	struct wow_enable_params wow_params = {
3585  		.is_unit_test = true,
3586  		.interface_pause = pause_setting,
3587  		.resume_trigger = resume_setting
3588  	};
3589  
3590  	if (wlan_hdd_validate_context(hdd_ctx))
3591  		return -EINVAL;
3592  
3593  	if (!hdd_ctx->config->is_unit_test_framework_enabled) {
3594  		hdd_warn_rl("UT framework is disabled");
3595  		return -EINVAL;
3596  	}
3597  
3598  	hdd_info("Unit-test suspend WLAN");
3599  
3600  	if (pause_setting < WOW_INTERFACE_PAUSE_DEFAULT ||
3601  	    pause_setting >= WOW_INTERFACE_PAUSE_COUNT) {
3602  		hdd_err_rl("Invalid interface pause %d (expected range [0, 2])",
3603  			   pause_setting);
3604  		return -EINVAL;
3605  	}
3606  
3607  	if (resume_setting < WOW_RESUME_TRIGGER_DEFAULT ||
3608  	    resume_setting >= WOW_RESUME_TRIGGER_COUNT) {
3609  		hdd_err_rl("Invalid resume trigger %d (expected range [0, 2])",
3610  			   resume_setting);
3611  		return -EINVAL;
3612  	}
3613  
3614  	qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
3615  	if (!qdf_dev)
3616  		return -EINVAL;
3617  
3618  	hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
3619  	if (!hif_ctx)
3620  		return -EINVAL;
3621  
3622  	if (test_and_set_bit(HDD_FA_SUSPENDED_BIT, &fake_apps_state)) {
3623  		hdd_alert("Already unit-test suspended; Nothing to do");
3624  		return 0;
3625  	}
3626  
3627  	hdd_info("prevent rtpm wow for wow unit test");
3628  	qdf_runtime_pm_prevent_suspend(&hdd_ctx->runtime_context.wow_unit_test);
3629  
3630  	/* pci link is needed to wakeup from HTC wakeup trigger */
3631  	if (resume_setting == WOW_RESUME_TRIGGER_HTC_WAKEUP)
3632  		hif_vote_link_up(hif_ctx);
3633  
3634  	errno = wlan_hdd_cfg80211_suspend_wlan(wiphy, NULL);
3635  	if (errno)
3636  		goto link_down;
3637  
3638  	errno = wlan_hdd_unit_test_bus_suspend(wow_params);
3639  	if (errno)
3640  		goto cfg80211_resume;
3641  
3642  	/* simulate kernel disabling irqs */
3643  	errno = hif_apps_irqs_disable(hif_ctx);
3644  	if (errno)
3645  		goto bus_resume;
3646  
3647  	errno = wlan_hdd_bus_suspend_noirq();
3648  	if (errno)
3649  		goto enable_irqs;
3650  
3651  	/* pass wiphy/dev to callback via global variables */
3652  	g_wiphy = wiphy;
3653  	g_dev = dev;
3654  	g_resume_trigger = resume_setting;
3655  	hif_ut_apps_suspend(hif_ctx, hdd_wlan_fake_apps_resume_irq_callback);
3656  
3657  	/* re-enable wake irq */
3658  	errno = hif_apps_wake_irq_enable(hif_ctx);
3659  	if (errno)
3660  		goto fake_apps_resume;
3661  
3662  	/*
3663  	 * Tell the kernel not to worry if TX queues aren't moving. This is
3664  	 * expected since we are suspending the wifi hardware, but not APPS
3665  	 */
3666  	dev->watchdog_timeo = INT_MAX;
3667  
3668  	hdd_alert("Unit-test suspend succeeded");
3669  
3670  	return 0;
3671  
3672  fake_apps_resume:
3673  	hif_ut_apps_resume(hif_ctx);
3674  
3675  enable_irqs:
3676  	QDF_BUG(!hif_apps_irqs_enable(hif_ctx));
3677  
3678  bus_resume:
3679  	QDF_BUG(!wlan_hdd_bus_resume(QDF_UNIT_TEST_WOW_SUSPEND));
3680  
3681  cfg80211_resume:
3682  	QDF_BUG(!wlan_hdd_cfg80211_resume_wlan(wiphy));
3683  
3684  link_down:
3685  	if (resume_setting == WOW_RESUME_TRIGGER_HTC_WAKEUP)
3686  		hif_vote_link_down(hif_ctx);
3687  
3688  	clear_bit(HDD_FA_SUSPENDED_BIT, &fake_apps_state);
3689  	hdd_err("Unit-test suspend failed: %d", errno);
3690  
3691  	hdd_info("allow rtpm wow for wow unit test");
3692  	qdf_runtime_pm_allow_suspend(&hdd_ctx->runtime_context.wow_unit_test);
3693  
3694  	return errno;
3695  }
3696  
hdd_wlan_fake_apps_resume(struct wiphy * wiphy,struct net_device * dev)3697  int hdd_wlan_fake_apps_resume(struct wiphy *wiphy, struct net_device *dev)
3698  {
3699  	struct hif_opaque_softc *hif_ctx;
3700  	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3701  
3702  	if (wlan_hdd_validate_context(hdd_ctx))
3703  		return -EINVAL;
3704  
3705  	if (!hdd_ctx->config->is_unit_test_framework_enabled) {
3706  		hdd_warn_rl("UT framework is disabled");
3707  		return -EINVAL;
3708  	}
3709  
3710  	hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
3711  	if (!hif_ctx)
3712  		return -EINVAL;
3713  
3714  	hif_ut_apps_resume(hif_ctx);
3715  	__hdd_wlan_fake_apps_resume(wiphy, dev);
3716  
3717  	return 0;
3718  }
3719  #endif
3720