Browse Source

qcacmn: Prevent link down for SAP on non DFS channel

In SAP on non DFS channel, there are double votes for PCIe
link down and later if there is PCIe link up, this counter
sends D3 WoW case instead of D0 WoW case to firmware.

To fix this, In vdev restart case, if SAP is on non DFS
channel and previously it was on DFS channel then vote
for PCIe link down and if SAP is on DFS channel and
previously it was on non DFS channel then vote for PCIe
link up. Also, the PCIe link down should be needed if
vdev stop response is for DFS channel.

Change-Id: I817ffceb482091b8d9c5441d80abb43b7d0f866b
CRs-Fixed: 2849706
Deeksha Gupta 4 năm trước cách đây
mục cha
commit
21ce9cf146

+ 4 - 4
target_if/mlme/psoc/inc/target_if_psoc_wake_lock.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -106,12 +106,12 @@ QDF_STATUS target_if_wake_lock_timeout_release(struct wlan_objmgr_psoc *psoc,
  * target_if_vdev_start_link_handler() - check for SAP mode and DFS freq
 						to handle link up/down
  * @vdev: pointer to vdev
- * @is_dfs : is dfs freq
+ * @is_restart: flag to check if it is vdev restart
  *
  * Return: None
  */
 void target_if_vdev_start_link_handler(struct wlan_objmgr_vdev *vdev,
-				       uint32_t is_dfs);
+				       bool is_restart);
 
 /**
  * target_if_vdev_stop_link_handler() - check for SAP mode to handle link
@@ -146,7 +146,7 @@ static inline QDF_STATUS target_if_wake_lock_timeout_release(
 
 static inline void
 target_if_vdev_start_link_handler(struct wlan_objmgr_vdev *vdev,
-				  uint32_t is_dfs)
+				  bool is_restart)
 {
 }
 

+ 63 - 14
target_if/mlme/psoc/src/target_if_psoc_wake_lock.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -192,27 +192,32 @@ target_if_vote_for_link_up(struct wlan_objmgr_psoc *psoc,
 }
 
 void target_if_vdev_start_link_handler(struct wlan_objmgr_vdev *vdev,
-				       uint32_t is_dfs)
+				       bool is_restart)
 {
 	struct wlan_objmgr_psoc *psoc;
 	struct wlan_objmgr_pdev *pdev;
 	struct psoc_mlme_wakelock *psoc_wakelock;
 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
-	struct wlan_channel *des_channel;
-	uint32_t ch_freq;
-	enum phy_ch_width ch_width;
+	struct wlan_channel *curr_channel, *prev_channel;
+	uint32_t ch_freq, prev_ch_freq;
+	enum phy_ch_width ch_width, prev_ch_width;
+	uint32_t is_dfs, prev_ch_is_dfs;
+	enum channel_state ch_state, prev_ch_state;
 
 	psoc = wlan_vdev_get_psoc(vdev);
 	pdev = wlan_vdev_get_pdev(vdev);
-	des_channel = wlan_vdev_mlme_get_des_chan(vdev);
-	ch_freq = des_channel->ch_freq;
-	ch_width = des_channel->ch_width;
 
 	if (!pdev) {
 		mlme_err("pdev is NULL");
 		return;
 	}
 
+	curr_channel = wlan_vdev_mlme_get_des_chan(vdev);
+	ch_freq = curr_channel->ch_freq;
+	ch_width = curr_channel->ch_width;
+	is_dfs = wlan_reg_is_dfs_for_freq(pdev, ch_freq);
+	ch_state = wlan_reg_get_5g_bonded_channel_state_for_freq(pdev, ch_freq,
+								 ch_width);
 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
 	if (!rx_ops || !rx_ops->psoc_get_wakelock_info) {
 		mlme_err("psoc_id:%d No Rx Ops",
@@ -222,22 +227,63 @@ void target_if_vdev_start_link_handler(struct wlan_objmgr_vdev *vdev,
 
 	psoc_wakelock = rx_ops->psoc_get_wakelock_info(psoc);
 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
-		if (is_dfs ||
-		    (wlan_reg_get_5g_bonded_channel_state_for_freq(pdev,
-			ch_freq, ch_width) == CHANNEL_STATE_DFS))
+		if (is_restart) {
+			prev_channel = wlan_vdev_mlme_get_bss_chan(vdev);
+			prev_ch_freq = prev_channel->ch_freq;
+			prev_ch_width = prev_channel->ch_width;
+			prev_ch_is_dfs = wlan_reg_is_dfs_for_freq(pdev,
+								  prev_ch_freq);
+			prev_ch_state =
+				wlan_reg_get_5g_bonded_channel_state_for_freq(pdev,
+						prev_ch_freq, prev_ch_width);
+			/*
+			 * In restart case, if SAP is on non DFS channel and
+			 * previously it was on DFS channel then vote for link
+			 * down.
+			 */
+			if ((prev_ch_is_dfs ||
+			     prev_ch_state == CHANNEL_STATE_DFS) &&
+			     !(is_dfs || ch_state == CHANNEL_STATE_DFS))
+				target_if_vote_for_link_down(psoc,
+							     psoc_wakelock);
+
+			/*
+			 * If SAP is on DFS channel and previously it was on
+			 * non DFS channel then vote for link up
+			 */
+			if (!(prev_ch_is_dfs ||
+			      prev_ch_state == CHANNEL_STATE_DFS) &&
+			     (is_dfs || ch_state == CHANNEL_STATE_DFS))
+				target_if_vote_for_link_up(psoc, psoc_wakelock);
+		} else if (is_dfs || ch_state == CHANNEL_STATE_DFS)
 			target_if_vote_for_link_up(psoc, psoc_wakelock);
