ソースを参照

qcacmn: Add locks to protect DFS NOL list

Add locks to prevent concurrent access of DFS NOL list
from different  contexts.

Change-Id: Ib94bb08bcf3e0cac80b2f8e6be7ab4fd54c53a68
CRs-Fixed: 2156892
Abhijit Pradhan 7 年 前
コミット
6744161372

+ 247 - 189
umac/dfs/core/src/dfs.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016-2017 The Linux Foundation.  All rights reserved.
+ * Copyright (c) 2013, 2016-2018 The Linux Foundation.  All rights reserved.
  * Copyright (c) 2005-2006 Atheros Communications, Inc.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -149,17 +149,42 @@
 #define DFS_EXT_CHAN_LOADING_THRESH 30
 #define DFS_DEFAULT_PRI_MARGIN      6
 #define DFS_DEFAULT_FIXEDPATTERN_PRI_MARGIN	4
-#define WLAN_DFSQ_LOCK(_dfs)            spin_lock(&(_dfs)->dfs_radarqlock)
-#define WLAN_DFSQ_UNLOCK(_dfs)          spin_unlock(&(_dfs)->dfs_radarqlock)
-#define WLAN_DFSQ_LOCK_INIT(_dfs)       spin_lock_init(&(_dfs)->dfs_radarqlock)
 
-#define WLAN_ARQ_LOCK(_dfs)             spin_lock(&(_dfs)->dfs_arqlock)
-#define WLAN_ARQ_UNLOCK(_dfs)           spin_unlock(&(_dfs)->dfs_arqlock)
-#define WLAN_ARQ_LOCK_INIT(_dfs)        spin_lock_init(&(_dfs)->dfs_arqlock)
-
-#define WLAN_DFSEVENTQ_LOCK(_dfs)       spin_lock(&(_dfs)->dfs_eventqlock)
-#define WLAN_DFSEVENTQ_UNLOCK(_dfs)     spin_unlock(&(_dfs)->dfs_eventqlock)
-#define WLAN_DFSEVENTQ_LOCK_INIT(_dfs)  spin_lock_init(&(_dfs)->dfs_eventqlock)
+#define WLAN_DFSQ_LOCK(_dfs)         qdf_spin_lock(&(_dfs)->dfs_radarqlock)
+#define WLAN_DFSQ_UNLOCK(_dfs)       qdf_spin_unlock(&(_dfs)->dfs_radarqlock)
+#define WLAN_DFSQ_LOCK_CREATE(_dfs)  qdf_spinlock_create( \
+		&(_dfs)->dfs_radarqlock)
+#define WLAN_DFSQ_LOCK_DESTROY(_dfs) qdf_spinlock_destroy( \
+		&(_dfs)->dfs_radarqlock)
+
+#define WLAN_ARQ_LOCK(_dfs)          qdf_spin_lock(&(_dfs)->dfs_arqlock)
+#define WLAN_ARQ_UNLOCK(_dfs)        qdf_spin_unlock(&(_dfs)->dfs_arqlock)
+#define WLAN_ARQ_LOCK_CREATE(_dfs)   qdf_spinlock_create(&(_dfs)->dfs_arqlock)
+#define WLAN_ARQ_LOCK_DESTROY(_dfs)  qdf_spinlock_destroy(&(_dfs)->dfs_arqlock)
+
+#define WLAN_DFSEVENTQ_LOCK(_dfs)         qdf_spin_lock(&(_dfs)->dfs_eventqlock)
+#define WLAN_DFSEVENTQ_UNLOCK(_dfs)       qdf_spin_unlock( \
+		&(_dfs)->dfs_eventqlock)
+#define WLAN_DFSEVENTQ_LOCK_CREATE(_dfs)  qdf_spinlock_create( \
+		&(_dfs)->dfs_eventqlock)
+#define WLAN_DFSEVENTQ_LOCK_DESTROY(_dfs) qdf_spinlock_destroy( \
+		&(_dfs)->dfs_eventqlock)
+
+#define WLAN_DFSNOL_LOCK(_dfs)         qdf_spin_lock_bh(&(_dfs)->dfs_nol_lock)
+#define WLAN_DFSNOL_UNLOCK(_dfs)       qdf_spin_unlock_bh(&(_dfs)->dfs_nol_lock)
+#define WLAN_DFSNOL_LOCK_CREATE(_dfs)  qdf_spinlock_create( \
+		&(_dfs)->dfs_nol_lock)
+#define WLAN_DFSNOL_LOCK_DESTROY(_dfs) qdf_spinlock_destroy( \
+		&(_dfs)->dfs_nol_lock)
+
+#define PRECAC_LIST_LOCK(_dfs)         qdf_spin_lock_irqsave( \
+		&(_dfs)->dfs_precac_lock)
+#define PRECAC_LIST_UNLOCK(_dfs)       qdf_spin_unlock_irqrestore( \
+		&(_dfs)->dfs_precac_lock)
+#define PRECAC_LIST_LOCK_CREATE(_dfs)  qdf_spinlock_create( \
+		&(_dfs)->dfs_precac_lock)
+#define PRECAC_LIST_LOCK_DESTROY(_dfs) qdf_spinlock_destroy( \
+		&(_dfs)->dfs_precac_lock)
 
 /* Mask for time stamp from descriptor */
 #define DFS_TSMASK    0xFFFFFFFF
@@ -290,6 +315,41 @@
 /* Array offset to ETSI legacy pulse */
 #define ETSI_LEGACY_PULSE_ARR_OFFSET 2
 
