You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
This commit is contained in:
@@ -161,6 +161,8 @@ struct ath_common {
|
||||
bool btcoex_enabled;
|
||||
bool disable_ani;
|
||||
bool bt_ant_diversity;
|
||||
|
||||
int last_rssi;
|
||||
};
|
||||
|
||||
struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
|
||||
|
||||
@@ -204,7 +204,7 @@ static void process_rx_rates(struct ath10k *ar, struct htt_rx_info *info,
|
||||
break;
|
||||
/* 80MHZ */
|
||||
case 2:
|
||||
status->flag |= RX_FLAG_80MHZ;
|
||||
status->vht_flag |= RX_VHT_FLAG_80MHZ;
|
||||
}
|
||||
|
||||
status->flag |= RX_FLAG_VHT;
|
||||
@@ -266,7 +266,7 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info)
|
||||
status->flag & RX_FLAG_HT ? "ht" : "",
|
||||
status->flag & RX_FLAG_VHT ? "vht" : "",
|
||||
status->flag & RX_FLAG_40MHZ ? "40" : "",
|
||||
status->flag & RX_FLAG_80MHZ ? "80" : "",
|
||||
status->vht_flag & RX_VHT_FLAG_80MHZ ? "80" : "",
|
||||
status->flag & RX_FLAG_SHORT_GI ? "sgi " : "",
|
||||
status->rate_idx,
|
||||
status->vht_nss,
|
||||
|
||||
@@ -790,7 +790,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
|
||||
if (nw_type & ADHOC_NETWORK) {
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n",
|
||||
nw_type & ADHOC_CREATOR ? "creator" : "joiner");
|
||||
cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
|
||||
cfg80211_ibss_joined(vif->ndev, bssid, chan, GFP_KERNEL);
|
||||
cfg80211_put_bss(ar->wiphy, bss);
|
||||
return;
|
||||
}
|
||||
@@ -861,13 +861,9 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
|
||||
}
|
||||
|
||||
if (vif->nw_type & ADHOC_NETWORK) {
|
||||
if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) {
|
||||
if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC)
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
|
||||
"%s: ath6k not in ibss mode\n", __func__);
|
||||
return;
|
||||
}
|
||||
memset(bssid, 0, ETH_ALEN);
|
||||
cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3256,6 +3252,15 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
||||
struct ath6kl_vif *vif = netdev_priv(dev);
|
||||
u16 interval;
|
||||
int ret, rssi_thold;
|
||||
int n_match_sets = request->n_match_sets;
|
||||
|
||||
/*
|
||||
* If there's a matchset w/o an SSID, then assume it's just for
|
||||
* the RSSI (nothing else is currently supported) and ignore it.
|
||||
* The device only supports a global RSSI filter that we set below.
|
||||
*/
|
||||
if (n_match_sets == 1 && !request->match_sets[0].ssid.ssid_len)
|
||||
n_match_sets = 0;
|
||||
|
||||
if (ar->state != ATH6KL_STATE_ON)
|
||||
return -EIO;
|
||||
@@ -3268,11 +3273,11 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
||||
ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
|
||||
request->n_ssids,
|
||||
request->match_sets,
|
||||
request->n_match_sets);
|
||||
n_match_sets);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!request->n_match_sets) {
|
||||
if (!n_match_sets) {
|
||||
ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
ALL_BSS_FILTER, 0);
|
||||
if (ret < 0)
|
||||
@@ -3286,12 +3291,12 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
||||
|
||||
if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
|
||||
ar->fw_capabilities)) {
|
||||
if (request->rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
|
||||
if (request->min_rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
|
||||
rssi_thold = 0;
|
||||
else if (request->rssi_thold < -127)
|
||||
else if (request->min_rssi_thold < -127)
|
||||
rssi_thold = -127;
|
||||
else
|
||||
rssi_thold = request->rssi_thold;
|
||||
rssi_thold = request->min_rssi_thold;
|
||||
|
||||
ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
rssi_thold);
|
||||
|
||||
@@ -120,18 +120,6 @@ config ATH9K_WOW
|
||||
This option enables Wake on Wireless LAN support for certain cards.
|
||||
Currently, AR9462 is supported.
|
||||
|
||||
config ATH9K_LEGACY_RATE_CONTROL
|
||||
bool "Atheros ath9k rate control"
|
||||
depends on ATH9K
|
||||
default n
|
||||
---help---
|
||||
Say Y, if you want to use the ath9k specific rate control
|
||||
module instead of minstrel_ht. Be warned that there are various
|
||||
issues with the ath9k RC and minstrel is a more robust algorithm.
|
||||
Note that even if this option is selected, "ath9k_rate_control"
|
||||
has to be passed to mac80211 using the module parameter,
|
||||
ieee80211_default_rc_algo.
|
||||
|
||||
config ATH9K_RFKILL
|
||||
bool "Atheros ath9k rfkill support" if EXPERT
|
||||
depends on ATH9K
|
||||
|
||||
@@ -8,7 +8,6 @@ ath9k-y += beacon.o \
|
||||
antenna.o
|
||||
|
||||
ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o
|
||||
ath9k-$(CONFIG_ATH9K_LEGACY_RATE_CONTROL) += rc.o
|
||||
ath9k-$(CONFIG_ATH9K_PCI) += pci.o
|
||||
ath9k-$(CONFIG_ATH9K_AHB) += ahb.o
|
||||
ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o
|
||||
|
||||
@@ -23,10 +23,11 @@
|
||||
#define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT
|
||||
#define MAX_MAG_DELTA 11
|
||||
#define MAX_PHS_DELTA 10
|
||||
#define MAXIQCAL 3
|
||||
|
||||
struct coeff {
|
||||
int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
|
||||
int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
|
||||
int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
|
||||
int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
|
||||
int iqc_coeff[2];
|
||||
};
|
||||
|
||||
@@ -655,9 +656,6 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
|
||||
if (i2_m_q2_a0_d1 > 0x800)
|
||||
i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1);
|
||||
|
||||
if (i2_p_q2_a0_d1 > 0x1000)
|
||||
i2_p_q2_a0_d1 = -((0x1fff - i2_p_q2_a0_d1) + 1);
|
||||
|
||||
if (iq_corr_a0_d1 > 0x800)
|
||||
iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1);
|
||||
|
||||
@@ -800,7 +798,7 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
|
||||
if (q_q_coff > 63)
|
||||
q_q_coff = 63;
|
||||
|
||||
iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
|
||||
iqc_coeff[0] = (q_q_coff * 128) + (0x7f & q_i_coff);
|
||||
|
||||
ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n",
|
||||
chain_idx, iqc_coeff[0]);
|
||||
@@ -831,7 +829,7 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
|
||||
if (q_q_coff > 63)
|
||||
q_q_coff = 63;
|
||||
|
||||
iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
|
||||
iqc_coeff[1] = (q_q_coff * 128) + (0x7f & q_i_coff);
|
||||
|
||||
ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n",
|
||||
chain_idx, iqc_coeff[1]);
|
||||
@@ -839,7 +837,8 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
|
||||
static void ar9003_hw_detect_outlier(int mp_coeff[][MAXIQCAL],
|
||||
int nmeasurement,
|
||||
int max_delta)
|
||||
{
|
||||
int mp_max = -64, max_idx = 0;
|
||||
@@ -848,20 +847,20 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
|
||||
|
||||
/* find min/max mismatch across all calibrated gains */
|
||||
for (i = 0; i < nmeasurement; i++) {
|
||||
if (mp_coeff[i] > mp_max) {
|
||||
mp_max = mp_coeff[i];
|
||||
if (mp_coeff[i][0] > mp_max) {
|
||||
mp_max = mp_coeff[i][0];
|
||||
max_idx = i;
|
||||
} else if (mp_coeff[i] < mp_min) {
|
||||
mp_min = mp_coeff[i];
|
||||
} else if (mp_coeff[i][0] < mp_min) {
|
||||
mp_min = mp_coeff[i][0];
|
||||
min_idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* find average (exclude max abs value) */
|
||||
for (i = 0; i < nmeasurement; i++) {
|
||||
if ((abs(mp_coeff[i]) < abs(mp_max)) ||
|
||||
(abs(mp_coeff[i]) < abs(mp_min))) {
|
||||
mp_avg += mp_coeff[i];
|
||||
if ((abs(mp_coeff[i][0]) < abs(mp_max)) ||
|
||||
(abs(mp_coeff[i][0]) < abs(mp_min))) {
|
||||
mp_avg += mp_coeff[i][0];
|
||||
mp_count++;
|
||||
}
|
||||
}
|
||||
@@ -873,7 +872,7 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
|
||||
if (mp_count)
|
||||
mp_avg /= mp_count;
|
||||
else
|
||||
mp_avg = mp_coeff[nmeasurement - 1];
|
||||
mp_avg = mp_coeff[nmeasurement - 1][0];
|
||||
|
||||
/* detect outlier */
|
||||
if (abs(mp_max - mp_min) > max_delta) {
|
||||
@@ -882,15 +881,16 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
|
||||
else
|
||||
outlier_idx = min_idx;
|
||||
|
||||
mp_coeff[outlier_idx] = mp_avg;
|
||||
mp_coeff[outlier_idx][0] = mp_avg;
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
|
||||
struct coeff *coeff,
|
||||
bool is_reusable)
|
||||
static void ar9003_hw_tx_iq_cal_outlier_detection(struct ath_hw *ah,
|
||||
struct coeff *coeff,
|
||||
bool is_reusable)
|
||||
{
|
||||
int i, im, nmeasurement;
|
||||
int magnitude, phase;
|
||||
u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
|
||||
struct ath9k_hw_cal_data *caldata = ah->caldata;
|
||||
|
||||
@@ -920,21 +920,30 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
|
||||
if (nmeasurement > MAX_MEASUREMENT)
|
||||
nmeasurement = MAX_MEASUREMENT;
|
||||
|
||||
/* detect outlier only if nmeasurement > 1 */
|
||||
if (nmeasurement > 1) {
|
||||
/* Detect magnitude outlier */
|
||||
ar9003_hw_detect_outlier(coeff->mag_coeff[i],
|
||||
nmeasurement, MAX_MAG_DELTA);
|
||||
/*
|
||||
* Skip normal outlier detection for AR9550.
|
||||
*/
|
||||
if (!AR_SREV_9550(ah)) {
|
||||
/* detect outlier only if nmeasurement > 1 */
|
||||
if (nmeasurement > 1) {
|
||||
/* Detect magnitude outlier */
|
||||
ar9003_hw_detect_outlier(coeff->mag_coeff[i],
|
||||
nmeasurement,
|
||||
MAX_MAG_DELTA);
|
||||
|
||||
/* Detect phase outlier */
|
||||
ar9003_hw_detect_outlier(coeff->phs_coeff[i],
|
||||
nmeasurement, MAX_PHS_DELTA);
|
||||
/* Detect phase outlier */
|
||||
ar9003_hw_detect_outlier(coeff->phs_coeff[i],
|
||||
nmeasurement,
|
||||
MAX_PHS_DELTA);
|
||||
}
|
||||
}
|
||||
|
||||
for (im = 0; im < nmeasurement; im++) {
|
||||
magnitude = coeff->mag_coeff[i][im][0];
|
||||
phase = coeff->phs_coeff[i][im][0];
|
||||
|
||||
coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
|
||||
((coeff->phs_coeff[i][im] & 0x7f) << 7);
|
||||
coeff->iqc_coeff[0] =
|
||||
(phase & 0x7f) | ((magnitude & 0x7f) << 7);
|
||||
|
||||
if ((im % 2) == 0)
|
||||
REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
|
||||
@@ -991,7 +1000,63 @@ static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
|
||||
static void __ar955x_tx_iq_cal_sort(struct ath_hw *ah,
|
||||
struct coeff *coeff,
|
||||
int i, int nmeasurement)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int im, ix, iy, temp;
|
||||
|
||||
for (im = 0; im < nmeasurement; im++) {
|
||||
for (ix = 0; ix < MAXIQCAL - 1; ix++) {
|
||||
for (iy = ix + 1; iy <= MAXIQCAL - 1; iy++) {
|
||||
if (coeff->mag_coeff[i][im][iy] <
|
||||
coeff->mag_coeff[i][im][ix]) {
|
||||
temp = coeff->mag_coeff[i][im][ix];
|
||||
coeff->mag_coeff[i][im][ix] =
|
||||
coeff->mag_coeff[i][im][iy];
|
||||
coeff->mag_coeff[i][im][iy] = temp;
|
||||
}
|
||||
if (coeff->phs_coeff[i][im][iy] <
|
||||
coeff->phs_coeff[i][im][ix]) {
|
||||
temp = coeff->phs_coeff[i][im][ix];
|
||||
coeff->phs_coeff[i][im][ix] =
|
||||
coeff->phs_coeff[i][im][iy];
|
||||
coeff->phs_coeff[i][im][iy] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
coeff->mag_coeff[i][im][0] = coeff->mag_coeff[i][im][MAXIQCAL / 2];
|
||||
coeff->phs_coeff[i][im][0] = coeff->phs_coeff[i][im][MAXIQCAL / 2];
|
||||
|
||||
ath_dbg(common, CALIBRATE,
|
||||
"IQCAL: Median [ch%d][gain%d]: mag = %d phase = %d\n",
|
||||
i, im,
|
||||
coeff->mag_coeff[i][im][0],
|
||||
coeff->phs_coeff[i][im][0]);
|
||||
}
|
||||
}
|
||||
|
||||
static bool ar955x_tx_iq_cal_median(struct ath_hw *ah,
|
||||
struct coeff *coeff,
|
||||
int iqcal_idx,
|
||||
int nmeasurement)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((iqcal_idx + 1) != MAXIQCAL)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
__ar955x_tx_iq_cal_sort(ah, coeff, i, nmeasurement);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah,
|
||||
int iqcal_idx,
|
||||
bool is_reusable)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
|
||||
@@ -1004,10 +1069,11 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
|
||||
AR_PHY_CHAN_INFO_TAB_1,
|
||||
AR_PHY_CHAN_INFO_TAB_2,
|
||||
};
|
||||
struct coeff coeff;
|
||||
static struct coeff coeff;
|
||||
s32 iq_res[6];
|
||||
int i, im, j;
|
||||
int nmeasurement;
|
||||
int nmeasurement = 0;
|
||||
bool outlier_detect = true;
|
||||
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
if (!(ah->txchainmask & (1 << i)))
|
||||
@@ -1065,17 +1131,23 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
|
||||
goto tx_iqcal_fail;
|
||||
}
|
||||
|
||||
coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
|
||||
coeff.phs_coeff[i][im] =
|
||||
coeff.phs_coeff[i][im][iqcal_idx] =
|
||||
coeff.iqc_coeff[0] & 0x7f;
|
||||
coeff.mag_coeff[i][im][iqcal_idx] =
|
||||
(coeff.iqc_coeff[0] >> 7) & 0x7f;
|
||||
|
||||
if (coeff.mag_coeff[i][im] > 63)
|
||||
coeff.mag_coeff[i][im] -= 128;
|
||||
if (coeff.phs_coeff[i][im] > 63)
|
||||
coeff.phs_coeff[i][im] -= 128;
|
||||
if (coeff.mag_coeff[i][im][iqcal_idx] > 63)
|
||||
coeff.mag_coeff[i][im][iqcal_idx] -= 128;
|
||||
if (coeff.phs_coeff[i][im][iqcal_idx] > 63)
|
||||
coeff.phs_coeff[i][im][iqcal_idx] -= 128;
|
||||
}
|
||||
}
|
||||
ar9003_hw_tx_iqcal_load_avg_2_passes(ah, &coeff, is_reusable);
|
||||
|
||||
if (AR_SREV_9550(ah))
|
||||
outlier_detect = ar955x_tx_iq_cal_median(ah, &coeff,
|
||||
iqcal_idx, nmeasurement);
|
||||
if (outlier_detect)
|
||||
ar9003_hw_tx_iq_cal_outlier_detection(ah, &coeff, is_reusable);
|
||||
|
||||
return;
|
||||
|
||||
@@ -1409,7 +1481,7 @@ skip_tx_iqcal:
|
||||
}
|
||||
|
||||
if (txiqcal_done)
|
||||
ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
|
||||
ar9003_hw_tx_iq_cal_post_proc(ah, 0, is_reusable);
|
||||
else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags))
|
||||
ar9003_hw_tx_iq_cal_reload(ah);
|
||||
|
||||
@@ -1455,14 +1527,38 @@ skip_tx_iqcal:
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool do_ar9003_agc_cal(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
bool status;
|
||||
|
||||
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
|
||||
REG_READ(ah, AR_PHY_AGC_CONTROL) |
|
||||
AR_PHY_AGC_CONTROL_CAL);
|
||||
|
||||
status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_CAL,
|
||||
0, AH_WAIT_TIMEOUT);
|
||||
if (!status) {
|
||||
ath_dbg(common, CALIBRATE,
|
||||
"offset calibration failed to complete in %d ms,"
|
||||
"noisy environment?\n",
|
||||
AH_WAIT_TIMEOUT / 1000);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_hw_cal_data *caldata = ah->caldata;
|
||||
bool txiqcal_done = false;
|
||||
bool is_reusable = true, status = true;
|
||||
bool status = true;
|
||||
bool run_agc_cal = false, sep_iq_cal = false;
|
||||
int i = 0;
|
||||
|
||||
/* Use chip chainmask only for calibration */
|
||||
ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
|
||||
@@ -1485,7 +1581,12 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
|
||||
* AGC calibration. Specifically, AR9550 in SoC chips.
|
||||
*/
|
||||
if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) {
|
||||
txiqcal_done = true;
|
||||
if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
|
||||
AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL)) {
|
||||
txiqcal_done = true;
|
||||
} else {
|
||||
txiqcal_done = false;
|
||||
}
|
||||
run_agc_cal = true;
|
||||
} else {
|
||||
sep_iq_cal = true;
|
||||
@@ -1512,27 +1613,37 @@ skip_tx_iqcal:
|
||||
if (AR_SREV_9330_11(ah))
|
||||
ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan));
|
||||
|
||||
/* Calibrate the AGC */
|
||||
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
|
||||
REG_READ(ah, AR_PHY_AGC_CONTROL) |
|
||||
AR_PHY_AGC_CONTROL_CAL);
|
||||
/*
|
||||
* For non-AR9550 chips, we just trigger AGC calibration
|
||||
* in the HW, poll for completion and then process
|
||||
* the results.
|
||||
*
|
||||
* For AR955x, we run it multiple times and use
|
||||
* median IQ correction.
|
||||
*/
|
||||
if (!AR_SREV_9550(ah)) {
|
||||
status = do_ar9003_agc_cal(ah);
|
||||
if (!status)
|
||||
return false;
|
||||
|
||||
/* Poll for offset calibration complete */
|
||||
status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_CAL,
|
||||
0, AH_WAIT_TIMEOUT);
|
||||
if (txiqcal_done)
|
||||
ar9003_hw_tx_iq_cal_post_proc(ah, 0, false);
|
||||
} else {
|
||||
if (!txiqcal_done) {
|
||||
status = do_ar9003_agc_cal(ah);
|
||||
if (!status)
|
||||
return false;
|
||||
} else {
|
||||
for (i = 0; i < MAXIQCAL; i++) {
|
||||
status = do_ar9003_agc_cal(ah);
|
||||
if (!status)
|
||||
return false;
|
||||
ar9003_hw_tx_iq_cal_post_proc(ah, i, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
ath_dbg(common, CALIBRATE,
|
||||
"offset calibration failed to complete in %d ms; noisy environment?\n",
|
||||
AH_WAIT_TIMEOUT / 1000);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (txiqcal_done)
|
||||
ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
|
||||
|
||||
/* Revert chainmask to runtime parameters */
|
||||
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "spectral.h"
|
||||
|
||||
struct ath_node;
|
||||
struct ath_rate_table;
|
||||
|
||||
extern struct ieee80211_ops ath9k_ops;
|
||||
extern int ath9k_modparam_nohwcrypt;
|
||||
@@ -150,6 +149,11 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
|
||||
#define IS_CCK_RATE(rate) ((rate >= 0x18) && (rate <= 0x1e))
|
||||
#define IS_OFDM_RATE(rate) ((rate >= 0x8) && (rate <= 0xf))
|
||||
|
||||
enum {
|
||||
WLAN_RC_PHY_OFDM,
|
||||
WLAN_RC_PHY_CCK,
|
||||
};
|
||||
|
||||
struct ath_txq {
|
||||
int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
|
||||
u32 axq_qnum; /* ath9k hardware queue number */
|
||||
@@ -442,7 +446,8 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
|
||||
void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
|
||||
void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
|
||||
void ath9k_set_beacon(struct ath_softc *sc);
|
||||
bool ath9k_csa_is_finished(struct ath_softc *sc);
|
||||
bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif);
|
||||
void ath9k_csa_update(struct ath_softc *sc);
|
||||
|
||||
/*******************/
|
||||
/* Link Monitoring */
|
||||
@@ -757,7 +762,6 @@ struct ath_softc {
|
||||
#endif
|
||||
|
||||
struct ath9k_hw_cal_data caldata;
|
||||
int last_rssi;
|
||||
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
struct ath9k_debug debug;
|
||||
@@ -774,7 +778,6 @@ struct ath_softc {
|
||||
#endif
|
||||
|
||||
struct ath_descdma txsdma;
|
||||
struct ieee80211_vif *csa_vif;
|
||||
|
||||
struct ath_ant_comb ant_comb;
|
||||
u8 ant_tx, ant_rx;
|
||||
|
||||
@@ -292,11 +292,8 @@ static void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
|
||||
(unsigned long long)tsfadjust, avp->av_bslot);
|
||||
}
|
||||
|
||||
bool ath9k_csa_is_finished(struct ath_softc *sc)
|
||||
bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
vif = sc->csa_vif;
|
||||
if (!vif || !vif->csa_active)
|
||||
return false;
|
||||
|
||||
@@ -304,11 +301,23 @@ bool ath9k_csa_is_finished(struct ath_softc *sc)
|
||||
return false;
|
||||
|
||||
ieee80211_csa_finish(vif);
|
||||
|
||||
sc->csa_vif = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ath9k_csa_update_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_softc *sc = data;
|
||||
ath9k_csa_is_finished(sc, vif);
|
||||
}
|
||||
|
||||
void ath9k_csa_update(struct ath_softc *sc)
|
||||
{
|
||||
ieee80211_iterate_active_interfaces(sc->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
ath9k_csa_update_vif,
|
||||
sc);
|
||||
}
|
||||
|
||||
void ath9k_beacon_tasklet(unsigned long data)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *)data;
|
||||
@@ -362,13 +371,13 @@ void ath9k_beacon_tasklet(unsigned long data)
|
||||
return;
|
||||
}
|
||||
|
||||
/* EDMA devices check that in the tx completion function. */
|
||||
if (!edma && ath9k_csa_is_finished(sc))
|
||||
return;
|
||||
|
||||
slot = ath9k_beacon_choose_slot(sc);
|
||||
vif = sc->beacon.bslot[slot];
|
||||
|
||||
/* EDMA devices check that in the tx completion function. */
|
||||
if (!edma && ath9k_csa_is_finished(sc, vif))
|
||||
return;
|
||||
|
||||
if (!vif || !vif->bss_conf.enable_beacon)
|
||||
return;
|
||||
|
||||
|
||||
@@ -27,6 +27,250 @@ MODULE_AUTHOR("Atheros Communications");
|
||||
MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
/* Assumes you've already done the endian to CPU conversion */
|
||||
bool ath9k_cmn_rx_accept(struct ath_common *common,
|
||||
struct ieee80211_hdr *hdr,
|
||||
struct ieee80211_rx_status *rxs,
|
||||
struct ath_rx_status *rx_stats,
|
||||
bool *decrypt_error,
|
||||
unsigned int rxfilter)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
bool is_mc, is_valid_tkip, strip_mic, mic_error;
|
||||
__le16 fc;
|
||||
|
||||
fc = hdr->frame_control;
|
||||
|
||||
is_mc = !!is_multicast_ether_addr(hdr->addr1);
|
||||
is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
|
||||
test_bit(rx_stats->rs_keyix, common->tkip_keymap);
|
||||
strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
|
||||
ieee80211_has_protected(fc) &&
|
||||
!(rx_stats->rs_status &
|
||||
(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
|
||||
ATH9K_RXERR_KEYMISS));
|
||||
|
||||
/*
|
||||
* Key miss events are only relevant for pairwise keys where the
|
||||
* descriptor does contain a valid key index. This has been observed
|
||||
* mostly with CCMP encryption.
|
||||
*/
|
||||
if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID ||
|
||||
!test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
|
||||
rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
|
||||
|
||||
mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
|
||||
!ieee80211_has_morefrags(fc) &&
|
||||
!(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
|
||||
(rx_stats->rs_status & ATH9K_RXERR_MIC);
|
||||
|
||||
/*
|
||||
* The rx_stats->rs_status will not be set until the end of the
|
||||
* chained descriptors so it can be ignored if rs_more is set. The
|
||||
* rs_more will be false at the last element of the chained
|
||||
* descriptors.
|
||||
*/
|
||||
if (rx_stats->rs_status != 0) {
|
||||
u8 status_mask;
|
||||
|
||||
if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
|
||||
rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
|
||||
mic_error = false;
|
||||
}
|
||||
|
||||
if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
|
||||
(!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
|
||||
*decrypt_error = true;
|
||||
mic_error = false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reject error frames with the exception of
|
||||
* decryption and MIC failures. For monitor mode,
|
||||
* we also ignore the CRC error.
|
||||
*/
|
||||
status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
|
||||
ATH9K_RXERR_KEYMISS;
|
||||
|
||||
if (ah->is_monitoring && (rxfilter & FIF_FCSFAIL))
|
||||
status_mask |= ATH9K_RXERR_CRC;
|
||||
|
||||
if (rx_stats->rs_status & ~status_mask)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* For unicast frames the MIC error bit can have false positives,
|
||||
* so all MIC error reports need to be validated in software.
|
||||
* False negatives are not common, so skip software verification
|
||||
* if the hardware considers the MIC valid.
|
||||
*/
|
||||
if (strip_mic)
|
||||
rxs->flag |= RX_FLAG_MMIC_STRIPPED;
|
||||
else if (is_mc && mic_error)
|
||||
rxs->flag |= RX_FLAG_MMIC_ERROR;
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_cmn_rx_accept);
|
||||
|
||||
void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
|
||||
struct sk_buff *skb,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rxs,
|
||||
bool decrypt_error)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
struct ieee80211_hdr *hdr;
|
||||
int hdrlen, padpos, padsize;
|
||||
u8 keyix;
|
||||
__le16 fc;
|
||||
|
||||
/* see if any padding is done by the hw and remove it */
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
fc = hdr->frame_control;
|
||||
padpos = ieee80211_hdrlen(fc);
|
||||
|
||||
/* The MAC header is padded to have 32-bit boundary if the
|
||||
* packet payload is non-zero. The general calculation for
|
||||
* padsize would take into account odd header lengths:
|
||||
* padsize = (4 - padpos % 4) % 4; However, since only
|
||||
* even-length headers are used, padding can only be 0 or 2
|
||||
* bytes and we can optimize this a bit. In addition, we must
|
||||
* not try to remove padding from short control frames that do
|
||||
* not have payload. */
|
||||
padsize = padpos & 3;
|
||||
if (padsize && skb->len>=padpos+padsize+FCS_LEN) {
|
||||
memmove(skb->data + padsize, skb->data, padpos);
|
||||
skb_pull(skb, padsize);
|
||||
}
|
||||
|
||||
keyix = rx_stats->rs_keyix;
|
||||
|
||||
if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error &&
|
||||
ieee80211_has_protected(fc)) {
|
||||
rxs->flag |= RX_FLAG_DECRYPTED;
|
||||
} else if (ieee80211_has_protected(fc)
|
||||
&& !decrypt_error && skb->len >= hdrlen + 4) {
|
||||
keyix = skb->data[hdrlen + 3] >> 6;
|
||||
|
||||
if (test_bit(keyix, common->keymap))
|
||||
rxs->flag |= RX_FLAG_DECRYPTED;
|
||||
}
|
||||
if (ah->sw_mgmt_crypto &&
|
||||
(rxs->flag & RX_FLAG_DECRYPTED) &&
|
||||
ieee80211_is_mgmt(fc))
|
||||
/* Use software decrypt for management frames. */
|
||||
rxs->flag &= ~RX_FLAG_DECRYPTED;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess);
|
||||
|
||||
int ath9k_cmn_process_rate(struct ath_common *common,
|
||||
struct ieee80211_hw *hw,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rxs)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
enum ieee80211_band band;
|
||||
unsigned int i = 0;
|
||||
struct ath_hw *ah = common->ah;
|
||||
|
||||
band = ah->curchan->chan->band;
|
||||
sband = hw->wiphy->bands[band];
|
||||
|
||||
if (IS_CHAN_QUARTER_RATE(ah->curchan))
|
||||
rxs->flag |= RX_FLAG_5MHZ;
|
||||
else if (IS_CHAN_HALF_RATE(ah->curchan))
|
||||
rxs->flag |= RX_FLAG_10MHZ;
|
||||
|
||||
if (rx_stats->rs_rate & 0x80) {
|
||||
/* HT rate */
|
||||
rxs->flag |= RX_FLAG_HT;
|
||||
rxs->flag |= rx_stats->flag;
|
||||
rxs->rate_idx = rx_stats->rs_rate & 0x7f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
if (sband->bitrates[i].hw_value == rx_stats->rs_rate) {
|
||||
rxs->rate_idx = i;
|
||||
return 0;
|
||||
}
|
||||
if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) {
|
||||
rxs->flag |= RX_FLAG_SHORTPRE;
|
||||
rxs->rate_idx = i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_cmn_process_rate);
|
||||
|
||||
void ath9k_cmn_process_rssi(struct ath_common *common,
|
||||
struct ieee80211_hw *hw,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rxs)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
int last_rssi;
|
||||
int rssi = rx_stats->rs_rssi;
|
||||
int i, j;
|
||||
|
||||
/*
|
||||
* RSSI is not available for subframes in an A-MPDU.
|
||||
*/
|
||||
if (rx_stats->rs_moreaggr) {
|
||||
rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the RSSI for the last subframe in an A-MPDU
|
||||
* or an unaggregated frame is valid.
|
||||
*/
|
||||
if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) {
|
||||
rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
|
||||
s8 rssi;
|
||||
|
||||
if (!(ah->rxchainmask & BIT(i)))
|
||||
continue;
|
||||
|
||||
rssi = rx_stats->rs_rssi_ctl[i];
|
||||
if (rssi != ATH9K_RSSI_BAD) {
|
||||
rxs->chains |= BIT(j);
|
||||
rxs->chain_signal[j] = ah->noise + rssi;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update Beacon RSSI, this is used by ANI.
|
||||
*/
|
||||
if (rx_stats->is_mybeacon &&
|
||||
((ah->opmode == NL80211_IFTYPE_STATION) ||
|
||||
(ah->opmode == NL80211_IFTYPE_ADHOC))) {
|
||||
ATH_RSSI_LPF(common->last_rssi, rx_stats->rs_rssi);
|
||||
last_rssi = common->last_rssi;
|
||||
|
||||
if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
|
||||
rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
|
||||
if (rssi < 0)
|
||||
rssi = 0;
|
||||
|
||||
ah->stats.avgbrssi = rssi;
|
||||
}
|
||||
|
||||
rxs->signal = ah->noise + rx_stats->rs_rssi;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_cmn_process_rssi);
|
||||
|
||||
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
@@ -42,6 +42,25 @@
|
||||
#define ATH_EP_RND(x, mul) \
|
||||
(((x) + ((mul)/2)) / (mul))
|
||||
|
||||
bool ath9k_cmn_rx_accept(struct ath_common *common,
|
||||
struct ieee80211_hdr *hdr,
|
||||
struct ieee80211_rx_status *rxs,
|
||||
struct ath_rx_status *rx_stats,
|
||||
bool *decrypt_error,
|
||||
unsigned int rxfilter);
|
||||
void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
|
||||
struct sk_buff *skb,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rxs,
|
||||
bool decrypt_error);
|
||||
int ath9k_cmn_process_rate(struct ath_common *common,
|
||||
struct ieee80211_hw *hw,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rxs);
|
||||
void ath9k_cmn_process_rssi(struct ath_common *common,
|
||||
struct ieee80211_hw *hw,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rxs);
|
||||
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
|
||||
struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw,
|
||||
struct ath_hw *ah,
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#define DEBUG_H
|
||||
|
||||
#include "hw.h"
|
||||
#include "rc.h"
|
||||
#include "dfs_debug.h"
|
||||
|
||||
struct ath_txq;
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
#include "hw.h"
|
||||
|
||||
struct ath_softc;
|
||||
|
||||
/**
|
||||
* struct ath_dfs_stats - DFS Statistics per wiphy
|
||||
* @pulses_total: pulses reported by HW
|
||||
|
||||
@@ -54,6 +54,8 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
|
||||
.driver_info = AR9280_USB }, /* SMC Networks */
|
||||
{ USB_DEVICE(0x0411, 0x017f),
|
||||
.driver_info = AR9280_USB }, /* Sony UWA-BR100 */
|
||||
{ USB_DEVICE(0x0411, 0x0197),
|
||||
.driver_info = AR9280_USB }, /* Buffalo WLI-UV-AG300P */
|
||||
{ USB_DEVICE(0x04da, 0x3904),
|
||||
.driver_info = AR9280_USB },
|
||||
|
||||
|
||||
@@ -277,7 +277,6 @@ struct ath9k_htc_rxbuf {
|
||||
};
|
||||
|
||||
struct ath9k_htc_rx {
|
||||
int last_rssi; /* FIXME: per-STA */
|
||||
struct list_head rxbuf;
|
||||
spinlock_t rxbuflock;
|
||||
};
|
||||
|
||||
@@ -611,6 +611,7 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv)
|
||||
|
||||
memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
|
||||
|
||||
common->last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
priv->ah->opmode = NL80211_IFTYPE_STATION;
|
||||
}
|
||||
|
||||
|
||||
@@ -1474,6 +1474,7 @@ static void ath9k_htc_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
|
||||
|
||||
if ((vif->type == NL80211_IFTYPE_STATION) && bss_conf->assoc) {
|
||||
common->curaid = bss_conf->aid;
|
||||
common->last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -927,43 +927,39 @@ void ath9k_host_rx_init(struct ath9k_htc_priv *priv)
|
||||
ath9k_hw_rxena(priv->ah);
|
||||
ath9k_htc_opmode_init(priv);
|
||||
ath9k_hw_startpcureceive(priv->ah, test_bit(OP_SCANNING, &priv->op_flags));
|
||||
priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
}
|
||||
|
||||
static void ath9k_process_rate(struct ieee80211_hw *hw,
|
||||
struct ieee80211_rx_status *rxs,
|
||||
u8 rx_rate, u8 rs_flags)
|
||||
static inline void convert_htc_flag(struct ath_rx_status *rx_stats,
|
||||
struct ath_htc_rx_status *rxstatus)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
enum ieee80211_band band;
|
||||
unsigned int i = 0;
|
||||
rx_stats->flag = 0;
|
||||
if (rxstatus->rs_flags & ATH9K_RX_2040)
|
||||
rx_stats->flag |= RX_FLAG_40MHZ;
|
||||
if (rxstatus->rs_flags & ATH9K_RX_GI)
|
||||
rx_stats->flag |= RX_FLAG_SHORT_GI;
|
||||
}
|
||||
|
||||
if (rx_rate & 0x80) {
|
||||
/* HT rate */
|
||||
rxs->flag |= RX_FLAG_HT;
|
||||
if (rs_flags & ATH9K_RX_2040)
|
||||
rxs->flag |= RX_FLAG_40MHZ;
|
||||
if (rs_flags & ATH9K_RX_GI)
|
||||
rxs->flag |= RX_FLAG_SHORT_GI;
|
||||
rxs->rate_idx = rx_rate & 0x7f;
|
||||
return;
|
||||
}
|
||||
static void rx_status_htc_to_ath(struct ath_rx_status *rx_stats,
|
||||
struct ath_htc_rx_status *rxstatus)
|
||||
{
|
||||
rx_stats->rs_datalen = rxstatus->rs_datalen;
|
||||
rx_stats->rs_status = rxstatus->rs_status;
|
||||
rx_stats->rs_phyerr = rxstatus->rs_phyerr;
|
||||
rx_stats->rs_rssi = rxstatus->rs_rssi;
|
||||
rx_stats->rs_keyix = rxstatus->rs_keyix;
|
||||
rx_stats->rs_rate = rxstatus->rs_rate;
|
||||
rx_stats->rs_antenna = rxstatus->rs_antenna;
|
||||
rx_stats->rs_more = rxstatus->rs_more;
|
||||
|
||||
band = hw->conf.chandef.chan->band;
|
||||
sband = hw->wiphy->bands[band];
|
||||
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
if (sband->bitrates[i].hw_value == rx_rate) {
|
||||
rxs->rate_idx = i;
|
||||
return;
|
||||
}
|
||||
if (sband->bitrates[i].hw_value_short == rx_rate) {
|
||||
rxs->rate_idx = i;
|
||||
rxs->flag |= RX_FLAG_SHORTPRE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
memcpy(rx_stats->rs_rssi_ctl, rxstatus->rs_rssi_ctl,
|
||||
sizeof(rx_stats->rs_rssi_ctl));
|
||||
memcpy(rx_stats->rs_rssi_ext, rxstatus->rs_rssi_ext,
|
||||
sizeof(rx_stats->rs_rssi_ext));
|
||||
|
||||
rx_stats->rs_isaggr = rxstatus->rs_isaggr;
|
||||
rx_stats->rs_moreaggr = rxstatus->rs_moreaggr;
|
||||
rx_stats->rs_num_delims = rxstatus->rs_num_delims;
|
||||
convert_htc_flag(rx_stats, rxstatus);
|
||||
}
|
||||
|
||||
static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
|
||||
@@ -975,10 +971,10 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_hw *hw = priv->hw;
|
||||
struct sk_buff *skb = rxbuf->skb;
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
struct ath_hw *ah = common->ah;
|
||||
struct ath_htc_rx_status *rxstatus;
|
||||
int hdrlen, padsize;
|
||||
int last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
__le16 fc;
|
||||
struct ath_rx_status rx_stats;
|
||||
bool decrypt_error;
|
||||
|
||||
if (skb->len < HTC_RX_FRAME_HEADER_SIZE) {
|
||||
ath_err(common, "Corrupted RX frame, dropping (len: %d)\n",
|
||||
@@ -999,103 +995,39 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
|
||||
ath9k_htc_err_stat_rx(priv, rxstatus);
|
||||
|
||||
/* Get the RX status information */
|
||||
memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE);
|
||||
skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
fc = hdr->frame_control;
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
|
||||
padsize = hdrlen & 3;
|
||||
if (padsize && skb->len >= hdrlen+padsize+FCS_LEN) {
|
||||
memmove(skb->data + padsize, skb->data, hdrlen);
|
||||
skb_pull(skb, padsize);
|
||||
}
|
||||
|
||||
memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
|
||||
|
||||
if (rxbuf->rxstatus.rs_status != 0) {
|
||||
if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_CRC)
|
||||
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
|
||||
if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_PHY)
|
||||
goto rx_next;
|
||||
/* Copy everything from ath_htc_rx_status (HTC_RX_FRAME_HEADER).
|
||||
* After this, we can drop this part of skb. */
|
||||
rx_status_htc_to_ath(&rx_stats, rxstatus);
|
||||
rx_status->mactime = be64_to_cpu(rxstatus->rs_tstamp);
|
||||
skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);
|
||||
|
||||
if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_DECRYPT) {
|
||||
/* FIXME */
|
||||
} else if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_MIC) {
|
||||
if (ieee80211_is_ctl(fc))
|
||||
/*
|
||||
* Sometimes, we get invalid
|
||||
* MIC failures on valid control frames.
|
||||
* Remove these mic errors.
|
||||
*/
|
||||
rxbuf->rxstatus.rs_status &= ~ATH9K_RXERR_MIC;
|
||||
else
|
||||
rx_status->flag |= RX_FLAG_MMIC_ERROR;
|
||||
}
|
||||
/*
|
||||
* everything but the rate is checked here, the rate check is done
|
||||
* separately to avoid doing two lookups for a rate for each frame.
|
||||
*/
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
if (!ath9k_cmn_rx_accept(common, hdr, rx_status, &rx_stats,
|
||||
&decrypt_error, priv->rxfilter))
|
||||
goto rx_next;
|
||||
|
||||
/*
|
||||
* Reject error frames with the exception of
|
||||
* decryption and MIC failures. For monitor mode,
|
||||
* we also ignore the CRC error.
|
||||
*/
|
||||
if (priv->ah->opmode == NL80211_IFTYPE_MONITOR) {
|
||||
if (rxbuf->rxstatus.rs_status &
|
||||
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
|
||||
ATH9K_RXERR_CRC))
|
||||
goto rx_next;
|
||||
} else {
|
||||
if (rxbuf->rxstatus.rs_status &
|
||||
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
|
||||
goto rx_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
ath9k_cmn_rx_skb_postprocess(common, skb, &rx_stats,
|
||||
rx_status, decrypt_error);
|
||||
|
||||
if (!(rxbuf->rxstatus.rs_status & ATH9K_RXERR_DECRYPT)) {
|
||||
u8 keyix;
|
||||
keyix = rxbuf->rxstatus.rs_keyix;
|
||||
if (keyix != ATH9K_RXKEYIX_INVALID) {
|
||||
rx_status->flag |= RX_FLAG_DECRYPTED;
|
||||
} else if (ieee80211_has_protected(fc) &&
|
||||
skb->len >= hdrlen + 4) {
|
||||
keyix = skb->data[hdrlen + 3] >> 6;
|
||||
if (test_bit(keyix, common->keymap))
|
||||
rx_status->flag |= RX_FLAG_DECRYPTED;
|
||||
}
|
||||
}
|
||||
if (ath9k_cmn_process_rate(common, hw, &rx_stats, rx_status))
|
||||
goto rx_next;
|
||||
|
||||
ath9k_process_rate(hw, rx_status, rxbuf->rxstatus.rs_rate,
|
||||
rxbuf->rxstatus.rs_flags);
|
||||
rx_stats.is_mybeacon = ath_is_mybeacon(common, hdr);
|
||||
ath9k_cmn_process_rssi(common, hw, &rx_stats, rx_status);
|
||||
|
||||
if (rxbuf->rxstatus.rs_rssi != ATH9K_RSSI_BAD &&
|
||||
!rxbuf->rxstatus.rs_moreaggr)
|
||||
ATH_RSSI_LPF(priv->rx.last_rssi,
|
||||
rxbuf->rxstatus.rs_rssi);
|
||||
|
||||
last_rssi = priv->rx.last_rssi;
|
||||
|
||||
if (ath_is_mybeacon(common, hdr)) {
|
||||
s8 rssi = rxbuf->rxstatus.rs_rssi;
|
||||
|
||||
if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
|
||||
rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
|
||||
|
||||
if (rssi < 0)
|
||||
rssi = 0;
|
||||
|
||||
priv->ah->stats.avgbrssi = rssi;
|
||||
}
|
||||
|
||||
rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
|
||||
rx_status->band = hw->conf.chandef.chan->band;
|
||||
rx_status->freq = hw->conf.chandef.chan->center_freq;
|
||||
rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR;
|
||||
rx_status->antenna = rxbuf->rxstatus.rs_antenna;
|
||||
rx_status->band = ah->curchan->chan->band;
|
||||
rx_status->freq = ah->curchan->chan->center_freq;
|
||||
rx_status->antenna = rx_stats.rs_antenna;
|
||||
rx_status->flag |= RX_FLAG_MACTIME_END;
|
||||
|
||||
return true;
|
||||
|
||||
rx_next:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -358,6 +358,36 @@ ret:
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
static void ath9k_htc_fw_panic_report(struct htc_target *htc_handle,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
uint32_t *pattern = (uint32_t *)skb->data;
|
||||
|
||||
switch (*pattern) {
|
||||
case 0x33221199:
|
||||
{
|
||||
struct htc_panic_bad_vaddr *htc_panic;
|
||||
htc_panic = (struct htc_panic_bad_vaddr *) skb->data;
|
||||
dev_err(htc_handle->dev, "ath: firmware panic! "
|
||||
"exccause: 0x%08x; pc: 0x%08x; badvaddr: 0x%08x.\n",
|
||||
htc_panic->exccause, htc_panic->pc,
|
||||
htc_panic->badvaddr);
|
||||
break;
|
||||
}
|
||||
case 0x33221299:
|
||||
{
|
||||
struct htc_panic_bad_epid *htc_panic;
|
||||
htc_panic = (struct htc_panic_bad_epid *) skb->data;
|
||||
dev_err(htc_handle->dev, "ath: firmware panic! "
|
||||
"bad epid: 0x%08x\n", htc_panic->epid);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
dev_err(htc_handle->dev, "ath: uknown panic pattern!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* HTC Messages are handled directly here and the obtained SKB
|
||||
* is freed.
|
||||
@@ -379,6 +409,12 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,
|
||||
htc_hdr = (struct htc_frame_hdr *) skb->data;
|
||||
epid = htc_hdr->endpoint_id;
|
||||
|
||||
if (epid == 0x99) {
|
||||
ath9k_htc_fw_panic_report(htc_handle, skb);
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (epid >= ENDPOINT_MAX) {
|
||||
if (pipe_id != USB_REG_IN_PIPE)
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
@@ -77,6 +77,18 @@ struct htc_config_pipe_msg {
|
||||
u8 credits;
|
||||
} __packed;
|
||||
|
||||
struct htc_panic_bad_vaddr {
|
||||
__be32 pattern;
|
||||
__be32 exccause;
|
||||
__be32 pc;
|
||||
__be32 badvaddr;
|
||||
} __packed;
|
||||
|
||||
struct htc_panic_bad_epid {
|
||||
__be32 pattern;
|
||||
__be32 epid;
|
||||
} __packed;
|
||||
|
||||
struct htc_ep_callbacks {
|
||||
void *priv;
|
||||
void (*tx) (void *, struct sk_buff *, enum htc_endpoint_id, bool txok);
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
|
||||
#include "hw.h"
|
||||
#include "hw-ops.h"
|
||||
#include "rc.h"
|
||||
#include "ar9003_mac.h"
|
||||
#include "ar9003_mci.h"
|
||||
#include "ar9003_phy.h"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user