-		else
-			target_if_vote_for_link_down(psoc, psoc_wakelock);
 	}
 }
 
 void target_if_vdev_stop_link_handler(struct wlan_objmgr_vdev *vdev)
 {
 	struct wlan_objmgr_psoc *psoc;
+	struct wlan_objmgr_pdev *pdev;
 	struct psoc_mlme_wakelock *psoc_wakelock;
 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
+	struct wlan_channel *curr_channel;
+	uint32_t ch_freq;
+	enum phy_ch_width ch_width;
+	uint32_t is_dfs;
 
 	psoc = wlan_vdev_get_psoc(vdev);
+	pdev = wlan_vdev_get_pdev(vdev);
+
+	if (!pdev) {
+		mlme_err("pdev is NULL");
+		return;
+	}
+
+	curr_channel = wlan_vdev_mlme_get_bss_chan(vdev);
+	ch_freq = curr_channel->ch_freq;
+	ch_width = curr_channel->ch_width;
+	is_dfs = wlan_reg_is_dfs_for_freq(pdev, ch_freq);
+
 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
 	if (!rx_ops || !rx_ops->psoc_get_wakelock_info) {
 		mlme_err("psoc_id:%d No Rx Ops",
@@ -247,6 +293,9 @@ void target_if_vdev_stop_link_handler(struct wlan_objmgr_vdev *vdev)
 
 	psoc_wakelock = rx_ops->psoc_get_wakelock_info(psoc);
 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
-		target_if_vote_for_link_down(psoc, psoc_wakelock);
+		if (is_dfs ||
+		    (wlan_reg_get_5g_bonded_channel_state_for_freq(pdev,
+			ch_freq, ch_width) == CHANNEL_STATE_DFS))
+			target_if_vote_for_link_down(psoc, psoc_wakelock);
 }
 

+ 2 - 2
target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_tx_ops.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -487,7 +487,7 @@ static QDF_STATUS target_if_vdev_mgr_start_send(
 							  START_RESPONSE_BIT);
 	} else {
 		target_if_vdev_start_link_handler(vdev,
-						  param->channel.dfs_set);
+						  param->is_restart);
 	}
 	return status;
 }