فهرست منبع

qca-wifi: Check if OCAC completion event is received on current channel

Consider a case where the current operating channel is 36HT80 and Agile
channel is 5290. When a radar is injected on agile channel 5290, Host
aborts agile on channel 5290, changes the timer status to not running  and
configures agile to the next channel 5530 and then changes the time status
again to running. But the FW might send the OCAC completion event, with
status as OCAC CANCEL for the previously configured channel 5290. Host will
now change the precac timer status as not-running even though Host has
changed the agile channel to 5530. This is an undesirable state change.

As a consequence, when a radar is injected on the agile channel 5530, Host
will add the channels to NOL but will not trigger a channel change because
according to Host, the precac timer is not running(Host will change agile
channel on radar detection only if the precac timer is running).

Whenever an OCAC completion event is received, check if the event is
received for the currently configured agile channel, else ignore the event
without processing.

CRs-Fixed: 2677927
Change-Id: I18788857bc97a8f78426185f00596079ae2cbfd5
Vignesh U 5 سال پیش
والد
کامیت
48615cf86f
1فایلهای تغییر یافته به همراه87 افزوده شده و 6 حذف شده
  1. 87 6
      umac/dfs/core/src/misc/dfs_zero_cac.c

+ 87 - 6
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) {
@@ -1982,12 +2063,12 @@ void dfs_process_ocac_complete(struct wlan_objmgr_pdev *pdev,
 	} else if (ocac_status == OCAC_SUCCESS) {
 		dfs_debug(NULL, WLAN_DEBUG_DFS_ALWAYS,
 			  "PreCAC timer Completed for agile freq: %d",
-			  center_freq_mhz);
+			  center_freq_mhz1);
 		/*
 		 * 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_chwidth = dfs->dfs_precac_chwidth;
 		dfs_start_agile_precac_timer(dfs,
 					     ocac_status,