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:

committato da
Prakash Dhavali

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;
|
||||
|
Fai riferimento in un nuovo problema
Block a user