+#define DFS_NOL_ADD_CHAN_LOCKED(dfs, freq, timeout)         \
+	do {                                                \
+		WLAN_DFSNOL_LOCK(dfs);                      \
+		dfs_nol_addchan(dfs, freq, timeout);        \
+		WLAN_DFSNOL_UNLOCK(dfs);                    \
+	} while (0)
+
+#define DFS_NOL_DELETE_CHAN_LOCKED(dfs, freq, chwidth)      \
+	do {                                                \
+		WLAN_DFSNOL_LOCK(dfs);                      \
+		dfs_nol_delete(dfs, freq, chwidth);         \
+		WLAN_DFSNOL_UNLOCK(dfs);                    \
+	} while (0)
+
+#define DFS_GET_NOL_LOCKED(dfs, dfs_nol, nchan)             \
+	do {                                                \
+		WLAN_DFSNOL_LOCK(dfs);                      \
+		dfs_get_nol(dfs, dfs_nol, nchan);           \
+		WLAN_DFSNOL_UNLOCK(dfs);                    \
+	} while (0)
+
+#define DFS_PRINT_NOL_LOCKED(dfs)                           \
+	do {                                                \
+		WLAN_DFSNOL_LOCK(dfs);                      \
+		dfs_print_nol(dfs);                         \
+		WLAN_DFSNOL_UNLOCK(dfs);                    \
+	} while (0)
+
+#define DFS_NOL_FREE_LIST_LOCKED(dfs)                       \
+	do {                                                \
+		WLAN_DFSNOL_LOCK(dfs);                      \
+		dfs_nol_free_list(dfs);                     \
+		WLAN_DFSNOL_UNLOCK(dfs);                    \
+	} while (0)
+
 /**
  * struct dfs_pulseparams - DFS pulse param structure.
  * @p_time:        Time for start of pulse in usecs.
@@ -760,189 +820,188 @@ struct dfs_event_log {
 #define RSSI_POSSIBLY_FALSE              50
 #define SEARCH_FFT_REPORT_PEAK_MAG_THRSH 40
 
-#define PRECAC_LIST_LOCK(_dfs)    spin_lock_irqsave(  \
-		&(_dfs)->dfs_precac_lock, (_dfs)->dfs_precac_lock_flags)
-#define PRECAC_LIST_UNLOCK(_dfs)  spin_unlock_irqrestore(  \
-		&(_dfs)->dfs_precac_lock, (_dfs)->dfs_precac_lock_flags)
-#define PRECAC_LIST_LOCK_INIT(_dfs)  spin_lock_init(&(_dfs)->dfs_precac_lock)
-
-/**
- * struct wlan_dfs -        The main dfs structure.
- * @dfs_debug_mask:        Current debug bitmask.
- * @dfs_curchan_radindex:  Current channel radar index.
- * @dfs_extchan_radindex:  Extension channel radar index.
- * @dfsdomain:             cur. DFS domain.
- * @dfs_proc_phyerr:       Flags for Phy Errs to process.
- * @dfs_eventq:            Q of free dfs event objects.
- * @dfs_eventqlock:        Lock for free dfs event list.
- * @dfs_radarq:            Q of radar events.
- * @dfs_radarqlock:        Lock for dfs q.
- * @dfs_arq:               Q of AR events.
- * @dfs_arqlock:           Lock for AR q.
- * @dfs_ar_state:          AR state.
- * @dfs_radar[]:           dfs_radar - Per-Channel Radar detector state.
- * @dfs_radarf[]:          dfs_radarf - One filter for each radar pulse type.
- * @dfs_rinfo:             State vars for radar processing.
- * @dfs_b5radars:          array of bin5 radar events.
- * @dfs_ftindextable:        map of radar durs to filter types.
- * @dfs_nol:               Non occupancy list for radar.
- * @dfs_nol_count:         How many items?
- * @dfs_defaultparams:     Default phy params per radar state.
- * @wlan_dfs_stats:         DFS related stats.
- * @pulses:                pulse history.
- * @events:                Events structure.
- * @wlan_radar_tasksched:   radar task is scheduled.
- * @wlan_dfswait:           waiting on channel for radar detect.
- * @wlan_dfstest:           Test timer in progress.
- * @dfs_caps:              Object of wlan_dfs_caps structure.
- * @wlan_dfstest_ieeechan:  IEEE chan num to return to after a dfs mute test.
- * @wlan_dfs_cac_time:      CAC period.
- * @wlan_dfstesttime:       Time to stay off chan during dfs test.
- * @wlan_dfswaittimer:      dfs wait timer.
- * @wlan_dfstesttimer:      dfs mute test timer.
- * @wlan_dfs_debug_timer:   dfs debug timer.
- * @dfs_second_segment_bangradar: Bangaradar on second segment of VHT80_80/160.
+/**
+ * struct wlan_dfs -                 The main dfs structure.
+ * @dfs_debug_mask:                  Current debug bitmask.
+ * @dfs_curchan_radindex:            Current channel radar index.
+ * @dfs_extchan_radindex:            Extension channel radar index.
+ * @dfsdomain:                       Current DFS domain.
+ * @dfs_proc_phyerr:                 Flags for Phy Errs to process.
+ * @dfs_eventq:                      Q of free dfs event objects.
+ * @dfs_eventqlock:                  Lock for free dfs event list.
+ * @dfs_radarq:                      Q of radar events.
+ * @dfs_radarqlock:                  Lock for dfs q.
+ * @dfs_arq:                         Q of AR events.
+ * @dfs_arqlock:                     Lock for AR q.
+ * @dfs_ar_state:                    AR state.
+ * @dfs_radar[]:                     Per-Channel Radar detector state.
+ * @dfs_radarf[]:                    One filter for each radar pulse type.
+ * @dfs_rinfo:                       State vars for radar processing.
+ * @dfs_b5radars:                    Array of bin5 radar events.
+ * @dfs_ftindextable:                Map of radar durs to filter types.
+ * @dfs_nol:                         Non occupancy list for radar.
+ * @dfs_nol_count:                   How many items?
+ * @dfs_defaultparams:               Default phy params per radar state.
+ * @wlan_dfs_stats:                  DFS related stats.
+ * @pulses:                          Pulse history.
+ * @events:                          Events structure.
+ * @wlan_radar_tasksched:            Radar task is scheduled.
+ * @wlan_dfswait:                    Waiting on channel for radar detect.
+ * @wlan_dfstest:                    Test timer in progress.
+ * @dfs_caps:                        Object of wlan_dfs_caps structure.
+ * @wlan_dfstest_ieeechan:           IEEE chan num to return to after a dfs mute
+ *                                   test.
+ * @wlan_dfs_cac_time:               CAC period.
+ * @wlan_dfstesttime:                Time to stay off chan during dfs test.
+ * @wlan_dfswaittimer:               Dfs wait timer.
+ * @wlan_dfstesttimer:               Dfs mute test timer.
+ * @wlan_dfs_debug_timer:            Dfs debug timer.
+ * @dfs_second_segment_bangradar:    Bangaradar on second segment of
+ *                                   VHT80_80/160.
  * @is_radar_found_on_secondary_seg: Radar on second segment.
- * @is_radar_during_precac: Radar found during precac.
- * @dfs_precac_lock:       lock to protect precac lists.
- * @dfs_precac_lock_flags  Flags for dfs_precac_lock.
- * @dfs_precac_enable:     Enable the precac.
- * @dfs_precac_secondary_freq: Second segment freq for precac.
- * @dfs_precac_primary_freq: Primary freq.
- * @dfs_precac_timer_running: precac timer running.
+ * @is_radar_during_precac:          Radar found during precac.
+ * @dfs_precac_lock:                 Lock to protect precac lists.
+ * @dfs_precac_enable:               Enable the precac.
+ * @dfs_precac_secondary_freq:       Second segment freq for precac.
+ * @dfs_precac_primary_freq:         Primary freq.
+ * @dfs_precac_timer_running:        Precac timer running.
  * @dfs_defer_precac_channel_change: Defer precac channel change.
  * @dfs_pre_cac_timeout_channel_change: Channel change due to precac timeout.
- * @wlan_dfs_task_timer:    dfs wait timer.
- * @dur_multiplier:        Duration multiplier.
- * @wlan_dfs_isdfsregdomain: true when AP is in DFS domain
- * @wlan_dfs_false_rssi_thres: False RSSI Threshold.
- * @wlan_dfs_peak_mag:      peak mag.
- * @radar_log[]:           radar log.
- * @dfs_event_log_count:   Event log count.
- * @dfs_event_log_on:      Event log on.
- * @dfs_phyerr_count:      Same as number of PHY radar interrupts.
- * @dfs_phyerr_reject_count: When TLV is supported, # of radar events ignored
- *                           after TLV is parsed.
- * @dfs_phyerr_queued_count: Number of radar events queued for matching the
- *                           filters.
- * @dfs_phyerr_freq_min:   Phyerr min freq.
- * @dfs_phyerr_freq_max:   Phyerr max freq.
- * @dfs_phyerr_w53_counter: phyerr w53 counter.
- * @dfs_pri_multiplier:    Allow pulse if they are within multiple of PRI for
- *                         the radar type.
- * @wlan_dfs_nol_timeout:   NOL timeout.
- * @update_nol:            Update NOL.
- * @dfs_seq_num:           Sequence number.
- * @dfs_nol_event[]:       NOL event.
- * @dfs_nol_timer:         NOL list processing.
- * @dfs_cac_timer:         CAC timer.
- * @dfs_cac_valid_timer:   Ignore CAC when this timer is running.
- * @dfs_cac_timeout_override: overridden cac timeout.
- * @dfs_enable:            DFS Enable.
- * @dfs_cac_timer_running: DFS CAC timer running.
- * @dfs_ignore_dfs:        Ignore DFS.
- * @dfs_ignore_cac:        Ignore CAC.
- * @dfs_cac_valid:         DFS CAC valid.
- * @dfs_cac_valid_time:    Time for which CAC will be valid and will not be
- *                         re-done.
- * @dfs_precac_timer:      PRECAC timer.
- * @dfs_precac_timeout_override: overridden precac timeout.
- * @dfs_num_precac_freqs:  Number of PreCAC VHT80 frequencies.
- * @dfs_precac_required_list: PreCAC required list.
- * @dfs_precac_done_list:  PreCAC done list.
- * @dfs_precac_nol_list:   PreCAC NOL List.
- * @dfs_is_offload_enabled: Set if DFS offload enabled.
- * @dfs_use_nol: Use the NOL when radar found (default: TRUE).
+ * @wlan_dfs_task_timer:             Dfs wait timer.
+ * @dur_multiplier:                  Duration multiplier.
+ * @wlan_dfs_isdfsregdomain:         True when AP is in DFS domain
+ * @wlan_dfs_false_rssi_thres:       False RSSI Threshold.
+ * @wlan_dfs_peak_mag:               Peak mag.
+ * @radar_log[]:                     Radar log.
+ * @dfs_event_log_count:             Event log count.
+ * @dfs_event_log_on:                Event log on.
+ * @dfs_phyerr_count:                Same as number of PHY radar interrupts.
+ * @dfs_phyerr_reject_count:         When TLV is supported, # of radar events
+ *                                   ignored after TLV is parsed.
+ * @dfs_phyerr_queued_count:         Number of radar events queued for matching
+ *                                   the filters.
+ * @dfs_phyerr_freq_min:             Phyerr min freq.
+ * @dfs_phyerr_freq_max:             Phyerr max freq.
+ * @dfs_phyerr_w53_counter:          Phyerr w53 counter.
+ * @dfs_pri_multiplier:              Allow pulse if they are within multiple of
+ *                                   PRI for the radar type.
+ * @wlan_dfs_nol_timeout:            NOL timeout.
+ * @update_nol:                      Update NOL.
+ * @dfs_seq_num:                     Sequence number.
+ * @dfs_nol_event[]:                 NOL event.
+ * @dfs_nol_timer:                   NOL list processing.
+ * @dfs_cac_timer:                   CAC timer.
+ * @dfs_cac_valid_timer:             Ignore CAC when this timer is running.
+ * @dfs_cac_timeout_override:        Overridden cac timeout.
+ * @dfs_enable:                      DFS Enable.
+ * @dfs_cac_timer_running:           DFS CAC timer running.
+ * @dfs_ignore_dfs:                  Ignore DFS.
+ * @dfs_ignore_cac:                  Ignore CAC.
+ * @dfs_cac_valid:                   DFS CAC valid.
+ * @dfs_cac_valid_time:              Time for which CAC will be valid and will
+ *                                   not be re-done.
+ * @dfs_precac_timer:                PRECAC timer.
+ * @dfs_precac_timeout_override:     Overridden precac timeout.
+ * @dfs_num_precac_freqs:            Number of PreCAC VHT80 frequencies.
+ * @dfs_precac_required_list:        PreCAC required list.
+ * @dfs_precac_done_list:            PreCAC done list.
+ * @dfs_precac_nol_list:             PreCAC NOL List.
+ * @dfs_is_offload_enabled:          Set if DFS offload enabled.
+ * @dfs_use_nol:                     Use the NOL when radar found(default: TRUE)
+ * @dfs_nol_lock:                    Lock to protect nol list.
  */
 struct wlan_dfs {
-	uint32_t  dfs_debug_mask;
-	int16_t   dfs_curchan_radindex;
-	int16_t   dfs_extchan_radindex;
-	uint32_t  dfsdomain;
-	uint32_t  dfs_proc_phyerr;
+	uint32_t       dfs_debug_mask;
+	int16_t        dfs_curchan_radindex;
+	int16_t        dfs_extchan_radindex;
+	uint32_t       dfsdomain;
+	uint32_t       dfs_proc_phyerr;
 
 	STAILQ_HEAD(, dfs_event) dfs_eventq;
-	spinlock_t dfs_eventqlock;
+	qdf_spinlock_t dfs_eventqlock;
 
 	STAILQ_HEAD(, dfs_event) dfs_radarq;
-	spinlock_t dfs_radarqlock;
+	qdf_spinlock_t dfs_radarqlock;
 
 	STAILQ_HEAD(, dfs_event) dfs_arq;
-	spinlock_t dfs_arqlock;
-	struct dfs_ar_state dfs_ar_state;
-	struct dfs_state dfs_radar[DFS_NUM_RADAR_STATES];
+	qdf_spinlock_t dfs_arqlock;
+
+	struct dfs_ar_state   dfs_ar_state;
+	struct dfs_state      dfs_radar[DFS_NUM_RADAR_STATES];
 	struct dfs_filtertype *dfs_radarf[DFS_MAX_RADAR_TYPES];
-	struct dfs_info dfs_rinfo;
+	struct dfs_info       dfs_rinfo;
 	struct dfs_bin5radars *dfs_b5radars;
-	int8_t **dfs_ftindextable;
-	struct dfs_nolelem *dfs_nol;
-	int dfs_nol_count;
+	int8_t                **dfs_ftindextable;
+	struct dfs_nolelem    *dfs_nol;
+	int                   dfs_nol_count;
 	struct wlan_dfs_phyerr_param dfs_defaultparams;
-	struct dfs_stats wlan_dfs_stats;
-	struct dfs_pulseline *pulses;
-	struct dfs_event *events;
-	uint32_t wlan_radar_tasksched:1,
-			 wlan_dfswait:1,
-			 wlan_dfstest:1;
+	struct dfs_stats      wlan_dfs_stats;
+	struct dfs_pulseline  *pulses;
+	struct dfs_event      *events;
+
+	uint32_t       wlan_radar_tasksched:1,
+				   wlan_dfswait:1,
+				   wlan_dfstest:1;
 	struct wlan_dfs_caps dfs_caps;
-	uint8_t wlan_dfstest_ieeechan;
-	uint32_t wlan_dfs_cac_time;
-	uint32_t wlan_dfstesttime;
-	os_timer_t wlan_dfswaittimer;
-	os_timer_t wlan_dfstesttimer;
-	os_timer_t wlan_dfs_debug_timer;
-	uint8_t    dfs_bangradar;
-	bool dfs_second_segment_bangradar;
-	bool is_radar_found_on_secondary_seg;
-	bool is_radar_during_precac;
-	spinlock_t dfs_precac_lock;
-	unsigned long dfs_precac_lock_flags;
-	bool dfs_precac_enable;
-	uint8_t dfs_precac_secondary_freq;
-	uint8_t dfs_precac_primary_freq;
-	uint8_t dfs_precac_timer_running;
-	uint8_t dfs_defer_precac_channel_change;
-	uint8_t dfs_pre_cac_timeout_channel_change:1;
-	os_timer_t wlan_dfs_task_timer;
-	int dur_multiplier;
-	uint16_t wlan_dfs_isdfsregdomain;
-	int wlan_dfs_false_rssi_thres;
-	int wlan_dfs_peak_mag;
+	uint8_t        wlan_dfstest_ieeechan;
+	uint32_t       wlan_dfs_cac_time;
+	uint32_t       wlan_dfstesttime;
+	os_timer_t     wlan_dfswaittimer;
+	os_timer_t     wlan_dfstesttimer;
+	os_timer_t     wlan_dfs_debug_timer;
+	uint8_t        dfs_bangradar;
+	bool           dfs_second_segment_bangradar;
+	bool           is_radar_found_on_secondary_seg;
+	bool           is_radar_during_precac;
+	qdf_spinlock_t dfs_precac_lock;
+	bool           dfs_precac_enable;
+	uint8_t        dfs_precac_secondary_freq;
+	uint8_t        dfs_precac_primary_freq;
+	uint8_t        dfs_precac_timer_running;
+	uint8_t        dfs_defer_precac_channel_change;
+	uint8_t        dfs_pre_cac_timeout_channel_change:1;
+	os_timer_t     wlan_dfs_task_timer;
+	int            dur_multiplier;
+	uint16_t       wlan_dfs_isdfsregdomain;
+	int            wlan_dfs_false_rssi_thres;
+	int            wlan_dfs_peak_mag;
 	struct dfs_event_log radar_log[DFS_EVENT_LOG_SIZE];
-	int dfs_event_log_count;
-	int dfs_event_log_on;
-	int dfs_phyerr_count;
-	int dfs_phyerr_reject_count;
-	int dfs_phyerr_queued_count;
-	int dfs_phyerr_freq_min;
-	int dfs_phyerr_freq_max;
-	int dfs_phyerr_w53_counter;
-	int dfs_pri_multiplier;
-	int wlan_dfs_nol_timeout;
-	bool update_nol;
-	uint32_t dfs_seq_num;
-	int dfs_nol_event[DFS_CHAN_MAX];
-	os_timer_t dfs_nol_timer;
-	os_timer_t dfs_cac_timer;
-	os_timer_t dfs_cac_valid_timer;
-	int dfs_cac_timeout_override;
-	uint8_t dfs_enable:1,
-		dfs_cac_timer_running:1,
-		dfs_ignore_dfs:1,
-		dfs_ignore_cac:1,
-		dfs_cac_valid:1;
-	uint32_t dfs_cac_valid_time;
-	os_timer_t dfs_precac_timer;
-	int dfs_precac_timeout_override;
-	uint8_t dfs_num_precac_freqs;
+	int            dfs_event_log_count;
+	int            dfs_event_log_on;
+	int            dfs_phyerr_count;
+	int            dfs_phyerr_reject_count;
+	int            dfs_phyerr_queued_count;
+	int            dfs_phyerr_freq_min;
+	int            dfs_phyerr_freq_max;
+	int            dfs_phyerr_w53_counter;
+	int            dfs_pri_multiplier;
+	int            wlan_dfs_nol_timeout;
+	bool           update_nol;
+	uint32_t       dfs_seq_num;
+	int            dfs_nol_event[DFS_CHAN_MAX];
+	os_timer_t     dfs_nol_timer;
+	os_timer_t     dfs_cac_timer;
+	os_timer_t     dfs_cac_valid_timer;
+	int            dfs_cac_timeout_override;
+	uint8_t        dfs_enable:1,
+				   dfs_cac_timer_running:1,
+				   dfs_ignore_dfs:1,
+				   dfs_ignore_cac:1,
+				   dfs_cac_valid:1;
+	uint32_t       dfs_cac_valid_time;
+	os_timer_t     dfs_precac_timer;
+	int            dfs_precac_timeout_override;
+	uint8_t        dfs_num_precac_freqs;
 
 	TAILQ_HEAD(, dfs_precac_entry) dfs_precac_required_list;
 	TAILQ_HEAD(, dfs_precac_entry) dfs_precac_done_list;
 	TAILQ_HEAD(, dfs_precac_entry) dfs_precac_nol_list;
+
 	struct dfs_channel *dfs_curchan;
 	struct wlan_objmgr_pdev *dfs_pdev_obj;
-	bool dfs_is_offload_enabled;
-	int dfs_use_nol;
+	bool           dfs_is_offload_enabled;
+	int            dfs_use_nol;
+	qdf_spinlock_t dfs_nol_lock;
 };
 
 /**
@@ -1775,6 +1834,12 @@ void dfs_nol_timer_init(struct wlan_dfs *dfs);
  */
 void dfs_nol_attach(struct wlan_dfs *dfs);
 
