Переглянути джерело

Merge "qca-wifi: Stop precac timer for OCAC completion on 165MHz channel"

Linux Build Service Account 5 роки тому
батько
коміт
f5b44af464
1 змінених файлів з 90 додано та 7 видалено
  1. 90 7
      umac/dfs/core/src/misc/dfs_zero_cac.c

+ 90 - 7
umac/dfs/core/src/misc/dfs_zero_cac.c

@@ -1953,23 +1953,104 @@ void dfs_mark_precac_nol_for_freq(struct wlan_dfs *dfs,
 }
 #endif
 
+#ifdef QCA_SUPPORT_AGILE_DFS
+#ifdef CONFIG_CHAN_FREQ_API
+/* Checks the Host side agile configurations. ie if agile channel
+ * is configured as 5730MHz and the agile channel width is 80P80/165MHz.
+ */
+#define IS_HOST_AGILE_CURCHAN_165MHZ(_x) \
+	((_x)->dfs_agile_precac_freq_mhz == \
+	 RESTRICTED_80P80_CHAN_CENTER_FREQ) && \
+	((_x)->dfs_precac_chwidth == CH_WIDTH_80P80MHZ)
+
+/* Checks if the FW Agile operation was on the restricited 80P80MHz,
+ * by comparing the center frequency 1 with 5690MHz, center frequency 2
+ * with 5775MHz and the channel width was 80P80/165MHz.
+ */
+#define IS_OCAC_EVENT_ON_165_MHZ_CHAN(_x, _y, _z) \
+	((_x) == RESTRICTED_80P80_LEFT_80_CENTER_FREQ) && \
+	((_y) == RESTRICTED_80P80_RIGHT_80_CENTER_FREQ) && \
+	((_z) == CH_WIDTH_80P80MHZ)
+
+/*
+ * dfs_is_ocac_complete_event_for_cur_agile_chan() - Check if the OCAC
+ * completion event from FW is received for the currently configured agile
+ * channel in host.
+ *
+ * @dfs: Pointer to dfs structure.
+ * @center_freq_mhz1: Center frequency of the band when the precac width is
+ * 20/40/80/160MHz and center frequency of the left 80MHz in case of restricted
+ * 80P80/165MHz.
+ * @center_freq_mhz2: Center frequency of the right 80MHz in case of restricted
+ * 80P80/165MHz. It is zero for other channel widths.
+ * @chwidth: Agile channel width for which the completion event is received.
+ *
+ * return: True if the channel on which OCAC completion event received is same
+ * as currently configured agile channel in host. False otherwise.
+ */
+static bool
+dfs_is_ocac_complete_event_for_cur_agile_chan(struct wlan_dfs *dfs,
+					      uint32_t center_freq_mhz1,
+					      uint32_t center_freq_mhz2,
+					      enum phy_ch_width chwidth)
+{
+    if (IS_HOST_AGILE_CURCHAN_165MHZ(dfs) &&
+	IS_OCAC_EVENT_ON_165_MHZ_CHAN(center_freq_mhz1,
+				      center_freq_mhz2,
+				      chwidth))
+	return true;
+    else if (dfs->dfs_agile_precac_freq_mhz == center_freq_mhz1)
+	return true;
+    else
+	return false;
+}
+
 /*
  * dfs_process_ocac_complete() - Process OCAC Complete eventid.
  * @pdev: Pointer to wlan_objmgr_pdev.
  * @ocac_status: OCAC Status.
- * @center_freq_mhz: Center frequency in MHZ.
+ * @center_freq_mhz1: Center frequency of the band when the precac width is
+ * 20/40/80/160MHz and center frequency of the left 80MHz in case of restricted
+ * 80P80/165MHz.
+ * @center_freq_mhz2: Center frequency of the right 80MHz in case of restricted
+ * 80P80/165MHz. It is zero for other channel widths.
+ * @chwidth: Agile channel width for which the completion event is received.
  */
-#ifdef QCA_SUPPORT_AGILE_DFS
-#ifdef CONFIG_CHAN_FREQ_API
 void dfs_process_ocac_complete(struct wlan_objmgr_pdev *pdev,
 			       uint32_t ocac_status,
-			       uint32_t center_freq_mhz)
+			       uint32_t center_freq_mhz1,
+			       uint32_t center_freq_mhz2,
+			       enum phy_ch_width chwidth)
 {
 	struct wlan_dfs *dfs = NULL;
 	struct dfs_agile_cac_params adfs_param;
 
 	dfs = wlan_pdev_get_dfs_obj(pdev);
 
+	/* When the FW sends a delayed OCAC completion status, Host might
+	 * have changed the precac channel already before an OCAC
+	 * completion event is received. So the OCAC completion status
+	 * should be validated if it is on the currently configured agile
+	 * channel.
+	 */
+
+	/* Assume the previous agile channel was 64 (20Mhz) and current
+	 * agile channel is 100(20Mhz), if the event from the FW is for
+	 * previously configured agile channel 64(20Mhz) then Host ignores
+	 * the event.
+	 */
+	if (!dfs_is_ocac_complete_event_for_cur_agile_chan(dfs,
+							  center_freq_mhz1,
+							  center_freq_mhz2,
+							  chwidth)) {
+	    dfs_debug(NULL, WLAN_DEBUG_DFS_ALWAYS,
+		    "OCAC completion event is received on a different channel %d %d that is not the current Agile channel %d",
+		    center_freq_mhz1,
+		    center_freq_mhz2,
+		    dfs->dfs_agile_precac_freq_mhz);
+	    return;
+	}
+
 	/* STOP TIMER irrespective of status */
 	utils_dfs_cancel_precac_timer(pdev);
 	if (ocac_status == OCAC_RESET) {
@@ -1981,13 +2062,15 @@ void dfs_process_ocac_complete(struct wlan_objmgr_pdev *pdev,
 			  "PreCAC timer abort, agile precac stopped");
 	} else if (ocac_status == OCAC_SUCCESS) {
 		dfs_debug(NULL, WLAN_DEBUG_DFS_ALWAYS,
-			  "PreCAC timer Completed for agile freq: %d",
-			  center_freq_mhz);
+			  "PreCAC timer Completed for agile freq: %d %d",
+			  center_freq_mhz1,
+			  center_freq_mhz2);
 		/*
 		 * TRIGGER agile precac timer with 0sec timeout
 		 * with ocac_status 0 for old pdev
 		 */
-		adfs_param.precac_center_freq_1 = center_freq_mhz;
+		adfs_param.precac_center_freq_1 = center_freq_mhz1;
+		adfs_param.precac_center_freq_2 = center_freq_mhz2;
 		adfs_param.precac_chwidth = dfs->dfs_precac_chwidth;
 		dfs_start_agile_precac_timer(dfs,
 					     ocac_status,