diff options
author | David S. Miller <davem@davemloft.net> | 2009-10-29 02:47:13 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-29 02:47:13 -0700 |
commit | ed3f2e40f3d438f4a1ec0a898173116cb26f106a (patch) | |
tree | f50e1c5f5f3511539084d9529e592e3fb0352607 /drivers/net/wireless/ath | |
parent | fb699dfd426a189fe33b91586c15176a75c8aed0 (diff) | |
parent | bd6b4442ff3cee73f73987cf0c0e66ea677aa075 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r-- | drivers/net/wireless/ath/ar9170/ar9170.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/hw.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/main.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/usb.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/usb.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/ath5k.h | 13 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/attach.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/phy.c | 185 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/reg.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/reset.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ahb.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/calib.c | 28 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/regd.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ath/regd_common.h | 32 |
15 files changed, 216 insertions, 119 deletions
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index ec034af2698..9f9459860d8 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -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; diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h index 88113148331..701ddb7d840 100644 --- a/drivers/net/wireless/ath/ar9170/hw.h +++ b/drivers/net/wireless/ath/ar9170/hw.h @@ -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) diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index de0ba2bf769..7e59b82e64d 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -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); diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index e974e5829e1..6bdcdf6d1cc 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -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; diff --git a/drivers/net/wireless/ath/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h index d098f4d5d2f..a2ce3b169ce 100644 --- a/drivers/net/wireless/ath/ar9170/usb.h +++ b/drivers/net/wireless/ath/ar9170/usb.h @@ -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; diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 647d826bf5f..6a2a9676111 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -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, diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 92995adeb5c..42284445b75 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -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); diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 1a039f2bd73..895990751d3 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -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); diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 64227abe3c2..4cb9c5df9f4 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -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 /* diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 3dab3d856d7..62954fc7786 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -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); diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 33c9e816718..25531f231b6 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -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; diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index f46bd05df44..551f8801459 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -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 */ diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index a8620b1d091..2a4efcbced6 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -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, diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index c1dd857697a..a1c39526161 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h @@ -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, diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h index 9847af72208..248c670fdfb 100644 --- a/drivers/net/wireless/ath/regd_common.h +++ b/drivers/net/wireless/ath/regd_common.h @@ -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"}, |