+/**
+ * dfs_nol_detach() - Detach NOL variables.
+ * @dfs: Pointer to wlan_dfs structure.
+ */
+void dfs_nol_detach(struct wlan_dfs *dfs);
+
 /**
  * dfs_print_nolhistory() - Print NOL history.
  * @dfs: Pointer to wlan_dfs structure.
@@ -1822,20 +1887,6 @@ int dfs_set_thresholds(struct wlan_dfs *dfs,
 		const uint32_t threshtype,
 		const uint32_t value);
 
-/**
- * ol_if_dfs_clist_update() - Update the channel list with the given NOL list.
- * @dfs: Pointer to wlan_dfs structure.
- * @cmd: DFS_NOL_CLIST_CMD_UPDATE command.
- * @nollist: NOL channel entries.
- * @nentries: Number of channels in the NOL entry.
- * @opmode: Device operating mode.
- */
-void ol_if_dfs_clist_update(struct wlan_dfs *dfs,
-		int cmd,
-		struct dfs_nol_chan_entry *nollist,
-		int nentries,
-		uint32_t opmode);
-
 /**
  * dfs_set_current_channel() - Set DFS current channel.
  * @dfs: Pointer to wlan_dfs structure.
@@ -1867,11 +1918,12 @@ int dfs_second_segment_radar_disable(struct wlan_dfs *dfs);
 
 /**
  * dfs_get_nol_chfreq_and_chwidth() - Get channel freq and width from NOL list.
- * @nollist: Pointer to NOL channel entry.
+ * @dfs_nol: Pointer to NOL channel entry.
  * @nol_chfreq: Pointer to save channel frequency.
  * @nol_chwidth: Pointer to save channel width.
+ * @index: Index to dfs_nol list.
  */
