qcacld-3.0: synchronize concurrent access of shared variable
qcacld-2.0 to qcacld-3.0 propagation 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
This commit is contained in:
parent
e3eaebe339
commit
b0319c4725
@ -169,7 +169,9 @@ static os_timer_func(dfs_task)
|
||||
*/
|
||||
OS_CANCEL_TIMER(&dfs->ath_dfstesttimer);
|
||||
dfs->ath_dfstest = 1;
|
||||
cdf_spin_lock_bh(&ic->chan_lock);
|
||||
dfs->ath_dfstest_ieeechan = ic->ic_curchan->ic_ieee;
|
||||
cdf_spin_unlock_bh(&ic->chan_lock);
|
||||
dfs->ath_dfstesttime = 1; /* 1ms */
|
||||
OS_SET_TIMER(&dfs->ath_dfstesttimer,
|
||||
dfs->ath_dfstesttime);
|
||||
|
@ -99,9 +99,12 @@ dfs_bin5_check_pulse(struct ath_dfs *dfs, struct dfs_event *re,
|
||||
}
|
||||
|
||||
/* Adjust the filter threshold for rssi in non TURBO mode */
|
||||
cdf_spin_lock_bh(&dfs->ic->chan_lock);
|
||||
if (!(dfs->ic->ic_curchan->ic_flags & CHANNEL_TURBO))
|
||||
b5_rssithresh += br->br_pulse.b5_rssimargin;
|
||||
|
||||
cdf_spin_unlock_bh(&dfs->ic->chan_lock);
|
||||
|
||||
/*
|
||||
* Check if the pulse is within duration and rssi
|
||||
* thresholds.
|
||||
@ -560,6 +563,7 @@ dfs_check_chirping_merlin(struct ath_dfs *dfs, void *buf, uint16_t datalen,
|
||||
int same_sign;
|
||||
int temp;
|
||||
|
||||
cdf_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;
|
||||
@ -590,6 +594,7 @@ dfs_check_chirping_merlin(struct ath_dfs *dfs, void *buf, uint16_t datalen,
|
||||
upper_mag_byte = UPPER_MAG_BYTE_HT20;
|
||||
}
|
||||
|
||||
cdf_spin_unlock_bh(&dfs->ic->chan_lock);
|
||||
ptr = (uint8_t *) buf;
|
||||
/*
|
||||
* sanity check for FFT buffer
|
||||
@ -625,6 +630,7 @@ dfs_check_chirping_merlin(struct ath_dfs *dfs, void *buf, uint16_t datalen,
|
||||
max_index_upper[i] =
|
||||
(ptr[fft_start + upper_index_byte] >> 2) + num_subchan_bins;
|
||||
|
||||
cdf_spin_lock_bh(&dfs->ic->chan_lock);
|
||||
if (!IS_CHAN_HT40(dfs->ic->ic_curchan)) {
|
||||
/*
|
||||
* for HT20 mode indices are 6 bit signed number
|
||||
@ -632,6 +638,8 @@ dfs_check_chirping_merlin(struct ath_dfs *dfs, void *buf, uint16_t datalen,
|
||||
max_index_lower[i] ^= 0x20;
|
||||
max_index_upper[i] = 0;
|
||||
}
|
||||
|
||||
cdf_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.
|
||||
|
@ -107,7 +107,9 @@ dfs_get_pri_margin(struct ath_dfs *dfs, int is_extchan_detect,
|
||||
else
|
||||
pri_margin = DFS_DEFAULT_PRI_MARGIN;
|
||||
|
||||
cdf_spin_lock_bh(&dfs->ic->chan_lock);
|
||||
if (IS_CHAN_HT40(dfs->ic->ic_curchan)) {
|
||||
cdf_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 =
|
||||
@ -131,6 +133,8 @@ dfs_get_pri_margin(struct ath_dfs *dfs, int is_extchan_detect,
|
||||
adjust_pri_per_chan_busy(ext_chan_busy, pri_margin);
|
||||
|
||||
pri_margin -= adjust_pri;
|
||||
} else {
|
||||
cdf_spin_unlock_bh(&dfs->ic->chan_lock);
|
||||
}
|
||||
return pri_margin;
|
||||
}
|
||||
@ -146,7 +150,9 @@ int dfs_get_filter_threshold(struct ath_dfs *dfs, struct dfs_filter *rf,
|
||||
|
||||
thresh = rf->rf_threshold;
|
||||
|
||||
cdf_spin_lock_bh(&dfs->ic->chan_lock);
|
||||
if (IS_CHAN_HT40(dfs->ic->ic_curchan)) {
|
||||
cdf_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 =
|
||||
@ -179,6 +185,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 {
|
||||
cdf_spin_unlock_bh(&dfs->ic->chan_lock);
|
||||
}
|
||||
return thresh;
|
||||
}
|
||||
|
@ -228,6 +228,7 @@ radar_summary_parse(struct ath_dfs *dfs, const char *buf, size_t len,
|
||||
* Set pulse duration to 20 us
|
||||
*/
|
||||
|
||||
cdf_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;
|
||||
|
||||
@ -238,6 +239,7 @@ radar_summary_parse(struct ath_dfs *dfs, const char *buf, size_t len,
|
||||
rsu->pulse_duration = 20;
|
||||
}
|
||||
|
||||
cdf_spin_unlock_bh(&dfs->ic->chan_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -435,13 +437,16 @@ static int 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;
|
||||
/*
|
||||
* 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)) {
|
||||
}
|
||||
|
||||
cdf_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!
|
||||
*/
|
||||
if (IEEE80211_IS_CHAN_11AC_VHT80(dfs->ic->ic_curchan)) {
|
||||
/* 11AC, so cfreq1/cfreq2 are setup */
|
||||
|
||||
/*
|
||||
@ -477,6 +482,7 @@ static int tlv_calc_freq_info(struct ath_dfs *dfs, struct rx_radar_status *rs)
|
||||
chan_centre += (chan_offset / 2);
|
||||
}
|
||||
|
||||
cdf_spin_unlock_bh(&dfs->ic->chan_lock);
|
||||
/*
|
||||
* XXX half/quarter rate support!
|
||||
*/
|
||||
|
@ -72,6 +72,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)
|
||||
@ -87,7 +88,7 @@ dfs_get_event_freqcentre(struct ath_dfs *dfs, int is_pri, int is_ext, int is_dc)
|
||||
* based on whether it's an upper or lower channel.
|
||||
*/
|
||||
chan_width = dfs_get_event_freqwidth(dfs);
|
||||
|
||||
cdf_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))
|
||||
@ -95,6 +96,8 @@ dfs_get_event_freqcentre(struct ath_dfs *dfs, int is_pri, int is_ext, int is_dc)
|
||||
else
|
||||
chan_offset = 0;
|
||||
|
||||
cdf_spin_unlock_bh(&ic->chan_lock);
|
||||
|
||||
/*
|
||||
* Check for DC events first - the sowl code may just set all
|
||||
* the bits together..
|
||||
@ -103,22 +106,36 @@ 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) +
|
||||
cdf_spin_lock_bh(&ic->chan_lock);
|
||||
freq = ieee80211_chan2freq(ic, ic->ic_curchan) +
|
||||
(chan_offset / 2);
|
||||
cdf_spin_unlock_bh(&ic->chan_lock);
|
||||
return freq;
|
||||
}
|
||||
|
||||
/*
|
||||
* For non-wide channels, the centre frequency is just ic_freq.
|
||||
* The centre frequency for pri events is still ic_freq.
|
||||
*/
|
||||
if (is_pri)
|
||||
return ieee80211_chan2freq(ic, ic->ic_curchan);
|
||||
if (is_pri) {
|
||||
cdf_spin_lock_bh(&ic->chan_lock);
|
||||
freq = ieee80211_chan2freq(ic, ic->ic_curchan);
|
||||
cdf_spin_unlock_bh(&ic->chan_lock);
|
||||
return freq;
|
||||
}
|
||||
|
||||
if (is_ext)
|
||||
return ieee80211_chan2freq(ic, ic->ic_curchan) + chan_width;
|
||||
if (is_ext) {
|
||||
cdf_spin_lock_bh(&ic->chan_lock);
|
||||
freq = ieee80211_chan2freq(ic, ic->ic_curchan) + chan_width;
|
||||
cdf_spin_unlock_bh(&ic->chan_lock);
|
||||
return freq;
|
||||
}
|
||||
|
||||
/* XXX shouldn't get here */
|
||||
return ieee80211_chan2freq(ic, ic->ic_curchan);
|
||||
cdf_spin_lock_bh(&ic->chan_lock);
|
||||
freq = ieee80211_chan2freq(ic, ic->ic_curchan);
|
||||
cdf_spin_unlock_bh(&ic->chan_lock);
|
||||
return freq;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -497,13 +514,16 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen,
|
||||
return;
|
||||
}
|
||||
|
||||
cdf_spin_lock_bh(&ic->chan_lock);
|
||||
if (IEEE80211_IS_CHAN_RADAR(chan)) {
|
||||
cdf_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", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
cdf_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",
|
||||
@ -691,7 +711,9 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen,
|
||||
* for the adaptive radio (AR) pattern matching rather than
|
||||
* radar detection.
|
||||
*/
|
||||
cdf_spin_lock_bh(&ic->chan_lock);
|
||||
if ((chan->ic_flags & CHANNEL_108G) == CHANNEL_108G) {
|
||||
cdf_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", __func__);
|
||||
@ -732,6 +754,7 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen,
|
||||
ATH_ARQ_UNLOCK(dfs);
|
||||
} else {
|
||||
if (IEEE80211_IS_CHAN_DFS(chan)) {
|
||||
cdf_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",
|
||||
@ -824,6 +847,8 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen,
|
||||
ATH_DFSQ_LOCK(dfs);
|
||||
STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
|
||||
ATH_DFSQ_UNLOCK(dfs);
|
||||
} else {
|
||||
cdf_spin_unlock_bh(&ic->chan_lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,13 +140,17 @@ int dfs_process_radarevent(struct ath_dfs *dfs, struct ieee80211_channel *chan)
|
||||
return 0;
|
||||
}
|
||||
pl = dfs->pulses;
|
||||
cdf_spin_lock_bh(&dfs->ic->chan_lock);
|
||||
if (!(IEEE80211_IS_CHAN_DFS(dfs->ic->ic_curchan))) {
|
||||
cdf_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;
|
||||
}
|
||||
|
||||
cdf_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) {
|
||||
@ -781,11 +785,15 @@ dfsfound:
|
||||
DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,
|
||||
"Primary channel freq = %u flags=0x%x",
|
||||
chan->ic_freq, chan->ic_flagext);
|
||||
cdf_spin_lock_bh(&dfs->ic->chan_lock);
|
||||
if ((dfs->ic->ic_curchan->ic_freq != thischan->ic_freq)) {
|
||||
cdf_spin_unlock_bh(&dfs->ic->chan_lock);
|
||||
DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,
|
||||
"Ext channel freq = %u flags=0x%x",
|
||||
thischan->ic_freq, thischan->ic_flagext);
|
||||
}
|
||||
|
||||
cdf_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;
|
||||
|
@ -232,7 +232,7 @@ typedef struct ieee80211com {
|
||||
uint8_t vdev_id;
|
||||
uint8_t last_radar_found_chan;
|
||||
int32_t dfs_pri_multiplier;
|
||||
cdf_mutex_t chan_lock;
|
||||
cdf_spinlock_t chan_lock;
|
||||
} IEEE80211COM, *PIEEE80211COM;
|
||||
|
||||
/**
|
||||
|
@ -2050,17 +2050,13 @@ CDF_STATUS wma_vdev_start(tp_wma_handle wma,
|
||||
return CDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
cdf_mutex_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;
|
||||
}
|
||||
cdf_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);
|
||||
cdf_mutex_release(&wma->dfs_ic->chan_lock);
|
||||
cdf_spin_unlock_bh(&wma->dfs_ic->chan_lock);
|
||||
|
||||
wma_unified_dfs_phyerr_filter_offload_enable(wma);
|
||||
dfs->disable_dfs_ch_switch =
|
||||
|
@ -1732,17 +1732,17 @@ static int wma_unified_dfs_radar_rx_event_handler(void *handle,
|
||||
|
||||
radar_event = param_tlvs->fixed_param;
|
||||
|
||||
cdf_mutex_acquire(&ic->chan_lock);
|
||||
cdf_spin_lock_bh(&ic->chan_lock);
|
||||
chan = ic->ic_curchan;
|
||||
if (CHANNEL_STATE_DFS != cds_get_channel_state(chan->ic_ieee)) {
|
||||
WMA_LOGE
|
||||
("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS",
|
||||
__func__, chan->ic_ieee);
|
||||
cdf_mutex_release(&ic->chan_lock);
|
||||
cdf_spin_unlock_bh(&ic->chan_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cdf_mutex_release(&ic->chan_lock);
|
||||
cdf_spin_unlock_bh(&ic->chan_lock);
|
||||
dfs->ath_dfs_stats.total_phy_errors++;
|
||||
|
||||
if (dfs->dfs_caps.ath_chip_is_bb_tlv) {
|
||||
@ -6625,7 +6625,7 @@ struct ieee80211com *wma_dfs_attach(struct ieee80211com *dfs_ic)
|
||||
* and shared DFS code
|
||||
*/
|
||||
dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs;
|
||||
cdf_mutex_init(&dfs_ic->chan_lock);
|
||||
cdf_spinlock_init(&dfs_ic->chan_lock);
|
||||
/* Initializes DFS Data Structures and queues */
|
||||
dfs_attach(dfs_ic);
|
||||
|
||||
@ -6642,7 +6642,7 @@ void wma_dfs_detach(struct ieee80211com *dfs_ic)
|
||||
{
|
||||
dfs_detach(dfs_ic);
|
||||
|
||||
cdf_mutex_destroy(&dfs_ic->chan_lock);
|
||||
cdf_spinlock_destroy(&dfs_ic->chan_lock);
|
||||
if (NULL != dfs_ic->ic_curchan) {
|
||||
OS_FREE(dfs_ic->ic_curchan);
|
||||
dfs_ic->ic_curchan = NULL;
|
||||
@ -6757,14 +6757,18 @@ struct ieee80211_channel *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;
|
||||
@ -6916,6 +6920,7 @@ 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.
|
||||
*/
|
||||
cdf_spin_lock_bh(&ic->chan_lock);
|
||||
if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) ||
|
||||
(pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) {
|
||||
wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee;
|
||||
@ -6937,6 +6942,7 @@ int wma_dfs_indicate_radar(struct ieee80211com *ic,
|
||||
wma_send_msg(wma, WMA_DFS_RADAR_IND, (void *)radar_event, 0);
|
||||
WMA_LOGE("%s:DFS- WMA_DFS_RADAR_IND Message Posted", __func__);
|
||||
}
|
||||
cdf_spin_unlock_bh(&ic->chan_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user