Pārlūkot izejas kodu

qcacmn: Fix high CAC timeouts

High CAC timeout is seen for weather and non-weather DFS channels.
This is due to the delay in 5.4 Kernel timers. There is 1 second delay
observed for every 60 seconds.

To fix this issue, replace qdf timers with HR timer for CAC timeout.
On CAC expiry, when VDEV UP is sent to FW, serialization timer is
cancelled. Since CAC expiry is processed in H/W interrupt context
(while using HR timers), no other timer cancellation is allowed.
Hence, process the CAC timer completion in work queue context to allow
other timer cancellations by the CAC thread.

Change-Id: I92c4662decbba27261448327abb16708d941d778
CRs-Fixed: 3142394
Amith Ajith 3 gadi atpakaļ
vecāks
revīzija
8635ab3be9
2 mainītis faili ar 33 papildinājumiem un 19 dzēšanām
  1. 3 2
      umac/dfs/core/src/dfs.h
  2. 30 17
      umac/dfs/core/src/misc/dfs_cac.c

+ 3 - 2
umac/dfs/core/src/dfs.h

@@ -1238,7 +1238,8 @@ struct wlan_dfs {
 	TAILQ_HEAD(, dfs_nolelem) dfs_nol_free_list;
 	TAILQ_HEAD(, dfs_nolelem) dfs_nol_free_list;
 	qdf_work_t     dfs_nol_elem_free_work;
 	qdf_work_t     dfs_nol_elem_free_work;
 
 
-	qdf_timer_t    dfs_cac_timer;
+	qdf_hrtimer_data_t    dfs_cac_timer;
+	qdf_work_t     dfs_cac_completion_work;
 	qdf_timer_t    dfs_cac_valid_timer;
 	qdf_timer_t    dfs_cac_valid_timer;
 	int            dfs_cac_timeout_override;
 	int            dfs_cac_timeout_override;
 	uint8_t        dfs_enable:1,
 	uint8_t        dfs_enable:1,
@@ -2940,7 +2941,7 @@ void dfs_complete_deferred_tasks(struct wlan_dfs *dfs);
  *
  *
  * Return: void.
  * Return: void.
  */
  */
-void dfs_process_cac_completion(struct wlan_dfs *dfs);
+void dfs_process_cac_completion(void *context);
 
 
 #ifdef WLAN_DFS_TRUE_160MHZ_SUPPORT
 #ifdef WLAN_DFS_TRUE_160MHZ_SUPPORT
 /**
 /**

+ 30 - 17
umac/dfs/core/src/misc/dfs_cac.c

@@ -2,7 +2,7 @@
  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
  * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
  * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
  * All rights reserved.
  * All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  *
  * Redistribution and use in source and binary forms, with or without
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * modification, are permitted provided that the following conditions
@@ -81,8 +81,9 @@ static void dfs_clear_nol_history_for_curchan(struct wlan_dfs *dfs)
 				num_subchs, DFS_NOL_HISTORY_RESET);
 				num_subchs, DFS_NOL_HISTORY_RESET);
 }
 }
 
 
-void dfs_process_cac_completion(struct wlan_dfs *dfs)
+void dfs_process_cac_completion(void *context)
 {
 {
+	struct wlan_dfs *dfs = (struct wlan_dfs *)context;
 	enum phy_ch_width ch_width = CH_WIDTH_INVALID;
 	enum phy_ch_width ch_width = CH_WIDTH_INVALID;
 	uint16_t primary_chan_freq = 0, sec_chan_freq = 0;
 	uint16_t primary_chan_freq = 0, sec_chan_freq = 0;
 	struct dfs_channel *dfs_curchan;
 	struct dfs_channel *dfs_curchan;
@@ -164,16 +165,21 @@ void dfs_process_cac_completion(struct wlan_dfs *dfs)
  * Sets dfs_cac_timer_running to 0  and dfs_cac_valid_timer.
  * Sets dfs_cac_timer_running to 0  and dfs_cac_valid_timer.
  */
  */
 #ifdef CONFIG_CHAN_FREQ_API
 #ifdef CONFIG_CHAN_FREQ_API
-static os_timer_func(dfs_cac_timeout)
+static enum qdf_hrtimer_restart_status
+dfs_cac_timeout(qdf_hrtimer_data_t *arg)
 {
 {
 	struct wlan_dfs *dfs = NULL;
 	struct wlan_dfs *dfs = NULL;
+	void *ptr = (void *)arg;
+	qdf_hrtimer_data_t *thr = container_of(ptr, qdf_hrtimer_data_t, u);
 
 
-	OS_GET_TIMER_ARG(dfs, struct wlan_dfs *);
+	dfs = container_of(thr, struct wlan_dfs, dfs_cac_timer);
 
 
 	if (dfs_is_hw_mode_switch_in_progress(dfs))
 	if (dfs_is_hw_mode_switch_in_progress(dfs))
 		dfs->dfs_defer_params.is_cac_completed = true;
 		dfs->dfs_defer_params.is_cac_completed = true;
 	else
 	else
-		dfs_process_cac_completion(dfs);
+		qdf_sched_work(NULL, &dfs->dfs_cac_completion_work);
+
+	return QDF_HRTIMER_NORESTART;
 }
 }
 #endif
 #endif
 
 
@@ -182,12 +188,15 @@ void dfs_cac_timer_attach(struct wlan_dfs *dfs)
 {
 {
 	dfs->dfs_cac_timeout_override = -1;
 	dfs->dfs_cac_timeout_override = -1;
 	dfs->wlan_dfs_cac_time = WLAN_DFS_WAIT_MS;
 	dfs->wlan_dfs_cac_time = WLAN_DFS_WAIT_MS;
-	qdf_timer_init(NULL,
-			&(dfs->dfs_cac_timer),
-			dfs_cac_timeout,
-			(void *)(dfs),
-			QDF_TIMER_TYPE_WAKE_APPS);
-
+	qdf_hrtimer_init(&dfs->dfs_cac_timer,
+			 dfs_cac_timeout,
+			 QDF_CLOCK_MONOTONIC,
+			 QDF_HRTIMER_MODE_REL,
+			 QDF_CONTEXT_HARDWARE);
+	qdf_create_work(NULL,
+			&dfs->dfs_cac_completion_work,
+			dfs_process_cac_completion,
+			dfs);
 	qdf_timer_init(NULL,
 	qdf_timer_init(NULL,
 			&(dfs->dfs_cac_valid_timer),
 			&(dfs->dfs_cac_valid_timer),
 			dfs_cac_valid_timeout,
 			dfs_cac_valid_timeout,
@@ -197,7 +206,8 @@ void dfs_cac_timer_attach(struct wlan_dfs *dfs)
 
 
 void dfs_cac_timer_reset(struct wlan_dfs *dfs)
 void dfs_cac_timer_reset(struct wlan_dfs *dfs)
 {
 {
-	qdf_timer_stop(&dfs->dfs_cac_timer);
+	qdf_hrtimer_cancel(&dfs->dfs_cac_timer);
+	qdf_flush_work(&dfs->dfs_cac_completion_work);
 	dfs_get_override_cac_timeout(dfs,
 	dfs_get_override_cac_timeout(dfs,
 			&(dfs->dfs_cac_timeout_override));
 			&(dfs->dfs_cac_timeout_override));
 	dfs_clear_cac_started_chan(dfs);
 	dfs_clear_cac_started_chan(dfs);
@@ -205,8 +215,9 @@ void dfs_cac_timer_reset(struct wlan_dfs *dfs)
 
 
 void dfs_cac_timer_detach(struct wlan_dfs *dfs)
 void dfs_cac_timer_detach(struct wlan_dfs *dfs)
 {
 {
-	qdf_timer_free(&dfs->dfs_cac_timer);
-
+	qdf_hrtimer_kill(&dfs->dfs_cac_timer);
+	qdf_flush_work(&dfs->dfs_cac_completion_work);
+	qdf_destroy_work(NULL, &dfs->dfs_cac_completion_work);
 	qdf_timer_free(&dfs->dfs_cac_valid_timer);
 	qdf_timer_free(&dfs->dfs_cac_valid_timer);
 	dfs->dfs_cac_valid = 0;
 	dfs->dfs_cac_valid = 0;
 }
 }
@@ -237,14 +248,16 @@ void dfs_start_cac_timer(struct wlan_dfs *dfs)
 		  cac_timeout,
 		  cac_timeout,
 		  qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000);
 		  qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000);
 
 
-	qdf_timer_mod(&dfs->dfs_cac_timer, cac_timeout * 1000);
+	qdf_hrtimer_start(&dfs->dfs_cac_timer,
+			  qdf_time_ms_to_ktime(cac_timeout * 1000),
+			  QDF_HRTIMER_MODE_REL);
 	dfs->dfs_cac_aborted = 0;
 	dfs->dfs_cac_aborted = 0;
 }
 }
 #endif
 #endif
 
 
 void dfs_cancel_cac_timer(struct wlan_dfs *dfs)
 void dfs_cancel_cac_timer(struct wlan_dfs *dfs)
 {
 {
-	qdf_timer_stop(&dfs->dfs_cac_timer);
+	qdf_hrtimer_cancel(&dfs->dfs_cac_timer);
 	dfs_clear_cac_started_chan(dfs);
 	dfs_clear_cac_started_chan(dfs);
 }
 }
 
 
@@ -256,7 +269,7 @@ void dfs_cac_stop(struct wlan_dfs *dfs)
 	dfs_debug(dfs, WLAN_DEBUG_DFS,
 	dfs_debug(dfs, WLAN_DEBUG_DFS,
 		"Stopping CAC Timer %d procphyerr 0x%08x",
 		"Stopping CAC Timer %d procphyerr 0x%08x",
 		 dfs->dfs_curchan->dfs_ch_freq, phyerr);
 		 dfs->dfs_curchan->dfs_ch_freq, phyerr);
-	qdf_timer_stop(&dfs->dfs_cac_timer);
+	qdf_hrtimer_cancel(&dfs->dfs_cac_timer);
 	if (dfs->dfs_cac_timer_running)
 	if (dfs->dfs_cac_timer_running)
 		dfs->dfs_cac_aborted = 1;
 		dfs->dfs_cac_aborted = 1;
 	dfs_clear_cac_started_chan(dfs);
 	dfs_clear_cac_started_chan(dfs);