-void dfs_get_nol_chfreq_and_chwidth(struct dfs_nol_chan_entry *nollist,
+void dfs_get_nol_chfreq_and_chwidth(struct dfsreq_nolelem *dfs_nol,
 		uint32_t *nol_chfreq,
 		uint32_t *nol_chwidth,
 		int index);
@@ -2027,7 +2079,7 @@ void dfs_update_cur_chan_flags(struct wlan_dfs *dfs,
 void dfs_send_csa_to_current_chan(struct wlan_dfs *dfs);
 
 /**
- * dfs_radarevent_basic_sanity - Check basic sanity of the radar event
+ * dfs_radarevent_basic_sanity() - Check basic sanity of the radar event
  * @dfs: Pointer to wlan_dfs structure.
  * @chan: Current channel.
  *
@@ -2045,4 +2097,10 @@ int dfs_radarevent_basic_sanity(struct wlan_dfs *dfs,
  */
 struct wlan_lmac_if_dfs_tx_ops *
 wlan_psoc_get_dfs_txops(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * dfs_nol_free_list() - Free NOL elements.
+ * @dfs: Pointer to wlan_dfs structure.
+ */
+void dfs_nol_free_list(struct wlan_dfs *dfs);
 #endif  /* _DFS_H_ */

+ 1 - 15
umac/dfs/core/src/dfs_structs.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012, 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2012, 2016-2018 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 above
@@ -110,20 +110,6 @@ struct dfs_bin5pulse {
 	uint32_t  b5_rssimargin;
 };
 
-/**
- * struct dfs_nol_chan_entry - DFS NOL representation.
- * @nol_chfreq:      Centre frequency, MHz .
- * @nol_chwidth:     Width, MHz.
- * @nol_start_ticks: Start ticks, OS specific.
- * @nol_timeout_ms:  Timeout, ms
- */
-struct dfs_nol_chan_entry {
-	uint32_t      nol_chfreq;
-	uint32_t      nol_chwidth;
-	unsigned long nol_start_ticks;
-	uint32_t      nol_timeout_ms;
-};
-
 /**
  * wlan_dfs_phyerr_init_noval() - Fill wlan_dfs_phyerr_param with 0xFF.
  * @pe: Pointer to wlan_dfs_phyerr_param structure.

+ 12 - 7
umac/dfs/core/src/misc/dfs.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
  * Copyright (c) 2002-2006, Atheros Communications Inc.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -187,12 +187,12 @@ int dfs_main_attach(struct wlan_dfs *dfs)
 	/*Verify : Passing NULL to qdf_timer_init().*/
 	dfs_main_task_timer_init(dfs);
 
-	WLAN_DFSQ_LOCK_INIT(dfs);
+	WLAN_DFSQ_LOCK_CREATE(dfs);
 	STAILQ_INIT(&dfs->dfs_radarq);
-	WLAN_ARQ_LOCK_INIT(dfs);
+	WLAN_ARQ_LOCK_CREATE(dfs);
 	STAILQ_INIT(&dfs->dfs_arq);
 	STAILQ_INIT(&(dfs->dfs_eventq));
-	WLAN_DFSEVENTQ_LOCK_INIT(dfs);
+	WLAN_DFSEVENTQ_LOCK_CREATE(dfs);
 
 	dfs->events = (struct dfs_event *)qdf_mem_malloc(
 			sizeof(struct dfs_event)*DFS_MAX_EVENTS);
@@ -420,6 +420,10 @@ void dfs_main_detach(struct wlan_dfs *dfs)
 		qdf_mem_free(dfs->events);
 		dfs->events = NULL;
 	}
+
+	WLAN_DFSQ_LOCK_DESTROY(dfs);
+	WLAN_ARQ_LOCK_DESTROY(dfs);
+	WLAN_DFSEVENTQ_LOCK_DESTROY(dfs);
 }
 
 void dfs_detach(struct wlan_dfs *dfs)
@@ -427,6 +431,7 @@ void dfs_detach(struct wlan_dfs *dfs)
 	if (!dfs->dfs_is_offload_enabled)
 		dfs_main_detach(dfs);
 	dfs_zero_cac_detach(dfs);
+	dfs_nol_detach(dfs);
 }
 
 void dfs_destroy_object(struct wlan_dfs *dfs)
