summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdhar, Mahesh Kumar <c_medhar@qti.qualcomm.com>2015-10-05 14:40:13 +0530
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2015-10-09 14:46:44 +0530
commita7111895c8a1af93cbfecc7784e5ecea828f717f (patch)
tree442e699be3d96947fbcea867223d26e72efe418c
parentc754d456389681cb10e73b409fa497db9356e956 (diff)
qcacld-2.0: synchronize concurrent access of shared variable
Currently DFS variables are accessed in different context without protection leading to NULL pointer dereferences. Ensure lock is taken before accessing the DFS shared variable. Change-Id: Ie78dd50ff4b32ef52f78e2944d175a6c10577882 CRs-Fixed: 910586
-rw-r--r--CORE/SERVICES/COMMON/wma_dfs_interface.h2
-rw-r--r--CORE/SERVICES/DFS/src/dfs.c2
-rw-r--r--CORE/SERVICES/DFS/src/dfs_fcc_bin5.c8
-rw-r--r--CORE/SERVICES/DFS/src/dfs_misc.c11
-rw-r--r--CORE/SERVICES/DFS/src/dfs_phyerr_tlv.c8
-rw-r--r--CORE/SERVICES/DFS/src/dfs_process_phyerr.c32
-rw-r--r--CORE/SERVICES/DFS/src/dfs_process_radarevent.c6
-rw-r--r--CORE/SERVICES/WMA/wma.c42
8 files changed, 86 insertions, 25 deletions
diff --git a/CORE/SERVICES/COMMON/wma_dfs_interface.h b/CORE/SERVICES/COMMON/wma_dfs_interface.h
index 7b601fd33ea6..05c6550391c7 100644
--- a/CORE/SERVICES/COMMON/wma_dfs_interface.h
+++ b/CORE/SERVICES/COMMON/wma_dfs_interface.h
@@ -206,7 +206,7 @@ typedef struct ieee80211com
u_int8_t vdev_id;
u_int8_t last_radar_found_chan;
int32_t dfs_pri_multiplier;
- vos_lock_t chan_lock;
+ adf_os_spinlock_t chan_lock;
} IEEE80211COM, *PIEEE80211COM;
/*
diff --git a/CORE/SERVICES/DFS/src/dfs.c b/CORE/SERVICES/DFS/src/dfs.c
index bf81edff21ae..803e99ecc1d4 100644
--- a/CORE/SERVICES/DFS/src/dfs.c
+++ b/CORE/SERVICES/DFS/src/dfs.c
@@ -174,7 +174,9 @@ static OS_TIMER_FUNC(dfs_task)
*/
OS_CANCEL_TIMER(&dfs->ath_dfstesttimer);
dfs->ath_dfstest = 1;
+ adf_os_spin_lock_bh(&ic->chan_lock);
dfs->ath_dfstest_ieeechan = ic->ic_curchan->ic_ieee;
+ adf_os_spin_unlock_bh(&ic->chan_lock);
dfs->ath_dfstesttime = 1; /* 1ms */
OS_SET_TIMER(&dfs->ath_dfstesttimer, dfs->ath_dfstesttime);
}
diff --git a/CORE/SERVICES/DFS/src/dfs_fcc_bin5.c b/CORE/SERVICES/DFS/src/dfs_fcc_bin5.c
index e41e49f0200d..5e9d2cbd5de2 100644
--- a/CORE/SERVICES/DFS/src/dfs_fcc_bin5.c
+++ b/CORE/SERVICES/DFS/src/dfs_fcc_bin5.c
@@ -102,9 +102,11 @@ dfs_bin5_check_pulse(struct ath_dfs *dfs, struct dfs_event *re,
}
/* Adjust the filter threshold for rssi in non TURBO mode */
+ adf_os_spin_lock_bh(&dfs->ic->chan_lock);
if( ! (dfs->ic->ic_curchan->ic_flags & CHANNEL_TURBO))
b5_rssithresh += br->br_pulse.b5_rssimargin;
+ adf_os_spin_unlock_bh(&dfs->ic->chan_lock);
/*
* Check if the pulse is within duration and rssi
* thresholds.
@@ -524,6 +526,7 @@ dfs_check_chirping_merlin(struct ath_dfs *dfs, void *buf, u_int16_t datalen,
int same_sign;
int temp;
+ adf_os_spin_lock_bh(&dfs->ic->chan_lock);
if (IS_CHAN_HT40(dfs->ic->ic_curchan)) {
num_fft_bytes = NUM_FFT_BYTES_HT40;
num_bin_bytes = NUM_BIN_BYTES_HT40;
@@ -554,6 +557,8 @@ dfs_check_chirping_merlin(struct ath_dfs *dfs, void *buf, u_int16_t datalen,
upper_mag_byte = UPPER_MAG_BYTE_HT20;
}
+ adf_os_spin_unlock_bh(&dfs->ic->chan_lock);
+
ptr = (u_int8_t*)buf;
/*
* sanity check for FFT buffer
@@ -584,6 +589,7 @@ dfs_check_chirping_merlin(struct ath_dfs *dfs, void *buf, u_int16_t datalen,
max_index_lower[i] = ptr[fft_start + lower_index_byte] >> 2;
max_index_upper[i] = (ptr[fft_start + upper_index_byte] >> 2) + num_subchan_bins;
+ adf_os_spin_lock_bh(&dfs->ic->chan_lock);
if (!IS_CHAN_HT40(dfs->ic->ic_curchan)) {
/*
* for HT20 mode indices are 6 bit signed number
@@ -591,6 +597,8 @@ dfs_check_chirping_merlin(struct ath_dfs *dfs, void *buf, u_int16_t datalen,
max_index_lower[i] ^= 0x20;
max_index_upper[i] = 0;
}
+
+ adf_os_spin_unlock_bh(&dfs->ic->chan_lock);
/*
* Reconstruct the maximum magnitude for each sub-channel. Also select
* and flag the max overall magnitude between the two sub-channels.
diff --git a/CORE/SERVICES/DFS/src/dfs_misc.c b/CORE/SERVICES/DFS/src/dfs_misc.c
index a8f8e2b3b595..e02ef6dfe901 100644
--- a/CORE/SERVICES/DFS/src/dfs_misc.c
+++ b/CORE/SERVICES/DFS/src/dfs_misc.c
@@ -106,7 +106,9 @@ dfs_get_pri_margin(struct ath_dfs *dfs, int is_extchan_detect,
else
pri_margin = DFS_DEFAULT_PRI_MARGIN;
+ adf_os_spin_lock_bh(&dfs->ic->chan_lock);
if (IS_CHAN_HT40(dfs->ic->ic_curchan)) {
+ adf_os_spin_unlock_bh(&dfs->ic->chan_lock);
ext_chan_busy = dfs->ic->ic_get_ext_busy(dfs->ic);
if(ext_chan_busy >= 0) {
dfs->dfs_rinfo.ext_chan_busy_ts = dfs->ic->ic_get_TSF64(dfs->ic);
@@ -125,7 +127,10 @@ dfs_get_pri_margin(struct ath_dfs *dfs, int is_extchan_detect,
adjust_pri = adjust_pri_per_chan_busy(ext_chan_busy, pri_margin);
pri_margin -= adjust_pri;
+ } else {
+ adf_os_spin_unlock_bh(&dfs->ic->chan_lock);
}
+
return pri_margin;
}
@@ -140,7 +145,9 @@ int dfs_get_filter_threshold(struct ath_dfs *dfs, struct dfs_filter *rf,
thresh = rf->rf_threshold;
+ adf_os_spin_lock_bh(&dfs->ic->chan_lock);
if (IS_CHAN_HT40(dfs->ic->ic_curchan)) {
+ adf_os_spin_unlock_bh(&dfs->ic->chan_lock);
ext_chan_busy = dfs->ic->ic_get_ext_busy(dfs->ic);
if(ext_chan_busy >= 0) {
dfs->dfs_rinfo.ext_chan_busy_ts = dfs->ic->ic_get_TSF64(dfs->ic);
@@ -167,6 +174,8 @@ int dfs_get_filter_threshold(struct ath_dfs *dfs, struct dfs_filter *rf,
rf->rf_pulseid, ext_chan_busy, adjust_thresh);
thresh += adjust_thresh;
+ } else {
+ adf_os_spin_unlock_bh(&dfs->ic->chan_lock);
}
return thresh;
}
@@ -197,6 +206,7 @@ ieee80211_get_extchan(struct ieee80211com *ic)
} else {
return NULL;
}
+
return(ic->ic_find_channel(ic, ic->ic_curchan->ic_freq + chan_offset, IEEE80211_CHAN_11NA_HT20));
}
@@ -233,6 +243,7 @@ dfs_getchanstate(struct ath_dfs *dfs, u_int8_t *index, int ext_chan_flag)
(dfs->dfs_radar[i].rs_chan.ic_flags == cmp_ch->ic_flags)) {
if (index != NULL)
*index = (u_int8_t) i;
+
return &(dfs->dfs_radar[i]);
}
}
diff --git a/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.c b/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.c
index 9f24e96a1198..a637484dda71 100644
--- a/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.c
+++ b/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.c
@@ -259,6 +259,7 @@ radar_summary_parse(struct ath_dfs *dfs, const char *buf, size_t len,
* Set pulse duration to 20 us
*/
+ adf_os_spin_lock_bh(&dfs->ic->chan_lock);
freq = ieee80211_chan2freq(dfs->ic, dfs->ic->ic_curchan);
freq_centre = dfs->ic->ic_curchan->ic_vhtop_ch_freq_seg1;
@@ -270,6 +271,7 @@ radar_summary_parse(struct ath_dfs *dfs, const char *buf, size_t len,
rsu->pulse_duration = 20;
}
+ adf_os_spin_unlock_bh(&dfs->ic->chan_lock);
}
static void
@@ -446,13 +448,16 @@ tlv_calc_freq_info(struct ath_dfs *dfs, struct rx_radar_status *rs)
DFS_PRINTK("%s: dfs->ic=%p, that or curchan is null?",
__func__, dfs->ic);
return (0);
+ }
+
+ adf_os_spin_lock_bh(&dfs->ic->chan_lock);
/*
* For now, the only 11ac channel with freq1/freq2 setup is
* VHT80.
*
* XXX should have a flag macro to check this!
*/
- } else if (IEEE80211_IS_CHAN_11AC_VHT80(dfs->ic->ic_curchan)) {
+ if (IEEE80211_IS_CHAN_11AC_VHT80(dfs->ic->ic_curchan)) {
/* 11AC, so cfreq1/cfreq2 are setup */
/*
@@ -487,6 +492,7 @@ tlv_calc_freq_info(struct ath_dfs *dfs, struct rx_radar_status *rs)
/* Calculate new _real_ channel centre */
chan_centre += (chan_offset / 2);
}
+ adf_os_spin_unlock_bh(&dfs->ic->chan_lock);
/*
* XXX half/quarter rate support!
diff --git a/CORE/SERVICES/DFS/src/dfs_process_phyerr.c b/CORE/SERVICES/DFS/src/dfs_process_phyerr.c
index 727635c145fb..a5cb6afec4a5 100644
--- a/CORE/SERVICES/DFS/src/dfs_process_phyerr.c
+++ b/CORE/SERVICES/DFS/src/dfs_process_phyerr.c
@@ -103,6 +103,7 @@ dfs_get_event_freqcentre(struct ath_dfs *dfs, int is_pri, int is_ext, int is_dc)
{
struct ieee80211com *ic;
int chan_offset = 0, chan_width;
+ uint16_t freq;
/* Handle edge cases during startup/transition, shouldn't happen! */
if (dfs == NULL)
@@ -119,12 +120,14 @@ dfs_get_event_freqcentre(struct ath_dfs *dfs, int is_pri, int is_ext, int is_dc)
*/
chan_width = dfs_get_event_freqwidth(dfs);
+ adf_os_spin_lock_bh(&ic->chan_lock);
if (IEEE80211_IS_CHAN_11N_HT40PLUS(ic->ic_curchan))
chan_offset = chan_width;
else if (IEEE80211_IS_CHAN_11N_HT40MINUS(ic->ic_curchan))
chan_offset = -chan_width;
else
chan_offset = 0;
+ adf_os_spin_unlock_bh(&ic->chan_lock);
/*
* Check for DC events first - the sowl code may just set all
@@ -134,8 +137,11 @@ dfs_get_event_freqcentre(struct ath_dfs *dfs, int is_pri, int is_ext, int is_dc)
/*
* XXX TODO: Should DC events be considered 40MHz wide here?
*/
- return (ieee80211_chan2freq(ic, ic->ic_curchan) +
+ adf_os_spin_lock_bh(&ic->chan_lock);
+ freq = (ieee80211_chan2freq(ic, ic->ic_curchan) +
(chan_offset / 2));
+ adf_os_spin_unlock_bh(&ic->chan_lock);
+ return freq;
}
/*
@@ -143,15 +149,25 @@ dfs_get_event_freqcentre(struct ath_dfs *dfs, int is_pri, int is_ext, int is_dc)
* The centre frequency for pri events is still ic_freq.
*/
if (is_pri) {
- return (ieee80211_chan2freq(ic, ic->ic_curchan));
+ adf_os_spin_lock_bh(&ic->chan_lock);
+ freq = (ieee80211_chan2freq(ic, ic->ic_curchan));
+ adf_os_spin_unlock_bh(&ic->chan_lock);
+ return freq;
}
if (is_ext) {
- return (ieee80211_chan2freq(ic, ic->ic_curchan) + chan_width);
+ adf_os_spin_lock_bh(&ic->chan_lock);
+ freq = (ieee80211_chan2freq(ic, ic->ic_curchan) + chan_width);
+ adf_os_spin_unlock_bh(&ic->chan_lock);
+ return freq;
}
/* XXX shouldn't get here */
- return (ieee80211_chan2freq(ic, ic->ic_curchan));
+ adf_os_spin_lock_bh(&ic->chan_lock);
+ freq = (ieee80211_chan2freq(ic, ic->ic_curchan));
+ adf_os_spin_unlock_bh(&ic->chan_lock);
+
+ return freq;
}
/*
@@ -545,7 +561,9 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, u_int16_t datalen,
return;
}
+ adf_os_spin_lock_bh(&ic->chan_lock);
if (IEEE80211_IS_CHAN_RADAR(chan)) {
+ adf_os_spin_unlock_bh(&ic->chan_lock);
DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,
"%s: Radar already found in the channel, "
" do not queue radar data\n",
@@ -553,6 +571,7 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, u_int16_t datalen,
return;
}
+ adf_os_spin_unlock_bh(&ic->chan_lock);
dfs->ath_dfs_stats.total_phy_errors++;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
"%s[%d] phyerr %d len %d\n",
@@ -736,7 +755,9 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, u_int16_t datalen,
* for the adaptive radio (AR) pattern matching rather than
* radar detection.
*/
+ adf_os_spin_lock_bh(&ic->chan_lock);
if ((chan->ic_flags & CHANNEL_108G) == CHANNEL_108G) {
+ adf_os_spin_unlock_bh(&ic->chan_lock);
if (!(dfs->dfs_proc_phyerr & DFS_AR_EN)) {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
"%s: DFS_AR_EN not enabled\n",
@@ -778,6 +799,7 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, u_int16_t datalen,
ATH_ARQ_UNLOCK(dfs);
} else {
if (IEEE80211_IS_CHAN_DFS(chan)) {
+ adf_os_spin_unlock_bh(&ic->chan_lock);
if (!(dfs->dfs_proc_phyerr & DFS_RADAR_EN)) {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS3,
"%s: DFS_RADAR_EN not enabled\n",
@@ -868,6 +890,8 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, u_int16_t datalen,
ATH_DFSQ_LOCK(dfs);
STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
ATH_DFSQ_UNLOCK(dfs);
+ } else {
+ adf_os_spin_unlock_bh(&ic->chan_lock);
}
}
diff --git a/CORE/SERVICES/DFS/src/dfs_process_radarevent.c b/CORE/SERVICES/DFS/src/dfs_process_radarevent.c
index 272028bbe652..b8a48ed39a74 100644
--- a/CORE/SERVICES/DFS/src/dfs_process_radarevent.c
+++ b/CORE/SERVICES/DFS/src/dfs_process_radarevent.c
@@ -146,13 +146,16 @@ dfs_process_radarevent(struct ath_dfs *dfs, struct ieee80211_channel *chan)
return 0;
}
pl = dfs->pulses;
+ adf_os_spin_lock_bh(&dfs->ic->chan_lock);
if ( !(IEEE80211_IS_CHAN_DFS(dfs->ic->ic_curchan))) {
+ adf_os_spin_unlock_bh(&dfs->ic->chan_lock);
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "%s: radar event on non-DFS chan",
__func__);
dfs_reset_radarq(dfs);
dfs_reset_alldelaylines(dfs);
return 0;
}
+ adf_os_spin_unlock_bh(&dfs->ic->chan_lock);
#ifndef ATH_DFS_RADAR_DETECTION_ONLY
/* TEST : Simulate radar bang, make sure we add the channel to NOL (bug 29968) */
if (dfs->dfs_bangradar) {
@@ -660,11 +663,14 @@ thischan->ic_freq);
DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,
"Primary channel freq = %u flags=0x%x",
chan->ic_freq, chan->ic_flagext);
+ adf_os_spin_lock_bh(&dfs->ic->chan_lock);
if ((dfs->ic->ic_curchan->ic_freq!= thischan->ic_freq)) {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,
"Ext channel freq = %u flags=0x%x",
thischan->ic_freq, thischan->ic_flagext);
}
+
+ adf_os_spin_unlock_bh(&dfs->ic->chan_lock);
dfs->dfs_phyerr_freq_min = 0x7fffffff;
dfs->dfs_phyerr_freq_max = 0;
dfs->dfs_phyerr_w53_counter = 0;
diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c
index 7c2179d4903f..7c09fdfa06ad 100644
--- a/CORE/SERVICES/WMA/wma.c
+++ b/CORE/SERVICES/WMA/wma.c
@@ -5540,16 +5540,17 @@ static int wma_unified_dfs_radar_rx_event_handler(void *handle,
radar_event = param_tlvs->fixed_param;
- vos_lock_acquire(&ic->chan_lock);
+ adf_os_spin_lock_bh(&ic->chan_lock);
chan = ic->ic_curchan;
+
if (NV_CHANNEL_DFS != vos_nv_getChannelEnabledState(chan->ic_ieee)) {
WMA_LOGE("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS",
__func__, chan->ic_ieee);
- vos_lock_release(&ic->chan_lock);
+ adf_os_spin_unlock_bh(&ic->chan_lock);
return 0;
}
- vos_lock_release(&ic->chan_lock);
+ adf_os_spin_unlock_bh(&ic->chan_lock);
dfs->ath_dfs_stats.total_phy_errors++;
if (dfs->dfs_caps.ath_chip_is_bb_tlv) {
@@ -11177,17 +11178,12 @@ VOS_STATUS wma_vdev_start(tp_wma_handle wma,
return VOS_STATUS_E_FAILURE;
}
- vos_lock_acquire(&wma->dfs_ic->chan_lock);
- if (wma->dfs_ic->ic_curchan)
- {
- OS_FREE(wma->dfs_ic->ic_curchan);
- wma->dfs_ic->ic_curchan = NULL;
- }
+ adf_os_spin_lock_bh(&wma->dfs_ic->chan_lock);
/* provide the current channel to DFS */
wma->dfs_ic->ic_curchan =
wma_dfs_configure_channel(wma->dfs_ic,chan,chanmode,req);
- vos_lock_release(&wma->dfs_ic->chan_lock);
+ adf_os_spin_unlock_bh(&wma->dfs_ic->chan_lock);
wma_unified_dfs_phyerr_filter_offload_enable(wma);
dfs->disable_dfs_ch_switch =
@@ -29082,7 +29078,7 @@ static void wma_dfs_detach(struct ieee80211com *dfs_ic)
{
dfs_detach(dfs_ic);
- vos_lock_destroy(&dfs_ic->chan_lock);
+ adf_os_spinlock_destroy(&dfs_ic->chan_lock);
if (NULL != dfs_ic->ic_curchan) {
OS_FREE(dfs_ic->ic_curchan);
dfs_ic->ic_curchan = NULL;
@@ -31723,7 +31719,7 @@ struct ieee80211com* wma_dfs_attach(struct ieee80211com *dfs_ic)
* and shared DFS code
*/
dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs;
- vos_lock_init(&dfs_ic->chan_lock);
+ adf_os_spinlock_init(&dfs_ic->chan_lock);
/* Initializes DFS Data Structures and queues*/
dfs_attach(dfs_ic);
@@ -31826,16 +31822,19 @@ wma_dfs_configure_channel(struct ieee80211com *dfs_ic,
WMA_LOGE("%s: DFS ic is Invalid",__func__);
return NULL;
}
- dfs_ic->ic_curchan = (struct ieee80211_channel *) OS_MALLOC(NULL,
+
+
+ if (!dfs_ic->ic_curchan) {
+ dfs_ic->ic_curchan = (struct ieee80211_channel *) OS_MALLOC(NULL,
sizeof(struct ieee80211_channel),
GFP_ATOMIC);
- if (dfs_ic->ic_curchan == NULL)
- {
- WMA_LOGE("%s: allocation of dfs_ic->ic_curchan failed %zu",
- __func__,
- sizeof(struct ieee80211_channel));
- return NULL;
+ if (dfs_ic->ic_curchan == NULL) {
+ WMA_LOGE("%s: allocation of dfs_ic->ic_curchan failed %zu",
+ __func__, sizeof(struct ieee80211_channel));
+ return NULL;
+ }
}
+
OS_MEMZERO(dfs_ic->ic_curchan, sizeof (struct ieee80211_channel));
dfs_ic->ic_curchan->ic_ieee = req->chan;
@@ -31985,6 +31984,9 @@ int wma_dfs_indicate_radar(struct ieee80211com *ic,
* But, when DFS test mode is enabled, allow multiple dfs
* radar events to be posted on the same channel.
*/
+
+ adf_os_spin_lock_bh(&ic->chan_lock);
+
if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) ||
( pmac->sap.SapDfsInfo.disable_dfs_ch_switch == VOS_TRUE) )
{
@@ -31998,6 +32000,7 @@ int wma_dfs_indicate_radar(struct ieee80211com *ic,
{
WMA_LOGE("%s:Application triggered channel switch in progress!.. drop radar event indiaction to SAP",
__func__);
+ adf_os_spin_unlock_bh(&ic->chan_lock);
return 0;
}
else
@@ -32016,6 +32019,7 @@ int wma_dfs_indicate_radar(struct ieee80211com *ic,
WMA_LOGE("%s:DFS- WDA_DFS_RADAR_IND Message Posted",__func__);
}
+ adf_os_spin_unlock_bh(&ic->chan_lock);
return 0;
}