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:
Edhar, Mahesh Kumar
2015-10-26 16:53:30 +05:30
committato da Prakash Dhavali
parent e3eaebe339
commit b0319c4725
9 ha cambiato i file con 90 aggiunte e 31 eliminazioni

Vedi File

@@ -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);

Vedi File

@@ -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.

Vedi File

@@ -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;
}

Vedi File

@@ -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!
*/

Vedi File

@@ -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);
}
}

Vedi File

@@ -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;