@@ -889,10 +894,10 @@ int dfs_control(struct wlan_dfs *dfs,
 		}
 		*outsize = sizeof(struct dfsreq_nolinfo);
 		nol = (struct dfsreq_nolinfo *)outdata;
-		dfs_get_nol(dfs,
+		DFS_GET_NOL_LOCKED(dfs,
 				(struct dfsreq_nolelem *)nol->dfs_nol,
 				&nol->dfs_ch_nchans);
-		dfs_print_nol(dfs);
+		DFS_PRINT_NOL_LOCKED(dfs);
 		break;
 	case DFS_SET_NOL:
 		if (insize < sizeof(struct dfsreq_nolinfo) || !indata) {
@@ -905,7 +910,7 @@ int dfs_control(struct wlan_dfs *dfs,
 				nol->dfs_ch_nchans);
 		break;
 	case DFS_SHOW_NOL:
-		dfs_print_nol(dfs);
+		DFS_PRINT_NOL_LOCKED(dfs);
 		break;
 	case DFS_SHOW_NOLHISTORY:
 		dfs_print_nolhistory(dfs);

+ 51 - 33
umac/dfs/core/src/misc/dfs_nol.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
  * Copyright (c) 2002-2010, Atheros Communications Inc.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -108,6 +108,12 @@ void dfs_nol_attach(struct wlan_dfs *dfs)
 	dfs->wlan_dfs_nol_timeout = DFS_NOL_TIMEOUT_S;
 	dfs_nol_timer_init(dfs);
 	dfs->dfs_use_nol = 1;
+	WLAN_DFSNOL_LOCK_CREATE(dfs);
+}
+
+void dfs_nol_detach(struct wlan_dfs *dfs)
+{
+	WLAN_DFSNOL_LOCK_DESTROY(dfs);
 }
 
 /**
@@ -144,7 +150,6 @@ static void dfs_nol_delete(struct wlan_dfs *dfs,
 				 (qdf_system_ticks()) / 1000));
 			qdf_timer_stop(&nol->nol_timer);
 			qdf_mem_free(nol);
-			nol = NULL;
 			nol = *prev_next;
 
 			/* Update the NOL counter. */
@@ -183,7 +188,7 @@ static os_timer_func(dfs_remove_from_nol)
 	delchwidth = nol_arg->nol_chwidth;
 
 	/* Delete the given NOL entry. */
-	dfs_nol_delete(dfs, delfreq, delchwidth);
+	DFS_NOL_DELETE_CHAN_LOCKED(dfs, delfreq, delchwidth);
 
 	/* Update the wireless stack with the new NOL. */
 	dfs_nol_update(dfs);
@@ -299,13 +304,15 @@ void dfs_set_nol(struct wlan_dfs *dfs,
 		nol_time_left_ms =
 			qdf_system_ticks_to_msecs(qdf_system_ticks() -
 				dfs_nol[i].nol_start_ticks);
+
 		if (nol_time_left_ms < dfs_nol[i].nol_timeout_ms) {
 			chan.dfs_ch_freq = dfs_nol[i].nol_freq;
 			chan.dfs_ch_flags = 0;
 			chan.dfs_ch_flagext = 0;
 			nol_time_left_ms =
 				(dfs_nol[i].nol_timeout_ms - nol_time_left_ms);
-			dfs_nol_addchan(dfs, chan.dfs_ch_freq,
+
+			DFS_NOL_ADD_CHAN_LOCKED(dfs, chan.dfs_ch_freq,
 					(nol_time_left_ms / TIME_IN_MS));
 		}
 	}
@@ -388,22 +395,21 @@ bad:
 #undef TIME_IN_US
 }
 
-void dfs_get_nol_chfreq_and_chwidth(struct dfs_nol_chan_entry *nollist,
+void dfs_get_nol_chfreq_and_chwidth(struct dfsreq_nolelem *dfs_nol,
 		uint32_t *nol_chfreq,
 		uint32_t *nol_chwidth,
 		int index)
 {
-	if (!nollist)
+	if (!dfs_nol)
 		return;
 
-	*nol_chfreq = nollist[index].nol_chfreq;
-	*nol_chwidth = nollist[index].nol_chwidth;
+	*nol_chfreq = dfs_nol[index].nol_freq;
+	*nol_chwidth = dfs_nol[index].nol_chwidth;
 }
 
 void dfs_nol_update(struct wlan_dfs *dfs)
 {
-	struct dfs_nol_chan_entry *dfs_nol;
-	struct dfs_nolelem *nol;
+	struct dfsreq_nolelem *dfs_nol;
 	int nlen;
 
 	/*
@@ -412,8 +418,8 @@ void dfs_nol_update(struct wlan_dfs *dfs)
 	 * returned pointer is 0x10.  Make sure you're aware of this
 	 * when you start debugging.
 	 */
-	dfs_nol = (struct dfs_nol_chan_entry *)qdf_mem_malloc(
-		sizeof(struct dfs_nol_chan_entry) * dfs->dfs_nol_count);
+	dfs_nol = (struct dfsreq_nolelem *)qdf_mem_malloc(
+		sizeof(struct dfsreq_nolelem) * dfs->dfs_nol_count);
 
 	if (!dfs_nol) {
 		/*
@@ -426,18 +432,7 @@ void dfs_nol_update(struct wlan_dfs *dfs)
 		return;
 	}
 
-	/* Populate the nol array. */
-	nlen = 0;
-
-	nol = dfs->dfs_nol;
-	while (nol != NULL && nlen < dfs->dfs_nol_count) {
-		dfs_nol[nlen].nol_chfreq = nol->nol_freq;
-		dfs_nol[nlen].nol_chwidth = nol->nol_chwidth;
-		dfs_nol[nlen].nol_start_ticks = nol->nol_start_ticks;
-		dfs_nol[nlen].nol_timeout_ms = nol->nol_timeout_ms;
-		nlen++;
-		nol = nol->nol_next;
-	}
+	DFS_GET_NOL_LOCKED(dfs, dfs_nol, &nlen);
 
 	/* Be suitably paranoid for now. */
 	if (nlen != dfs->dfs_nol_count)
@@ -460,17 +455,10 @@ void dfs_nol_update(struct wlan_dfs *dfs)
 	qdf_mem_free(dfs_nol);
 }
 
-void dfs_nol_timer_cleanup(struct wlan_dfs *dfs)
+void dfs_nol_free_list(struct wlan_dfs *dfs)
 {
 	struct dfs_nolelem *nol = dfs->dfs_nol, *prev;
 
-	while (nol) {
-		qdf_timer_sync_cancel(&nol->nol_timer);
-		nol = nol->nol_next;
-	}
-
-	/* Free NOL elem, don't mix this while loop with above loop. */
-	nol = dfs->dfs_nol;
 	while (nol) {
 		prev = nol;
 		nol = nol->nol_next;
@@ -483,9 +471,39 @@ void dfs_nol_timer_cleanup(struct wlan_dfs *dfs)
 			ASSERT(0);
 		}
 	}
+
 	dfs->dfs_nol = NULL;
 }
 
+void dfs_nol_timer_cleanup(struct wlan_dfs *dfs)
+{
+	struct dfs_nolelem *nol;
+	os_timer_t *nol_timer_list;
+	uint8_t i;
+
+	nol_timer_list = (os_timer_t *)qdf_mem_malloc(
+			sizeof(os_timer_t) * dfs->dfs_nol_count);
+
+	if (!nol_timer_list) {
+		dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "failed to allocate NOL timer memory!");
+		return;
+	}
+
+	WLAN_DFSNOL_LOCK(dfs);
+	nol = dfs->dfs_nol;
+	for (i = 0; (nol != NULL) && (i < dfs->dfs_nol_count);
+			i++, nol = nol->nol_next)
+		nol_timer_list[i] = nol->nol_timer;
+	WLAN_DFSNOL_UNLOCK(dfs);
+
+	for (i = 0; i < dfs->dfs_nol_count; i++)
+		qdf_timer_sync_cancel(&nol_timer_list[i]);
+
+	DFS_NOL_FREE_LIST_LOCKED(dfs);
+
+	qdf_mem_free(nol_timer_list);
+}
+
 int dfs_get_use_nol(struct wlan_dfs *dfs)
 {
 	return dfs->dfs_use_nol;
@@ -500,7 +518,7 @@ void dfs_getnol(struct wlan_dfs *dfs, void *dfs_nolinfo)
 {
 	struct dfsreq_nolinfo *nolinfo = (struct dfsreq_nolinfo *)dfs_nolinfo;
 
-	dfs_get_nol(dfs, nolinfo->dfs_nol, &(nolinfo->dfs_ch_nchans));
+	DFS_GET_NOL_LOCKED(dfs, nolinfo->dfs_nol, &(nolinfo->dfs_ch_nchans));
 }
 
 void dfs_clear_nolhistory(struct wlan_dfs *dfs)

+ 3 - 2
umac/dfs/core/src/misc/dfs_process_radar_found_ind.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018 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
@@ -146,7 +146,8 @@ static QDF_STATUS dfs_radar_add_to_nol(struct wlan_dfs *dfs,
 			continue;
 		}
 		last_chan = freq_offset->chan_num[i];
-		dfs_nol_addchan(dfs, (uint16_t)freq_offset->freq[i],
+		DFS_NOL_ADD_CHAN_LOCKED(dfs,
+				(uint16_t)freq_offset->freq[i],
 				dfs->wlan_dfs_nol_timeout);
 		nollist[num_ch++] = last_chan;
 		dfs_info(dfs, WLAN_DEBUG_DFS,

+ 3 - 2
umac/dfs/core/src/misc/dfs_zero_cac.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
  * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
  * All rights reserved.
  *
@@ -447,7 +447,7 @@ void dfs_zero_cac_attach(struct wlan_dfs *dfs)
 {
 	dfs->dfs_precac_timeout_override = -1;
 	dfs_zero_cac_timer_init(dfs);
-	PRECAC_LIST_LOCK_INIT(dfs);
+	PRECAC_LIST_LOCK_CREATE(dfs);
 }
 
 /**
@@ -618,6 +618,7 @@ void dfs_deinit_precac_list(struct wlan_dfs *dfs)
 void dfs_zero_cac_detach(struct wlan_dfs *dfs)
 {
 	dfs_deinit_precac_list(dfs);
+	PRECAC_LIST_LOCK_DESTROY(dfs);
 }
 
 uint8_t dfs_get_freq_from_precac_required_list(struct wlan_dfs *dfs,

+ 1 - 1
umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c

@@ -201,7 +201,7 @@ QDF_STATUS wlan_dfs_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev,
 		return QDF_STATUS_E_FAILURE;
 	}
 	utils_dfs_init_nol(pdev);
-	dfs_print_nol(dfs);
+	DFS_PRINT_NOL_LOCKED(dfs);
 
 	return QDF_STATUS_SUCCESS;
 }

+ 7 - 6
umac/dfs/dispatcher/src/wlan_dfs_utils_api.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
@@ -265,7 +265,7 @@ QDF_STATUS utils_dfs_nol_addchan(struct wlan_objmgr_pdev *pdev,
 	if (!dfs)
 		return  QDF_STATUS_E_FAILURE;
 
-	dfs_nol_addchan(dfs, freq, dfs_nol_timeout);
+	DFS_NOL_ADD_CHAN_LOCKED(dfs, freq, dfs_nol_timeout);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -702,7 +702,7 @@ void utils_dfs_init_nol(struct wlan_objmgr_pdev *pdev)
 	if (len > 0) {
 		dfs_set_nol(dfs, dfs_nolinfo.dfs_nol, dfs_nolinfo.num_chans);
 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "nol channels in pld");
-		dfs_print_nol(dfs);
+		DFS_PRINT_NOL_LOCKED(dfs);
 	} else {
 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "no nol in pld");
 	}
@@ -742,7 +742,7 @@ void utils_dfs_save_nol(struct wlan_objmgr_pdev *pdev)
 	}
 
 	qdf_mem_zero(&dfs_nolinfo, sizeof(dfs_nolinfo));
-	dfs_get_nol(dfs, dfs_nolinfo.dfs_nol, &num_chans);
+	DFS_GET_NOL_LOCKED(dfs, dfs_nolinfo.dfs_nol, &num_chans);
 	if (num_chans > 0) {
 
 		if (num_chans > DFS_MAX_NOL_CHANNEL)
@@ -767,7 +767,7 @@ void utils_dfs_print_nol_channels(struct wlan_objmgr_pdev *pdev)
 		return;
 	}
 
-	dfs_print_nol(dfs);
+	DFS_PRINT_NOL_LOCKED(dfs);
 }
 EXPORT_SYMBOL(utils_dfs_print_nol_channels);
 
@@ -782,7 +782,7 @@ void utils_dfs_clear_nol_channels(struct wlan_objmgr_pdev *pdev)
 	}
 
 	/* First print list */
-	dfs_print_nol(dfs);
+	DFS_PRINT_NOL_LOCKED(dfs);
 
 	/* clear local cache first */
 	dfs_nol_timer_cleanup(dfs);
@@ -807,6 +807,7 @@ void utils_dfs_reg_update_nol_ch(struct wlan_objmgr_pdev *pdev,
 		uint8_t num_ch,
 		bool nol_ch)
 {
+	/* TODO : Need locking?*/
 	wlan_reg_update_nol_ch(pdev, ch_list, num_ch, nol_ch);
 }
 EXPORT_SYMBOL(utils_dfs_reg_update_nol_ch);