Commit ed3f2e40 authored by David S. Miller's avatar David S. Miller
Browse files
parents fb699dfd bd6b4442
......@@ -1086,7 +1086,6 @@ F: include/net/ax25.h
F: net/ax25/
B43 WIRELESS DRIVER
M: Michael Buesch <mb@bu3sch.de>
M: Stefano Brivio <stefano.brivio@polimi.it>
L: linux-wireless@vger.kernel.org
W: http://linuxwireless.org/en/users/Drivers/b43
......
......@@ -5660,7 +5660,8 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
pci_save_state(pdev);
return pci_set_power_state(pdev, pci_choose_state(pdev, state));
pci_set_power_state(pdev, pci_choose_state(pdev, state));
return 0;
}
static int airo_pci_resume(struct pci_dev *pdev)
......
......@@ -231,7 +231,7 @@ struct ar9170 {
struct sk_buff_head tx_status_ampdu;
spinlock_t tx_ampdu_list_lock;
struct list_head tx_ampdu_list;
unsigned int tx_ampdu_pending;
atomic_t tx_ampdu_pending;
/* rxstream mpdu merge */
struct ar9170_rxstream_mpdu_merge rx_mpdu;
......
......@@ -152,14 +152,14 @@ enum ar9170_cmd {
#define AR9170_MAC_REG_FTF_BIT14 BIT(14)
#define AR9170_MAC_REG_FTF_BIT15 BIT(15)
#define AR9170_MAC_REG_FTF_BAR BIT(24)
#define AR9170_MAC_REG_FTF_BIT25 BIT(25)
#define AR9170_MAC_REG_FTF_BA BIT(25)
#define AR9170_MAC_REG_FTF_PSPOLL BIT(26)
#define AR9170_MAC_REG_FTF_RTS BIT(27)
#define AR9170_MAC_REG_FTF_CTS BIT(28)
#define AR9170_MAC_REG_FTF_ACK BIT(29)
#define AR9170_MAC_REG_FTF_CFE BIT(30)
#define AR9170_MAC_REG_FTF_CFE_ACK BIT(31)
#define AR9170_MAC_REG_FTF_DEFAULTS 0x0500ffff
#define AR9170_MAC_REG_FTF_DEFAULTS 0x0700ffff
#define AR9170_MAC_REG_FTF_MONITOR 0xfd00ffff
#define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6A0)
......
......@@ -414,9 +414,9 @@ static void ar9170_tx_ampdu_callback(struct ar9170 *ar, struct sk_buff *skb)
skb_queue_tail(&ar->tx_status_ampdu, skb);
ar9170_tx_fake_ampdu_status(ar);
ar->tx_ampdu_pending--;
if (!list_empty(&ar->tx_ampdu_list) && !ar->tx_ampdu_pending)
if (atomic_dec_and_test(&ar->tx_ampdu_pending) &&
!list_empty(&ar->tx_ampdu_list))
ar9170_tx_ampdu(ar);
}
......@@ -1248,6 +1248,7 @@ static int ar9170_op_start(struct ieee80211_hw *hw)
ar->global_ampdu_density = 6;
ar->global_ampdu_factor = 3;
atomic_set(&ar->tx_ampdu_pending, 0);
ar->bad_hw_nagger = jiffies;
err = ar->open(ar);
......@@ -1773,7 +1774,7 @@ static void ar9170_tx(struct ar9170 *ar)
msecs_to_jiffies(AR9170_TX_TIMEOUT);
if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK)
ar->tx_ampdu_pending++;
atomic_inc(&ar->tx_ampdu_pending);
#ifdef AR9170_QUEUE_DEBUG
printk(KERN_DEBUG "%s: send frame q:%d =>\n",
......@@ -1784,7 +1785,7 @@ static void ar9170_tx(struct ar9170 *ar)
err = ar->tx(ar, skb);
if (unlikely(err)) {
if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK)
ar->tx_ampdu_pending--;
atomic_dec(&ar->tx_ampdu_pending);
frames_failed++;
dev_kfree_skb_any(skb);
......@@ -1931,7 +1932,7 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
bool run = ar9170_tx_ampdu_queue(ar, skb);
if (run || !ar->tx_ampdu_pending)
if (run || !atomic_read(&ar->tx_ampdu_pending))
ar9170_tx_ampdu(ar);
} else {
unsigned int queue = skb_get_queue_mapping(skb);
......
......@@ -108,15 +108,15 @@ static void ar9170_usb_submit_urb(struct ar9170_usb *aru)
return ;
spin_lock_irqsave(&aru->tx_urb_lock, flags);
if (aru->tx_submitted_urbs >= AR9170_NUM_TX_URBS) {
if (atomic_read(&aru->tx_submitted_urbs) >= AR9170_NUM_TX_URBS) {
spin_unlock_irqrestore(&aru->tx_urb_lock, flags);
return ;
}
aru->tx_submitted_urbs++;
atomic_inc(&aru->tx_submitted_urbs);
urb = usb_get_from_anchor(&aru->tx_pending);
if (!urb) {
aru->tx_submitted_urbs--;
atomic_dec(&aru->tx_submitted_urbs);
spin_unlock_irqrestore(&aru->tx_urb_lock, flags);
return ;
......@@ -133,7 +133,7 @@ static void ar9170_usb_submit_urb(struct ar9170_usb *aru)
err);
usb_unanchor_urb(urb);
aru->tx_submitted_urbs--;
atomic_dec(&aru->tx_submitted_urbs);
ar9170_tx_callback(&aru->common, urb->context);
}
......@@ -151,7 +151,7 @@ static void ar9170_usb_tx_urb_complete_frame(struct urb *urb)
return ;
}
aru->tx_submitted_urbs--;
atomic_dec(&aru->tx_submitted_urbs);
ar9170_tx_callback(&aru->common, skb);
......@@ -794,7 +794,7 @@ static int ar9170_usb_probe(struct usb_interface *intf,
spin_lock_init(&aru->tx_urb_lock);
aru->tx_pending_urbs = 0;
aru->tx_submitted_urbs = 0;
atomic_set(&aru->tx_submitted_urbs, 0);
aru->common.stop = ar9170_usb_stop;
aru->common.flush = ar9170_usb_flush;
......
......@@ -67,7 +67,7 @@ struct ar9170_usb {
bool req_one_stage_fw;
spinlock_t tx_urb_lock;
unsigned int tx_submitted_urbs;
atomic_t tx_submitted_urbs;
unsigned int tx_pending_urbs;
struct completion cmd_wait;
......
......@@ -198,6 +198,7 @@
#define AR5K_TUNE_CWMAX_11B 1023
#define AR5K_TUNE_CWMAX_XR 7
#define AR5K_TUNE_NOISE_FLOOR -72
#define AR5K_TUNE_CCA_MAX_GOOD_VALUE -95
#define AR5K_TUNE_MAX_TXPOWER 63
#define AR5K_TUNE_DEFAULT_TXPOWER 25
#define AR5K_TUNE_TPC_TXPOWER false
......@@ -1006,6 +1007,14 @@ struct ath5k_capabilities {
} cap_queues;
};
/* size of noise floor history (keep it a power of two) */
#define ATH5K_NF_CAL_HIST_MAX 8
struct ath5k_nfcal_hist
{
s16 index; /* current index into nfval */
s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */
};
/***************************************\
HARDWARE ABSTRACTION LAYER STRUCTURE
......@@ -1112,6 +1121,8 @@ struct ath5k_hw {
struct ieee80211_channel r_last_channel;
} ah_radar;
struct ath5k_nfcal_hist ah_nfcal_hist;
/* noise floor from last periodic calibration */
s32 ah_noise_floor;
......@@ -1274,8 +1285,10 @@ extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah);
extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags);
extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel);
/* PHY calibration */
void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah);
extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel);
extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq);
extern s16 ath5k_hw_get_noise_floor(struct ath5k_hw *ah);
extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah);
/* Spur mitigation */
bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
......
......@@ -331,6 +331,8 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
ath5k_hw_rfgain_opt_init(ah);
ath5k_hw_init_nfcal_hist(ah);
/* turn on HW LEDs */
ath5k_hw_set_ledstate(ah, AR5K_LED_INIT);
......
......@@ -1124,77 +1124,148 @@ ath5k_hw_calibration_poll(struct ath5k_hw *ah)
ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION;
AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI);
}
}
static int sign_extend(int val, const int nbits)
{
int order = BIT(nbits-1);
return (val ^ order) - order;
}
/**
* ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration
*
* @ah: struct ath5k_hw pointer we are operating on
* @freq: the channel frequency, just used for error logging
*
* This function performs a noise floor calibration of the PHY and waits for
* it to complete. Then the noise floor value is compared to some maximum
* noise floor we consider valid.
*
* Note that this is different from what the madwifi HAL does: it reads the
* noise floor and afterwards initiates the calibration. Since the noise floor
* calibration can take some time to finish, depending on the current channel
* use, that avoids the occasional timeout warnings we are seeing now.
*
* See the following link for an Atheros patent on noise floor calibration:
* http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \
* &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7
static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah)
{
s32 val;
val = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
return sign_extend(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 9);
}
void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah)
{
int i;
ah->ah_nfcal_hist.index = 0;
for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++)
ah->ah_nfcal_hist.nfval[i] = AR5K_TUNE_CCA_MAX_GOOD_VALUE;
}
static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor)
{
struct ath5k_nfcal_hist *hist = &ah->ah_nfcal_hist;
hist->index = (hist->index + 1) & (ATH5K_NF_CAL_HIST_MAX-1);
hist->nfval[hist->index] = noise_floor;
}
static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah)
{
s16 sort[ATH5K_NF_CAL_HIST_MAX];
s16 tmp;
int i, j;
memcpy(sort, ah->ah_nfcal_hist.nfval, sizeof(sort));
for (i = 0; i < ATH5K_NF_CAL_HIST_MAX - 1; i++) {
for (j = 1; j < ATH5K_NF_CAL_HIST_MAX - i; j++) {
if (sort[j] > sort[j-1]) {
tmp = sort[j];
sort[j] = sort[j-1];
sort[j-1] = tmp;
}
}
}
for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++) {
ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
"cal %d:%d\n", i, sort[i]);
}
return sort[(ATH5K_NF_CAL_HIST_MAX-1) / 2];
}
/*
* When we tell the hardware to perform a noise floor calibration
* by setting the AR5K_PHY_AGCCTL_NF bit, it will periodically
* sample-and-hold the minimum noise level seen at the antennas.
* This value is then stored in a ring buffer of recently measured
* noise floor values so we have a moving window of the last few
* samples.
*
* XXX: Since during noise floor calibration antennas are detached according to
* the patent, we should stop tx queues here.
* The median of the values in the history is then loaded into the
* hardware for its own use for RSSI and CCA measurements.
*/
int
ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
{
int ret;
unsigned int i;
s32 noise_floor;
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
u32 val;
s16 nf, threshold;
u8 ee_mode;
/*
* Enable noise floor calibration
*/
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
AR5K_PHY_AGCCTL_NF);
/* keep last value if calibration hasn't completed */
if (ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL) & AR5K_PHY_AGCCTL_NF) {
ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
"NF did not complete in calibration window\n");
ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
AR5K_PHY_AGCCTL_NF, 0, false);
if (ret) {
ATH5K_ERR(ah->ah_sc,
"noise floor calibration timeout (%uMHz)\n", freq);
return -EAGAIN;
return;
}
/* Wait until the noise floor is calibrated and read the value */
for (i = 20; i > 0; i--) {
mdelay(1);
noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
noise_floor = AR5K_PHY_NF_RVAL(noise_floor);
if (noise_floor & AR5K_PHY_NF_ACTIVE) {
noise_floor = AR5K_PHY_NF_AVAL(noise_floor);
if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
break;
}
switch (ah->ah_current_channel->hw_value & CHANNEL_MODES) {
case CHANNEL_A:
case CHANNEL_T:
case CHANNEL_XR:
ee_mode = AR5K_EEPROM_MODE_11A;
break;
case CHANNEL_G:
case CHANNEL_TG:
ee_mode = AR5K_EEPROM_MODE_11G;
break;
default:
case CHANNEL_B:
ee_mode = AR5K_EEPROM_MODE_11B;
break;
}
ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
"noise floor %d\n", noise_floor);
if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
ATH5K_ERR(ah->ah_sc,
"noise floor calibration failed (%uMHz)\n", freq);
return -EAGAIN;
/* completed NF calibration, test threshold */
nf = ath5k_hw_read_measured_noise_floor(ah);
threshold = ee->ee_noise_floor_thr[ee_mode];
if (nf > threshold) {
ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
"noise floor failure detected; "
"read %d, threshold %d\n",
nf, threshold);
nf = AR5K_TUNE_CCA_MAX_GOOD_VALUE;
}
ah->ah_noise_floor = noise_floor;
ath5k_hw_update_nfcal_hist(ah, nf);
nf = ath5k_hw_get_median_noise_floor(ah);
return 0;
/* load noise floor (in .5 dBm) so the hardware will use it */
val = ath5k_hw_reg_read(ah, AR5K_PHY_NF) & ~AR5K_PHY_NF_M;
val |= (nf * 2) & AR5K_PHY_NF_M;
ath5k_hw_reg_write(ah, val, AR5K_PHY_NF);
AR5K_REG_MASKED_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF,
~(AR5K_PHY_AGCCTL_NF_EN | AR5K_PHY_AGCCTL_NF_NOUPDATE));
ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF,
0, false);
/*
* Load a high max CCA Power value (-50 dBm in .5 dBm units)
* so that we're not capped by the median we just loaded.
* This will be used as the initial value for the next noise
* floor calibration.
*/
val = (val & ~AR5K_PHY_NF_M) | ((-50 * 2) & AR5K_PHY_NF_M);
ath5k_hw_reg_write(ah, val, AR5K_PHY_NF);
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
AR5K_PHY_AGCCTL_NF_EN |
AR5K_PHY_AGCCTL_NF_NOUPDATE |
AR5K_PHY_AGCCTL_NF);
ah->ah_noise_floor = nf;
ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
"noise floor calibrated: %d\n", nf);
}
/*
......@@ -1287,7 +1358,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
return ret;
}
ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
ath5k_hw_update_noise_floor(ah);
/*
* Re-enable RX/TX and beacons
......@@ -1360,7 +1431,7 @@ done:
* since noise floor calibration interrupts rx path while I/Q
* calibration doesn't. We don't need to run noise floor calibration
* as often as I/Q calibration.*/
ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
ath5k_hw_update_noise_floor(ah);
/* Initiate a gain_F calibration */
ath5k_hw_request_rfgain_probe(ah);
......
......@@ -2033,17 +2033,14 @@
#define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */
/*
* PHY noise floor status register
* PHY noise floor status register (CCA = Clear Channel Assessment)
*/
#define AR5K_PHY_NF 0x9864 /* Register address */
#define AR5K_PHY_NF_M 0x000001ff /* Noise floor mask */
#define AR5K_PHY_NF_ACTIVE 0x00000100 /* Noise floor calibration still active */
#define AR5K_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_PHY_NF_M)
#define AR5K_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_PHY_NF_M) + 1)
#define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9))
#define AR5K_PHY_NF_M 0x000001ff /* Noise floor, written to hardware in 1/2 dBm units */
#define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9))
#define AR5K_PHY_NF_THRESH62 0x0007f000 /* Thresh62 -check ANI patent- (field) */
#define AR5K_PHY_NF_THRESH62_S 12
#define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* ??? */
#define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* Minimum measured noise level, read from hardware in 1 dBm units */
#define AR5K_PHY_NF_MINCCA_PWR_S 19
/*
......
......@@ -1293,7 +1293,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
* out and/or noise floor calibration might timeout.
*/
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
AR5K_PHY_AGCCTL_CAL);
AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF);
/* At the same time start I/Q calibration for QAM constellation
* -no need for CCK- */
......@@ -1314,21 +1314,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
channel->center_freq);
}
/*
* If we run NF calibration before AGC, it always times out.
* Binary HAL starts NF and AGC calibration at the same time
* and only waits for AGC to finish. Also if AGC or NF cal.
* times out, reset doesn't fail on binary HAL. I believe
* that's wrong because since rx path is routed to a detector,
* if cal. doesn't finish we won't have RX. Sam's HAL for AR5210/5211
* enables noise floor calibration after offset calibration and if noise
* floor calibration fails, reset fails. I believe that's
* a better approach, we just need to find a polling interval
* that suits best, even if reset continues we need to make
* sure that rx path is ready.
*/
ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
/* Restore antenna mode */
ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
......
......@@ -29,15 +29,13 @@ static void ath_ahb_read_cachesize(struct ath_common *common, int *csz)
static void ath_ahb_cleanup(struct ath_common *common)
{
struct ath_hw *ah = (struct ath_hw *) common->ah;
struct ath_softc *sc = ah->ah_sc;
struct ath_softc *sc = (struct ath_softc *)common->priv;
iounmap(sc->mem);
}
static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
{
struct ath_hw *ah = (struct ath_hw *) common->ah;
struct ath_softc *sc = ah->ah_sc;
struct ath_softc *sc = (struct ath_softc *)common->priv;
struct platform_device *pdev = to_platform_device(sc->dev);
struct ath9k_platform_data *pdata;
......
......@@ -813,7 +813,7 @@ static void ath9k_olc_temp_compensation(struct ath_hw *ah)
}
}
static void ath9k_hw_9271_pa_cal(struct ath_hw *ah)
static void ath9k_hw_9271_pa_cal(struct ath_hw *ah, bool is_reset)
{
u32 regVal;
unsigned int i;
......@@ -889,10 +889,19 @@ static void ath9k_hw_9271_pa_cal(struct ath_hw *ah)
REG_WRITE(ah, 0x7834, regVal);
}
/* Empirical offset correction */
#if 0
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0x20);
#endif
regVal = (regVal >>20) & 0x7f;
/* Update PA cal info */
if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) {
if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
ah->pacal_info.max_skipcount =
2 * ah->pacal_info.max_skipcount;
ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
} else {
ah->pacal_info.max_skipcount = 1;
ah->pacal_info.skipcount = 0;
ah->pacal_info.prev_offset = regVal;
}
regVal = REG_READ(ah, 0x7834);
regVal |= 0x1;
......@@ -1043,7 +1052,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
if (longcal) {
/* Do periodic PAOffset Cal */
if (AR_SREV_9271(ah))
ath9k_hw_9271_pa_cal(ah);
ath9k_hw_9271_pa_cal(ah, false);
else if (AR_SREV_9285_11_OR_LATER(ah)) {
if (!ah->pacal_info.skipcount)
ath9k_hw_9285_pa_cal(ah, false);
......@@ -1070,6 +1079,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
}
EXPORT_SYMBOL(ath9k_hw_calibrate);
/* Carrier leakage Calibration fix */
static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
......@@ -1115,7 +1125,7 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
if (AR_SREV_9285_12_OR_LATER(ah)) {
if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) {
if (!ar9285_clc(ah, chan))
return false;
} else {
......@@ -1151,7 +1161,9 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
}
/* Do PA Calibration */
if (AR_SREV_9285_11_OR_LATER(ah))
if (AR_SREV_9271(ah))
ath9k_hw_9271_pa_cal(ah, true);
else if (AR_SREV_9285_11_OR_LATER(ah))
ath9k_hw_9285_pa_cal(ah, true);
/* Do NF Calibration after DC offset and other calibrations */
......
......@@ -2079,7 +2079,9 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
if (needreset) {
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
"tx hung, resetting the chip\n");
ath9k_ps_wakeup(sc);
ath_reset(sc, false);
ath9k_ps_restore(sc);
}
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
......
......@@ -65,10 +65,13 @@ enum CountryCode {
CTRY_ALGERIA = 12,
CTRY_ARGENTINA = 32,
CTRY_ARMENIA = 51,
CTRY_ARUBA = 533,
CTRY_AUSTRALIA = 36,
CTRY_AUSTRIA = 40,
CTRY_AZERBAIJAN = 31,
CTRY_BAHRAIN = 48,
CTRY_BANGLADESH = 50,
CTRY_BARBADOS = 52,
CTRY_BELARUS = 112,
CTRY_BELGIUM = 56,
CTRY_BELIZE = 84,
......@@ -77,6 +80,7 @@ enum CountryCode {
CTRY_BRAZIL = 76,
CTRY_BRUNEI_DARUSSALAM = 96,
CTRY_BULGARIA = 100,
CTRY_CAMBODIA = 116,
CTRY_CANADA = 124,
CTRY_CHILE = 152,
CTRY_CHINA = 156,
......@@ -97,7 +101,11 @@ enum CountryCode {
CTRY_GEORGIA = 268,
CTRY_GERMANY = 276,
CTRY_GREECE = 300,
CTRY_GREENLAND = 304,
CTRY_GRENEDA = 308,
CTRY_GUAM = 316,
CTRY_GUATEMALA = 320,
CTRY_HAITI = 332,
CTRY_HONDURAS = 340,
CTRY_HONG_KONG = 344,
CTRY_HUNGARY = 348,
......
......@@ -288,13 +288,16 @@ static struct country_code_to_enum_rd allCountries[] = {
{CTRY_DEFAULT, FCC1_FCCA, "CO"},
{CTRY_ALBANIA, NULL1_WORLD, "AL"},
{CTRY_ALGERIA, NULL1_WORLD, "DZ"},
{CTRY_ARGENTINA, APL3_WORLD, "AR"},
{CTRY_ARGENTINA, FCC3_WORLD, "AR"},
{CTRY_ARMENIA, ETSI4_WORLD, "AM"},
{CTRY_ARUBA, ETSI1_WORLD, "AW"},
{CTRY_AUSTRALIA, FCC2_WORLD, "AU"},
{CTRY_AUSTRALIA2, FCC6_WORLD, "AU"},
{CTRY_AUSTRIA, ETSI1_WORLD, "AT"},
{CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"},
{CTRY_BAHRAIN, APL6_WORLD, "BH"},
{CTRY_BANGLADESH, NULL1_WORLD, "BD"},
{CTRY_BARBADOS, FCC2_WORLD, "BB"},
{CTRY_BELARUS, ETSI1_WORLD, "BY"},
{CTRY_BELGIUM, ETSI1_WORLD, "BE"},
{CTRY_BELGIUM2, ETSI4_WORLD, "BL"},
......@@ -304,13 +307,14 @@ static struct country_code_to_enum_rd allCountries[] = {
{CTRY_BRAZIL, FCC3_WORLD, "BR"},
{CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN"},
{CTRY_BULGARIA, ETSI6_WORLD, "BG"},
{CTRY_CANADA, FCC2_FCCA, "CA"},
{CTRY_CAMBODIA, ETSI1_WORLD, "KH"},
{CTRY_CANADA, FCC3_FCCA, "CA"},
{CTRY_CANADA2, FCC6_FCCA, "CA"},
{CTRY_CHILE, APL6_WORLD, "CL"},
{CTRY_CHINA, APL1_WORLD, "CN"},
{CTRY_COLOMBIA, FCC1_FCCA, "CO"},
{CTRY_COSTA_RICA, FCC1_WORLD, "CR"},
{CTRY_CROATIA, ETSI3_WORLD, "HR"},
{CTRY_CROATIA, ETSI1_WORLD, "HR"},
{CTRY_CYPRUS, ETSI1_WORLD, "CY"},
{CTRY_CZECH, ETSI3_WORLD, "CZ"},
{CTRY_DENMARK, ETSI1_WORLD, "DK"},
......@@ -324,18 +328,22 @@ static struct country_code_to_enum_rd allCountries[] = {
{CTRY_GEORGIA, ETSI4_WORLD, "GE"},
{CTRY_GERMANY, ETSI1_WORLD, "DE"},
{CTRY_GREECE, ETSI1_WORLD, "GR"},
{CTRY_GREENLAND, ETSI1_WORLD, "GL"},
{CTRY_GRENEDA, FCC3_FCCA, "GD"},
{CTRY_GUAM, FCC1_FCCA, "GU"},
{CTRY_GUATEMALA, FCC1_FCCA, "GT"},
{CTRY_HAITI, ETSI1_WORLD, "HT"},
{CTRY_HONDURAS, NULL1_WORLD, "HN"},
{CTRY_HONG_KONG, FCC2_WORLD, "HK"},
{CTRY_HONG_KONG, FCC3_WORLD, "HK"},
{CTRY_HUNGARY, ETSI1_WORLD, "HU"},
{CTRY_ICELAND, ETSI1_WORLD, "IS"},
{CTRY_INDIA, APL6_WORLD, "IN"},
{CTRY_INDONESIA, APL1_WORLD, "ID"},
{CTRY_INDONESIA, NULL1_WORLD, "ID"},
{CTRY_IRAN, APL1_WORLD, "IR"},
{CTRY_IRELAND, ETSI1_WORLD, "IE"},
{CTRY_ISRAEL, NULL1_WORLD, "IL"},
{CTRY_ITALY, ETSI1_WORLD, "IT"},
{CTRY_JAMAICA, ETSI1_WORLD, "JM"},
{CTRY_JAMAICA, FCC3_WORLD, "JM"},
{CTRY_JAPAN, MKK1_MKKA, "JP"},
{CTRY_JAPAN1, MKK1_MKKB, "JP"},
......@@ -402,7 +410,7 @@ static struct country_code_to_enum_rd allCountries[] = {
{CTRY_KOREA_ROC, APL9_WORLD, "KR"},
{CTRY_KOREA_ROC2, APL2_WORLD, "K2"},
{CTRY_KOREA_ROC3, APL9_WORLD, "K3"},
{CTRY_KUWAIT, NULL1_WORLD, "KW"},
{CTRY_KUWAIT, ETSI3_WORLD, "KW"},
{CTRY_LATVIA, ETSI1_WORLD, "LV"},
{CTRY_LEBANON, NULL1_WORLD, "LB"},
{CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI"},
......@@ -414,13 +422,13 @@ static struct country_code_to_enum_rd allCountries[] = {
{CTRY_MALTA, ETSI1_WORLD, "MT"},
{CTRY_MEXICO, FCC1_FCCA, "MX"},
{CTRY_MONACO, ETSI4_WORLD, "MC"},
{CTRY_MOROCCO, NULL1_WORLD, "MA"},
{CTRY_MOROCCO, APL4_WORLD, "MA"},
{CTRY_NEPAL, APL1_WORLD, "NP"},
{CTRY_NETHERLANDS, ETSI1_WORLD, "NL"},
{CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN"},
{CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ"},
{CTRY_NORWAY, ETSI1_WORLD, "NO"},
{CTRY_OMAN, APL6_WORLD, "OM"},
{CTRY_OMAN, FCC3_WORLD, "OM"},
{CTRY_PAKISTAN, NULL1_WORLD, "PK"},
{CTRY_PANAMA, FCC1_FCCA, "PA"},
{CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG"},
......@@ -429,7 +437,7 @@ static struct country_code_to_enum_rd allCountries[] = {
{CTRY_POLAND, ETSI1_WORLD, "PL"},
{CTRY_PORTUGAL, ETSI1_WORLD, "PT"},
{CTRY_PUERTO_RICO, FCC1_FCCA, "PR"},
{CTRY_QATAR, NULL1_WORLD, "QA"},
{CTRY_QATAR, APL1_WORLD, "QA"},
{CTRY_ROMANIA, NULL1_WORLD, "RO"},
{CTRY_RUSSIA, NULL1_WORLD, "RU"},
{CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"},
......@@ -445,7 +453,7 @@ static struct country_code_to_enum_rd allCountries[] = {
{CTRY_SYRIA, NULL1_WORLD, "SY"},
{CTRY_TAIWAN, APL3_FCCA, "TW"},
{CTRY_THAILAND, FCC3_WORLD, "TH"},
{CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT"},
{CTRY_TRINIDAD_Y_TOBAGO, FCC3_WORLD, "TT"},
{CTRY_TUNISIA, ETSI3_WORLD, "TN"},
{CTRY_TURKEY, ETSI3_WORLD, "TR"},
{CTRY_UKRAINE, NULL1_WORLD, "UA"},
......@@ -456,7 +464,7 @@ static struct country_code_to_enum_rd allCountries[] = {
* would need to assign new special alpha2 to CRDA db as with the world
* regdomain and use another alpha2 */
{CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS"},
{CTRY_URUGUAY, APL2_WORLD, "UY"},
{CTRY_URUGUAY, FCC3_WORLD, "UY"},
{CTRY_UZBEKISTAN, FCC3_FCCA, "UZ"},
{CTRY_VENEZUELA, APL2_ETSIC, "VE"},
{CTRY_VIET_NAM, NULL1_WORLD, "VN"},
......
......@@ -749,12 +749,6 @@ struct b43_wldev {
#endif
};
/*
* Include goes here to avoid a dependency problem.
* A better fix would be to integrate xmit.h into b43.h.
*/
#include "xmit.h"
/* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */
struct b43_wl {
/* Pointer to the active wireless device on this chip */
......@@ -830,13 +824,9 @@ struct b43_wl {
struct b43_leds leds;
#ifdef CONFIG_B43_PIO
/*
* RX/TX header/tail buffers used by the frame transmit functions.
*/
struct b43_rxhdr_fw4 rxhdr;
struct b43_txhdr txhdr;
u8 rx_tail[4];
u8 tx_tail[4];
/* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */
u8 pio_scratchspace[110] __attribute__((__aligned__(8)));
u8 pio_tailspace[4] __attribute__((__aligned__(8)));
#endif /* CONFIG_B43_PIO */
};
......
......@@ -4671,7 +4671,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
struct ssb_bus *bus = dev->dev->bus;
struct pci_dev *pdev = bus->host_pci;
struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL;
int err;
bool have_2ghz_phy = 0, have_5ghz_phy = 0;
u32 tmp;
......@@ -4804,7 +4804,7 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
if (!list_empty(&wl->devlist)) {
/* We are not the first core on this chip. */
pdev = dev->bus->host_pci;
pdev = (dev->bus->bustype == SSB_BUSTYPE_PCI) ? dev->bus->host_pci : NULL;
/* Only special chips support more than one wireless
* core, although some of the other chips have more than
* one wireless core as well. Check for this and
......
......@@ -341,12 +341,15 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
q->mmio_base + B43_PIO_TXDATA,
sizeof(u16));
if (data_len & 1) {
u8 *tail = wl->pio_tailspace;
BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
/* Write the last byte. */
ctl &= ~B43_PIO_TXCTL_WRITEHI;
b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
wl->tx_tail[0] = data[data_len - 1];
wl->tx_tail[1] = 0;
ssb_block_write(dev->dev, wl->tx_tail, 2,
tail[0] = data[data_len - 1];
tail[1] = 0;
ssb_block_write(dev->dev, tail, 2,
q->mmio_base + B43_PIO_TXDATA,
sizeof(u16));
}
......@@ -392,31 +395,31 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
q->mmio_base + B43_PIO8_TXDATA,
sizeof(u32));
if (data_len & 3) {
wl->tx_tail[3] = 0;
u8 *tail = wl->pio_tailspace;
BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
memset(tail, 0, 4);
/* Write the last few bytes. */
ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
B43_PIO8_TXCTL_24_31);
switch (data_len & 3) {
case 3:
ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15;
wl->tx_tail[0] = data[data_len - 3];
wl->tx_tail[1] = data[data_len - 2];
wl->tx_tail[2] = data[data_len - 1];
tail[0] = data[data_len - 3];
tail[1] = data[data_len - 2];
tail[2] = data[data_len - 1];
break;
case 2:
ctl |= B43_PIO8_TXCTL_8_15;
wl->tx_tail[0] = data[data_len - 2];
wl->tx_tail[1] = data[data_len - 1];
wl->tx_tail[2] = 0;
tail[0] = data[data_len - 2];
tail[1] = data[data_len - 1];
break;
case 1:
wl->tx_tail[0] = data[data_len - 1];
wl->tx_tail[1] = 0;
wl->tx_tail[2] = 0;
tail[0] = data[data_len - 1];
break;
}
b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
ssb_block_write(dev->dev, wl->tx_tail, 4,
ssb_block_write(dev->dev, tail, 4,
q->mmio_base + B43_PIO8_TXDATA,
sizeof(u32));
}
......@@ -455,6 +458,7 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
int err;
unsigned int hdrlen;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct b43_txhdr *txhdr = (struct b43_txhdr *)wl->pio_scratchspace;
B43_WARN_ON(list_empty(&q->packets_list));
pack = list_entry(q->packets_list.next,
......@@ -462,7 +466,9 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
cookie = generate_cookie(q, pack);
hdrlen = b43_txhdr_size(dev);
err = b43_generate_txhdr(dev, (u8 *)&wl->txhdr, skb,
BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(struct b43_txhdr));
B43_WARN_ON(sizeof(wl->pio_scratchspace) < hdrlen);
err = b43_generate_txhdr(dev, (u8 *)txhdr, skb,
info, cookie);
if (err)
return err;
......@@ -476,9 +482,9 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
pack->skb = skb;
if (q->rev >= 8)
pio_tx_frame_4byte_queue(pack, (const u8 *)&wl->txhdr, hdrlen);
pio_tx_frame_4byte_queue(pack, (const u8 *)txhdr, hdrlen);
else
pio_tx_frame_2byte_queue(pack, (const u8 *)&wl->txhdr, hdrlen);
pio_tx_frame_2byte_queue(pack, (const u8 *)txhdr, hdrlen);
/* Remove it from the list of available packet slots.
* It will be put back when we receive the status report. */
......@@ -624,8 +630,11 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q)
unsigned int i, padding;
struct sk_buff *skb;
const char *err_msg = NULL;
struct b43_rxhdr_fw4 *rxhdr =
(struct b43_rxhdr_fw4 *)wl->pio_scratchspace;
memset(&wl->rxhdr, 0, sizeof(wl->rxhdr));
BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(*rxhdr));
memset(rxhdr, 0, sizeof(*rxhdr));
/* Check if we have data and wait for it to get ready. */
if (q->rev >= 8) {
......@@ -663,16 +672,16 @@ data_ready:
/* Get the preamble (RX header) */
if (q->rev >= 8) {
ssb_block_read(dev->dev, &wl->rxhdr, sizeof(wl->rxhdr),
ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr),
q->mmio_base + B43_PIO8_RXDATA,
sizeof(u32));
} else {
ssb_block_read(dev->dev, &wl->rxhdr, sizeof(wl->rxhdr),
ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr),
q->mmio_base + B43_PIO_RXDATA,
sizeof(u16));
}
/* Sanity checks. */
len = le16_to_cpu(wl->rxhdr.frame_len);
len = le16_to_cpu(rxhdr->frame_len);
if (unlikely(len > 0x700)) {
err_msg = "len > 0x700";
goto rx_error;
......@@ -682,7 +691,7 @@ data_ready:
goto rx_error;
}
macstat = le32_to_cpu(wl->rxhdr.mac_status);
macstat = le32_to_cpu(rxhdr->mac_status);
if (macstat & B43_RX_MAC_FCSERR) {
if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
/* Drop frames with failed FCS. */
......@@ -707,22 +716,25 @@ data_ready:
q->mmio_base + B43_PIO8_RXDATA,
sizeof(u32));
if (len & 3) {
u8 *tail = wl->pio_tailspace;
BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
/* Read the last few bytes. */
ssb_block_read(dev->dev, wl->rx_tail, 4,
ssb_block_read(dev->dev, tail, 4,
q->mmio_base + B43_PIO8_RXDATA,
sizeof(u32));
switch (len & 3) {
case 3:
skb->data[len + padding - 3] = wl->rx_tail[0];
skb->data[len + padding - 2] = wl->rx_tail[1];
skb->data[len + padding - 1] = wl->rx_tail[2];
skb->data[len + padding - 3] = tail[0];
skb->data[len + padding - 2] = tail[1];
skb->data[len + padding - 1] = tail[2];
break;
case 2:
skb->data[len + padding - 2] = wl->rx_tail[0];
skb->data[len + padding - 1] = wl->rx_tail[1];
skb->data[len + padding - 2] = tail[0];
skb->data[len + padding - 1] = tail[1];
break;
case 1:
skb->data[len + padding - 1] = wl->rx_tail[0];
skb->data[len + padding - 1] = tail[0];
break;
}
}
......@@ -731,15 +743,18 @@ data_ready:
q->mmio_base + B43_PIO_RXDATA,
sizeof(u16));
if (len & 1) {
u8 *tail = wl->pio_tailspace;
BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
/* Read the last byte. */
ssb_block_read(dev->dev, wl->rx_tail, 2,
ssb_block_read(dev->dev, tail, 2,
q->mmio_base + B43_PIO_RXDATA,
sizeof(u16));
skb->data[len + padding - 1] = wl->rx_tail[0];
skb->data[len + padding - 1] = tail[0];
}
}
b43_rx(q->dev, skb, &wl->rxhdr);
b43_rx(q->dev, skb, rxhdr);
return 1;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment