提交 3eb14b94 编写于 作者: D David S. Miller

Merge branch 'for-davem' of...

Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
......@@ -520,7 +520,6 @@ Who: Hans de Goede <hdegoede@redhat.com>
----------------------------
What: corgikbd, spitzkbd, tosakbd driver
When: 2.6.35
Files: drivers/input/keyboard/{corgi,spitz,tosa}kbd.c
......@@ -608,3 +607,24 @@ Why: Useful in 2003, implementation is a hack.
Generally invoked by accident today.
Seen as doing more harm than good.
Who: Len Brown <len.brown@intel.com>
----------------------------
What: iwlwifi 50XX module parameters
When: 2.6.40
Why: The "..50" modules parameters were used to configure 5000 series and
up devices; different set of module parameters also available for 4965
with same functionalities. Consolidate both set into single place
in drivers/net/wireless/iwlwifi/iwl-agn.c
Who: Wey-Yi Guy <wey-yi.w.guy@intel.com>
----------------------------
What: iwl4965 alias support
When: 2.6.40
Why: Internal alias support has been present in module-init-tools for some
time, the MODULE_ALIAS("iwl4965") boilerplate aliases can be removed
with no impact.
Who: Wey-Yi Guy <wey-yi.w.guy@intel.com>
......@@ -79,7 +79,7 @@ __regwrite_out : \
if (__nreg) { \
if (IS_ACCEPTING_CMD(__ar)) \
__err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \
8 * __nreg, \
8 * __nreg, \
(u8 *) &__ar->cmdbuf[1], \
0, NULL); \
__nreg = 0; \
......
......@@ -127,8 +127,8 @@ struct ar9170_eeprom {
__le16 checksum;
__le16 version;
u8 operating_flags;
#define AR9170_OPFLAG_5GHZ 1
#define AR9170_OPFLAG_2GHZ 2
#define AR9170_OPFLAG_5GHZ 1
#define AR9170_OPFLAG_2GHZ 2
u8 misc;
__le16 reg_domain[2];
u8 mac_address[6];
......
......@@ -425,5 +425,6 @@ enum ar9170_txq {
#define AR9170_TXQ_DEPTH 32
#define AR9170_TX_MAX_PENDING 128
#define AR9170_RX_STREAM_MAX_SIZE 65535
#endif /* __AR9170_HW_H */
......@@ -236,7 +236,7 @@ static void __ar9170_dump_txqueue(struct ar9170 *ar,
wiphy_name(ar->hw->wiphy), skb_queue_len(queue));
skb_queue_walk(queue, skb) {
printk(KERN_DEBUG "index:%d => \n", i++);
printk(KERN_DEBUG "index:%d =>\n", i++);
ar9170_print_txheader(ar, skb);
}
if (i != skb_queue_len(queue))
......@@ -281,7 +281,7 @@ static void ar9170_dump_tx_status_ampdu(struct ar9170 *ar)
unsigned long flags;
spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags);
printk(KERN_DEBUG "%s: A-MPDU tx_status queue => \n",
printk(KERN_DEBUG "%s: A-MPDU tx_status queue =>\n",
wiphy_name(ar->hw->wiphy));
__ar9170_dump_txqueue(ar, &ar->tx_status_ampdu);
spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags);
......@@ -308,7 +308,7 @@ static void ar9170_recycle_expired(struct ar9170 *ar,
if (time_is_before_jiffies(arinfo->timeout)) {
#ifdef AR9170_QUEUE_DEBUG
printk(KERN_DEBUG "%s: [%ld > %ld] frame expired => "
"recycle \n", wiphy_name(ar->hw->wiphy),
"recycle\n", wiphy_name(ar->hw->wiphy),
jiffies, arinfo->timeout);
ar9170_print_txheader(ar, skb);
#endif /* AR9170_QUEUE_DEBUG */
......@@ -689,7 +689,8 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
/* firmware debug */
case 0xca:
printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, (char *)buf + 4);
printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4,
(char *)buf + 4);
break;
case 0xcb:
len -= 4;
......@@ -1728,7 +1729,7 @@ static void ar9170_tx(struct ar9170 *ar)
printk(KERN_DEBUG "%s: queue %d full\n",
wiphy_name(ar->hw->wiphy), i);
printk(KERN_DEBUG "%s: stuck frames: ===> \n",
printk(KERN_DEBUG "%s: stuck frames: ===>\n",
wiphy_name(ar->hw->wiphy));
ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
ar9170_dump_txqueue(ar, &ar->tx_status[i]);
......@@ -2512,7 +2513,7 @@ void *ar9170_alloc(size_t priv_size)
* tends to split the streams into separate rx descriptors.
*/
skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL);
skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL);
if (!skb)
goto err_nomem;
......
......@@ -67,18 +67,28 @@ static struct usb_device_id ar9170_usb_ids[] = {
{ USB_DEVICE(0x0cf3, 0x1001) },
/* TP-Link TL-WN821N v2 */
{ USB_DEVICE(0x0cf3, 0x1002) },
/* 3Com Dual Band 802.11n USB Adapter */
{ USB_DEVICE(0x0cf3, 0x1010) },
/* H3C Dual Band 802.11n USB Adapter */
{ USB_DEVICE(0x0cf3, 0x1011) },
/* Cace Airpcap NX */
{ USB_DEVICE(0xcace, 0x0300) },
/* D-Link DWA 160 A1 */
{ USB_DEVICE(0x07d1, 0x3c10) },
/* D-Link DWA 160 A2 */
{ USB_DEVICE(0x07d1, 0x3a09) },
/* Netgear WNA1000 */
{ USB_DEVICE(0x0846, 0x9040) },
/* Netgear WNDA3100 */
{ USB_DEVICE(0x0846, 0x9010) },
/* Netgear WN111 v2 */
{ USB_DEVICE(0x0846, 0x9001) },
/* Zydas ZD1221 */
{ USB_DEVICE(0x0ace, 0x1221) },
/* Proxim ORiNOCO 802.11n USB */
{ USB_DEVICE(0x1435, 0x0804) },
/* WNC Generic 11n USB Dongle */
{ USB_DEVICE(0x1435, 0x0326) },
/* ZyXEL NWD271N */
{ USB_DEVICE(0x0586, 0x3417) },
/* Z-Com UB81 BG */
......
......@@ -48,6 +48,12 @@ enum ath_device_state {
ATH_HW_INITIALIZED,
};
enum ath_bus_type {
ATH_PCI,
ATH_AHB,
ATH_USB,
};
struct reg_dmn_pair_mapping {
u16 regDmnEnum;
u16 reg_5ghz_ctl;
......@@ -73,9 +79,10 @@ struct ath_ops {
struct ath_common;
struct ath_bus_ops {
void (*read_cachesize)(struct ath_common *common, int *csz);
bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
void (*bt_coex_prep)(struct ath_common *common);
enum ath_bus_type ath_bus_type;
void (*read_cachesize)(struct ath_common *common, int *csz);
bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
void (*bt_coex_prep)(struct ath_common *common);
};
struct ath_common {
......
......@@ -12,5 +12,6 @@ ath5k-y += attach.o
ath5k-y += base.o
ath5k-y += led.o
ath5k-y += rfkill.o
ath5k-y += ani.o
ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o
obj-$(CONFIG_ATH5K) += ath5k.o
此差异已折叠。
/*
* Copyright (C) 2010 Bruno Randolf <br1@einfach.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef ANI_H
#define ANI_H
/* these thresholds are relative to the ATH5K_ANI_LISTEN_PERIOD */
#define ATH5K_ANI_LISTEN_PERIOD 100
#define ATH5K_ANI_OFDM_TRIG_HIGH 500
#define ATH5K_ANI_OFDM_TRIG_LOW 200
#define ATH5K_ANI_CCK_TRIG_HIGH 200
#define ATH5K_ANI_CCK_TRIG_LOW 100
/* average beacon RSSI thresholds */
#define ATH5K_ANI_RSSI_THR_HIGH 40
#define ATH5K_ANI_RSSI_THR_LOW 7
/* maximum availabe levels */
#define ATH5K_ANI_MAX_FIRSTEP_LVL 2
#define ATH5K_ANI_MAX_NOISE_IMM_LVL 1
/**
* enum ath5k_ani_mode - mode for ANI / noise sensitivity
*
* @ATH5K_ANI_MODE_OFF: Turn ANI off. This can be useful to just stop the ANI
* algorithm after it has been on auto mode.
* ATH5K_ANI_MODE_MANUAL_LOW: Manually set all immunity parameters to low,
* maximizing sensitivity. ANI will not run.
* ATH5K_ANI_MODE_MANUAL_HIGH: Manually set all immunity parameters to high,
* minimizing sensitivity. ANI will not run.
* ATH5K_ANI_MODE_AUTO: Automatically control immunity parameters based on the
* amount of OFDM and CCK frame errors (default).
*/
enum ath5k_ani_mode {
ATH5K_ANI_MODE_OFF = 0,
ATH5K_ANI_MODE_MANUAL_LOW = 1,
ATH5K_ANI_MODE_MANUAL_HIGH = 2,
ATH5K_ANI_MODE_AUTO = 3
};
/**
* struct ath5k_ani_state - ANI state and associated counters
*
* @max_spur_level: the maximum spur level is chip dependent
*/
struct ath5k_ani_state {
enum ath5k_ani_mode ani_mode;
/* state */
int noise_imm_level;
int spur_level;
int firstep_level;
bool ofdm_weak_sig;
bool cck_weak_sig;
int max_spur_level;
/* used by the algorithm */
unsigned int listen_time;
unsigned int ofdm_errors;
unsigned int cck_errors;
/* debug/statistics only: numbers from last ANI calibration */
unsigned int pfc_tx;
unsigned int pfc_rx;
unsigned int pfc_busy;
unsigned int pfc_cycles;
unsigned int last_listen;
unsigned int last_ofdm_errors;
unsigned int last_cck_errors;
unsigned int sum_ofdm_errors;
unsigned int sum_cck_errors;
};
void ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode);
void ath5k_ani_mib_intr(struct ath5k_hw *ah);
void ath5k_ani_calibration(struct ath5k_hw *ah);
void ath5k_ani_phy_error_report(struct ath5k_hw *ah,
enum ath5k_phy_error_code phyerr);
/* for manual control */
void ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level);
void ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level);
void ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level);
void ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on);
void ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on);
void ath5k_ani_print_counters(struct ath5k_hw *ah);
#endif /* ANI_H */
......@@ -202,6 +202,8 @@
#define AR5K_TUNE_MAX_TXPOWER 63
#define AR5K_TUNE_DEFAULT_TXPOWER 25
#define AR5K_TUNE_TPC_TXPOWER false
#define ATH5K_TUNE_CALIBRATION_INTERVAL_FULL 10000 /* 10 sec */
#define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI 1000 /* 1 sec */
#define AR5K_INIT_CARR_SENSE_EN 1
......@@ -799,9 +801,9 @@ struct ath5k_athchan_2ghz {
* @AR5K_INT_TXURN: received when we should increase the TX trigger threshold
* We currently do increments on interrupt by
* (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2
* @AR5K_INT_MIB: Indicates the Management Information Base counters should be
* checked. We should do this with ath5k_hw_update_mib_counters() but
* it seems we should also then do some noise immunity work.
* @AR5K_INT_MIB: Indicates the either Management Information Base counters or
* one of the PHY error counters reached the maximum value and should be
* read and cleared.
* @AR5K_INT_RXPHY: RX PHY Error
* @AR5K_INT_RXKCM: RX Key cache miss
* @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a
......@@ -889,10 +891,11 @@ enum ath5k_int {
AR5K_INT_NOCARD = 0xffffffff
};
/* Software interrupts used for calibration */
enum ath5k_software_interrupt {
AR5K_SWI_FULL_CALIBRATION = 0x01,
AR5K_SWI_SHORT_CALIBRATION = 0x02,
/* mask which calibration is active at the moment */
enum ath5k_calibration_mask {
AR5K_CALIBRATION_FULL = 0x01,
AR5K_CALIBRATION_SHORT = 0x02,
AR5K_CALIBRATION_ANI = 0x04,
};
/*
......@@ -981,6 +984,8 @@ struct ath5k_capabilities {
struct {
u8 q_tx_num;
} cap_queues;
bool cap_has_phyerr_counters;
};
/* size of noise floor history (keep it a power of two) */
......@@ -991,6 +996,15 @@ struct ath5k_nfcal_hist
s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */
};
/**
* struct avg_val - Helper structure for average calculation
* @avg: contains the actual average value
* @avg_weight: is used internally during calculation to prevent rounding errors
*/
struct ath5k_avg_val {
int avg;
int avg_weight;
};
/***************************************\
HARDWARE ABSTRACTION LAYER STRUCTURE
......@@ -1095,17 +1109,18 @@ struct ath5k_hw {
struct ath5k_nfcal_hist ah_nfcal_hist;
/* average beacon RSSI in our BSS (used by ANI) */
struct ath5k_avg_val ah_beacon_rssi_avg;
/* noise floor from last periodic calibration */
s32 ah_noise_floor;
/* Calibration timestamp */
unsigned long ah_cal_tstamp;
/* Calibration interval (secs) */
u8 ah_cal_intval;
unsigned long ah_cal_next_full;
unsigned long ah_cal_next_ani;
/* Software interrupt mask */
u8 ah_swi_mask;
/* Calibration mask */
u8 ah_cal_mask;
/*
* Function pointers
......@@ -1163,8 +1178,7 @@ int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase);
bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah);
int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask);
void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
struct ieee80211_low_level_stats *stats);
void ath5k_hw_update_mib_counters(struct ath5k_hw *ah);
/* EEPROM access functions */
int ath5k_eeprom_init(struct ath5k_hw *ah);
......@@ -1256,7 +1270,6 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel);
void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah);
int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
struct ieee80211_channel *channel);
void ath5k_hw_calibration_poll(struct ath5k_hw *ah);
/* Spur mitigation */
bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
struct ieee80211_channel *channel);
......@@ -1308,4 +1321,27 @@ static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits)
return retval;
}
#define AVG_SAMPLES 8
#define AVG_FACTOR 1000
/**
* ath5k_moving_average - Exponentially weighted moving average
* @avg: average structure
* @val: current value
*
* This implementation make use of a struct ath5k_avg_val to prevent rounding
* errors.
*/
static inline struct ath5k_avg_val
ath5k_moving_average(const struct ath5k_avg_val avg, const int val)
{
struct ath5k_avg_val new;
new.avg_weight = avg.avg_weight ?
(((avg.avg_weight * ((AVG_SAMPLES) - 1)) +
(val * (AVG_FACTOR))) / (AVG_SAMPLES)) :
(val * (AVG_FACTOR));
new.avg = new.avg_weight / (AVG_FACTOR);
return new;
}
#endif
......@@ -124,6 +124,8 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
ah->ah_software_retry = false;
ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
ah->ah_noise_floor = -95; /* until first NF calibration is run */
sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO;
/*
* Find the mac version
......
......@@ -59,8 +59,8 @@
#include "base.h"
#include "reg.h"
#include "debug.h"
#include "ani.h"
static u8 ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */
static int modparam_nohwcrypt;
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
......@@ -365,6 +365,7 @@ static void ath5k_beacon_send(struct ath5k_softc *sc);
static void ath5k_beacon_config(struct ath5k_softc *sc);
static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
static void ath5k_tasklet_beacon(unsigned long data);
static void ath5k_tasklet_ani(unsigned long data);
static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
{
......@@ -830,6 +831,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc);
tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc);
ret = ath5k_eeprom_read_mac(ah, mac);
if (ret) {
......@@ -1635,7 +1637,6 @@ ath5k_txq_cleanup(struct ath5k_softc *sc)
sc->txqs[i].link);
}
}
ieee80211_wake_queues(sc->hw); /* XXX move to callers */
for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
if (sc->txqs[i].setup)
......@@ -1805,6 +1806,25 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
}
}
static void
ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi)
{
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
/* only beacons from our BSSID */
if (!ieee80211_is_beacon(mgmt->frame_control) ||
memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) != 0)
return;
ah->ah_beacon_rssi_avg = ath5k_moving_average(ah->ah_beacon_rssi_avg,
rssi);
/* in IBSS mode we should keep RSSI statistics per neighbour */
/* le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS */
}
/*
* Compute padding position. skb must contains an IEEE 802.11 frame
*/
......@@ -1923,6 +1943,8 @@ ath5k_tasklet_rx(unsigned long data)
sc->stats.rxerr_fifo++;
if (rs.rs_status & AR5K_RXERR_PHY) {
sc->stats.rxerr_phy++;
if (rs.rs_phyerr > 0 && rs.rs_phyerr < 32)
sc->stats.rxerr_phy_code[rs.rs_phyerr]++;
goto next;
}
if (rs.rs_status & AR5K_RXERR_DECRYPT) {
......@@ -2024,6 +2046,8 @@ ath5k_tasklet_rx(unsigned long data)
ath5k_debug_dump_skb(sc, skb, "RX ", 0);
ath5k_update_beacon_rssi(sc, skb, rs.rs_rssi);
/* check beacons in IBSS mode */
if (sc->opmode == NL80211_IFTYPE_ADHOC)
ath5k_check_ibss_tsf(sc, skb, rxs);
......@@ -2060,6 +2084,17 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
list_for_each_entry_safe(bf, bf0, &txq->q, list) {
ds = bf->desc;
/*
* It's possible that the hardware can say the buffer is
* completed when it hasn't yet loaded the ds_link from
* host memory and moved on. If there are more TX
* descriptors in the queue, wait for TXDP to change
* before processing this one.
*/
if (ath5k_hw_get_txdp(sc->ah, txq->qnum) == bf->daddr &&
!list_is_last(&bf->list, &txq->q))
break;
ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
if (unlikely(ret == -EINPROGRESS))
break;
......@@ -2095,7 +2130,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
info->status.rates[ts.ts_final_idx].count++;
if (unlikely(ts.ts_status)) {
sc->ll_stats.dot11ACKFailureCount++;
sc->stats.ack_fail++;
if (ts.ts_status & AR5K_TXERR_FILT) {
info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
sc->stats.txerr_filt++;
......@@ -2498,9 +2533,6 @@ ath5k_init(struct ath5k_softc *sc)
*/
ath5k_stop_locked(sc);
/* Set PHY calibration interval */
ah->ah_cal_intval = ath5k_calinterval;
/*
* The basic interface to setting the hardware in a good
* state is ``reset''. On return the hardware is known to
......@@ -2512,7 +2544,8 @@ ath5k_init(struct ath5k_softc *sc)
sc->curband = &sc->sbands[sc->curchan->band];
sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_SWI;
AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB;
ret = ath5k_reset(sc, NULL);
if (ret)
goto done;
......@@ -2526,8 +2559,7 @@ ath5k_init(struct ath5k_softc *sc)
for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
ath5k_hw_reset_key(ah, i);
/* Set ack to be sent at low bit-rates */
ath5k_hw_set_ack_bitrate_high(ah, false);
ath5k_hw_set_ack_bitrate_high(ah, true);
ret = 0;
done:
mmiowb();
......@@ -2624,12 +2656,33 @@ ath5k_stop_hw(struct ath5k_softc *sc)
tasklet_kill(&sc->restq);
tasklet_kill(&sc->calib);
tasklet_kill(&sc->beacontq);
tasklet_kill(&sc->ani_tasklet);
ath5k_rfkill_hw_stop(sc->ah);
return ret;
}
static void
ath5k_intr_calibration_poll(struct ath5k_hw *ah)
{
if (time_is_before_eq_jiffies(ah->ah_cal_next_ani) &&
!(ah->ah_cal_mask & AR5K_CALIBRATION_FULL)) {
/* run ANI only when full calibration is not active */
ah->ah_cal_next_ani = jiffies +
msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI);
tasklet_schedule(&ah->ah_sc->ani_tasklet);
} else if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) {
ah->ah_cal_next_full = jiffies +
msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL);
tasklet_schedule(&ah->ah_sc->calib);
}
/* we could use SWI to generate enough interrupts to meet our
* calibration interval requirements, if necessary:
* AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */
}
static irqreturn_t
ath5k_intr(int irq, void *dev_id)
{
......@@ -2653,7 +2706,20 @@ ath5k_intr(int irq, void *dev_id)
*/
tasklet_schedule(&sc->restq);
} else if (unlikely(status & AR5K_INT_RXORN)) {
tasklet_schedule(&sc->restq);
/*
* Receive buffers are full. Either the bus is busy or
* the CPU is not fast enough to process all received
* frames.
* Older chipsets need a reset to come out of this
* condition, but we treat it as RX for newer chips.
* We don't know exactly which versions need a reset -
* this guess is copied from the HAL.
*/
sc->stats.rxorn_intr++;
if (ah->ah_mac_srev < AR5K_SREV_AR5212)
tasklet_schedule(&sc->restq);
else
tasklet_schedule(&sc->rxtq);
} else {
if (status & AR5K_INT_SWBA) {
tasklet_hi_schedule(&sc->beacontq);
......@@ -2678,15 +2744,10 @@ ath5k_intr(int irq, void *dev_id)
if (status & AR5K_INT_BMISS) {
/* TODO */
}
if (status & AR5K_INT_SWI) {
tasklet_schedule(&sc->calib);
}
if (status & AR5K_INT_MIB) {
/*
* These stats are also used for ANI i think
* so how about updating them more often ?
*/
ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
sc->stats.mib_intr++;
ath5k_hw_update_mib_counters(ah);
ath5k_ani_mib_intr(ah);
}
if (status & AR5K_INT_GPIO)
tasklet_schedule(&sc->rf_kill.toggleq);
......@@ -2697,7 +2758,7 @@ ath5k_intr(int irq, void *dev_id)
if (unlikely(!counter))
ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
ath5k_hw_calibration_poll(ah);
ath5k_intr_calibration_poll(ah);
return IRQ_HANDLED;
}
......@@ -2721,8 +2782,7 @@ ath5k_tasklet_calibrate(unsigned long data)
struct ath5k_hw *ah = sc->ah;
/* Only full calibration for now */
if (ah->ah_swi_mask != AR5K_SWI_FULL_CALIBRATION)
return;
ah->ah_cal_mask |= AR5K_CALIBRATION_FULL;
/* Stop queues so that calibration
* doesn't interfere with tx */
......@@ -2738,18 +2798,29 @@ ath5k_tasklet_calibrate(unsigned long data)
* to load new gain values.
*/
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n");
ath5k_reset_wake(sc);
ath5k_reset(sc, sc->curchan);
}
if (ath5k_hw_phy_calibrate(ah, sc->curchan))
ATH5K_ERR(sc, "calibration of channel %u failed\n",
ieee80211_frequency_to_channel(
sc->curchan->center_freq));
ah->ah_swi_mask = 0;
/* Wake queues */
ieee80211_wake_queues(sc->hw);
ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL;
}
static void
ath5k_tasklet_ani(unsigned long data)
{
struct ath5k_softc *sc = (void *)data;
struct ath5k_hw *ah = sc->ah;
ah->ah_cal_mask |= AR5K_CALIBRATION_ANI;
ath5k_ani_calibration(ah);
ah->ah_cal_mask &= ~AR5K_CALIBRATION_ANI;
}
......@@ -2852,6 +2923,8 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
goto err;
}
ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode);
/*
* Change channels and update the h/w rate map if we're switching;
* e.g. 11a to 11b/g.
......@@ -3207,12 +3280,14 @@ ath5k_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats)
{
struct ath5k_softc *sc = hw->priv;
struct ath5k_hw *ah = sc->ah;
/* Force update */
ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
ath5k_hw_update_mib_counters(sc->ah);
memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats));
stats->dot11ACKFailureCount = sc->stats.ack_fail;
stats->dot11RTSFailureCount = sc->stats.rts_fail;
stats->dot11RTSSuccessCount = sc->stats.rts_ok;
stats->dot11FCSErrorCount = sc->stats.fcs_error;
return 0;
}
......
......@@ -50,6 +50,7 @@
#include "ath5k.h"
#include "debug.h"
#include "ani.h"
#include "../regd.h"
#include "../ath.h"
......@@ -105,14 +106,18 @@ struct ath5k_rfkill {
struct tasklet_struct toggleq;
};
/* statistics (only used for debugging now) */
/* statistics */
struct ath5k_statistics {
/* antenna use */
unsigned int antenna_rx[5]; /* frames count per antenna RX */
unsigned int antenna_tx[5]; /* frames count per antenna TX */
/* frame errors */
unsigned int rx_all_count; /* all RX frames, including errors */
unsigned int tx_all_count; /* all TX frames, including errors */
unsigned int rxerr_crc;
unsigned int rxerr_phy;
unsigned int rxerr_phy_code[32];
unsigned int rxerr_fifo;
unsigned int rxerr_decrypt;
unsigned int rxerr_mic;
......@@ -121,6 +126,16 @@ struct ath5k_statistics {
unsigned int txerr_retry;
unsigned int txerr_fifo;
unsigned int txerr_filt;
/* MIB counters */
unsigned int ack_fail;
unsigned int rts_fail;
unsigned int rts_ok;
unsigned int fcs_error;
unsigned int beacons;
unsigned int mib_intr;
unsigned int rxorn_intr;
};
#if CHAN_DEBUG
......@@ -135,7 +150,6 @@ struct ath5k_softc {
struct pci_dev *pdev; /* for dma mapping */
void __iomem *iobase; /* address of the device */
struct mutex lock; /* dev-level lock */
struct ieee80211_low_level_stats ll_stats;
struct ieee80211_hw *hw; /* IEEE 802.11 common */
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
struct ieee80211_channel channels[ATH_CHAN_MAX];
......@@ -211,6 +225,9 @@ struct ath5k_softc {
bool enable_beacon; /* true if beacons are on */
struct ath5k_statistics stats;
struct ath5k_ani_state ani_state;
struct tasklet_struct ani_tasklet; /* ANI calibration */
};
#define ath5k_hw_hasbssidmask(_ah) \
......
......@@ -109,6 +109,12 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
else
ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES;
/* newer hardware has PHY error counters */
if (ah->ah_mac_srev >= AR5K_SREV_AR5213A)
ah->ah_capabilities.cap_has_phyerr_counters = true;
else
ah->ah_capabilities.cap_has_phyerr_counters = false;
return 0;
}
......
......@@ -69,6 +69,7 @@ module_param_named(debug, ath5k_debug, uint, 0);
#include <linux/seq_file.h>
#include "reg.h"
#include "ani.h"
static struct dentry *ath5k_global_debugfs;
......@@ -307,6 +308,7 @@ static const struct {
{ ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" },
{ ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" },
{ ATH5K_DEBUG_TRACE, "trace", "trace function calls" },
{ ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" },
{ ATH5K_DEBUG_ANY, "all", "show all debug levels" },
};
......@@ -474,6 +476,7 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
struct ath5k_statistics *st = &sc->stats;
char buf[700];
unsigned int len = 0;
int i;
len += snprintf(buf+len, sizeof(buf)-len,
"RX\n---------------------\n");
......@@ -485,6 +488,13 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
st->rxerr_phy,
st->rx_all_count > 0 ?
st->rxerr_phy*100/st->rx_all_count : 0);
for (i = 0; i < 32; i++) {
if (st->rxerr_phy_code[i])
len += snprintf(buf+len, sizeof(buf)-len,
" phy_err[%d]\t%d\n",
i, st->rxerr_phy_code[i]);
}
len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n",
st->rxerr_fifo,
st->rx_all_count > 0 ?
......@@ -565,6 +575,160 @@ static const struct file_operations fops_frameerrors = {
};
/* debugfs: ani */
static ssize_t read_file_ani(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath5k_softc *sc = file->private_data;
struct ath5k_statistics *st = &sc->stats;
struct ath5k_ani_state *as = &sc->ani_state;
char buf[700];
unsigned int len = 0;
len += snprintf(buf+len, sizeof(buf)-len,
"HW has PHY error counters:\t%s\n",
sc->ah->ah_capabilities.cap_has_phyerr_counters ?
"yes" : "no");
len += snprintf(buf+len, sizeof(buf)-len,
"HW max spur immunity level:\t%d\n",
as->max_spur_level);
len += snprintf(buf+len, sizeof(buf)-len,
"\nANI state\n--------------------------------------------\n");
len += snprintf(buf+len, sizeof(buf)-len, "operating mode:\t\t\t");
switch (as->ani_mode) {
case ATH5K_ANI_MODE_OFF:
len += snprintf(buf+len, sizeof(buf)-len, "OFF\n");
break;
case ATH5K_ANI_MODE_MANUAL_LOW:
len += snprintf(buf+len, sizeof(buf)-len,
"MANUAL LOW\n");
break;
case ATH5K_ANI_MODE_MANUAL_HIGH:
len += snprintf(buf+len, sizeof(buf)-len,
"MANUAL HIGH\n");
break;
case ATH5K_ANI_MODE_AUTO:
len += snprintf(buf+len, sizeof(buf)-len, "AUTO\n");
break;
default:
len += snprintf(buf+len, sizeof(buf)-len,
"??? (not good)\n");
break;
}
len += snprintf(buf+len, sizeof(buf)-len,
"noise immunity level:\t\t%d\n",
as->noise_imm_level);
len += snprintf(buf+len, sizeof(buf)-len,
"spur immunity level:\t\t%d\n",
as->spur_level);
len += snprintf(buf+len, sizeof(buf)-len, "firstep level:\t\t\t%d\n",
as->firstep_level);
len += snprintf(buf+len, sizeof(buf)-len,
"OFDM weak signal detection:\t%s\n",
as->ofdm_weak_sig ? "on" : "off");
len += snprintf(buf+len, sizeof(buf)-len,
"CCK weak signal detection:\t%s\n",
as->cck_weak_sig ? "on" : "off");
len += snprintf(buf+len, sizeof(buf)-len,
"\nMIB INTERRUPTS:\t\t%u\n",
st->mib_intr);
len += snprintf(buf+len, sizeof(buf)-len,
"beacon RSSI average:\t%d\n",
sc->ah->ah_beacon_rssi_avg.avg);
len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n",
as->pfc_tx,
as->pfc_cycles > 0 ?
as->pfc_tx*100/as->pfc_cycles : 0);
len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n",
as->pfc_rx,
as->pfc_cycles > 0 ?
as->pfc_rx*100/as->pfc_cycles : 0);
len += snprintf(buf+len, sizeof(buf)-len, "profcnt busy\t\t%u\t(%d%%)\n",
as->pfc_busy,
as->pfc_cycles > 0 ?
as->pfc_busy*100/as->pfc_cycles : 0);
len += snprintf(buf+len, sizeof(buf)-len, "profcnt cycles\t\t%u\n",
as->pfc_cycles);
len += snprintf(buf+len, sizeof(buf)-len,
"listen time\t\t%d\tlast: %d\n",
as->listen_time, as->last_listen);
len += snprintf(buf+len, sizeof(buf)-len,
"OFDM errors\t\t%u\tlast: %u\tsum: %u\n",
as->ofdm_errors, as->last_ofdm_errors,
as->sum_ofdm_errors);
len += snprintf(buf+len, sizeof(buf)-len,
"CCK errors\t\t%u\tlast: %u\tsum: %u\n",
as->cck_errors, as->last_cck_errors,
as->sum_cck_errors);
len += snprintf(buf+len, sizeof(buf)-len,
"AR5K_PHYERR_CNT1\t%x\t(=%d)\n",
ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1),
ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1)));
len += snprintf(buf+len, sizeof(buf)-len,
"AR5K_PHYERR_CNT2\t%x\t(=%d)\n",
ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2),
ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2)));
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t write_file_ani(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct ath5k_softc *sc = file->private_data;
char buf[20];
if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
return -EFAULT;
if (strncmp(buf, "sens-low", 8) == 0) {
ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_HIGH);
} else if (strncmp(buf, "sens-high", 9) == 0) {
ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_LOW);
} else if (strncmp(buf, "ani-off", 7) == 0) {
ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_OFF);
} else if (strncmp(buf, "ani-on", 6) == 0) {
ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_AUTO);
} else if (strncmp(buf, "noise-low", 9) == 0) {
ath5k_ani_set_noise_immunity_level(sc->ah, 0);
} else if (strncmp(buf, "noise-high", 10) == 0) {
ath5k_ani_set_noise_immunity_level(sc->ah,
ATH5K_ANI_MAX_NOISE_IMM_LVL);
} else if (strncmp(buf, "spur-low", 8) == 0) {
ath5k_ani_set_spur_immunity_level(sc->ah, 0);
} else if (strncmp(buf, "spur-high", 9) == 0) {
ath5k_ani_set_spur_immunity_level(sc->ah,
sc->ani_state.max_spur_level);
} else if (strncmp(buf, "fir-low", 7) == 0) {
ath5k_ani_set_firstep_level(sc->ah, 0);
} else if (strncmp(buf, "fir-high", 8) == 0) {
ath5k_ani_set_firstep_level(sc->ah, ATH5K_ANI_MAX_FIRSTEP_LVL);
} else if (strncmp(buf, "ofdm-off", 8) == 0) {
ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, false);
} else if (strncmp(buf, "ofdm-on", 7) == 0) {
ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, true);
} else if (strncmp(buf, "cck-off", 7) == 0) {
ath5k_ani_set_cck_weak_signal_detection(sc->ah, false);
} else if (strncmp(buf, "cck-on", 6) == 0) {
ath5k_ani_set_cck_weak_signal_detection(sc->ah, true);
}
return count;
}
static const struct file_operations fops_ani = {
.read = read_file_ani,
.write = write_file_ani,
.open = ath5k_debugfs_open,
.owner = THIS_MODULE,
};
/* init */
void
......@@ -603,6 +767,11 @@ ath5k_debug_init_device(struct ath5k_softc *sc)
S_IWUSR | S_IRUSR,
sc->debug.debugfs_phydir, sc,
&fops_frameerrors);
sc->debug.debugfs_ani = debugfs_create_file("ani",
S_IWUSR | S_IRUSR,
sc->debug.debugfs_phydir, sc,
&fops_ani);
}
void
......@@ -620,6 +789,7 @@ ath5k_debug_finish_device(struct ath5k_softc *sc)
debugfs_remove(sc->debug.debugfs_reset);
debugfs_remove(sc->debug.debugfs_antenna);
debugfs_remove(sc->debug.debugfs_frameerrors);
debugfs_remove(sc->debug.debugfs_ani);
debugfs_remove(sc->debug.debugfs_phydir);
}
......
......@@ -76,6 +76,7 @@ struct ath5k_dbg_info {
struct dentry *debugfs_reset;
struct dentry *debugfs_antenna;
struct dentry *debugfs_frameerrors;
struct dentry *debugfs_ani;
};
/**
......@@ -115,6 +116,7 @@ enum ath5k_debug_level {
ATH5K_DEBUG_DUMP_TX = 0x00000200,
ATH5K_DEBUG_DUMPBANDS = 0x00000400,
ATH5K_DEBUG_TRACE = 0x00001000,
ATH5K_DEBUG_ANI = 0x00002000,
ATH5K_DEBUG_ANY = 0xffffffff
};
......
......@@ -645,6 +645,7 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
rs->rs_status |= AR5K_RXERR_PHY;
rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1,
AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
ath5k_ani_phy_error_report(ah, rs->rs_phyerr);
}
if (rx_status->rx_status_1 &
......
......@@ -112,15 +112,32 @@ struct ath5k_hw_rx_error {
#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00
#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8
/* PHY Error codes */
#define AR5K_DESC_RX_PHY_ERROR_NONE 0x00
#define AR5K_DESC_RX_PHY_ERROR_TIMING 0x20
#define AR5K_DESC_RX_PHY_ERROR_PARITY 0x40
#define AR5K_DESC_RX_PHY_ERROR_RATE 0x60
#define AR5K_DESC_RX_PHY_ERROR_LENGTH 0x80
#define AR5K_DESC_RX_PHY_ERROR_64QAM 0xa0
#define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0
#define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0
/**
* enum ath5k_phy_error_code - PHY Error codes
*/
enum ath5k_phy_error_code {
AR5K_RX_PHY_ERROR_UNDERRUN = 0, /* Transmit underrun */
AR5K_RX_PHY_ERROR_TIMING = 1, /* Timing error */
AR5K_RX_PHY_ERROR_PARITY = 2, /* Illegal parity */
AR5K_RX_PHY_ERROR_RATE = 3, /* Illegal rate */
AR5K_RX_PHY_ERROR_LENGTH = 4, /* Illegal length */
AR5K_RX_PHY_ERROR_RADAR = 5, /* Radar detect */
AR5K_RX_PHY_ERROR_SERVICE = 6, /* Illegal service */
AR5K_RX_PHY_ERROR_TOR = 7, /* Transmit override receive */
/* these are specific to the 5212 */
AR5K_RX_PHY_ERROR_OFDM_TIMING = 17,
AR5K_RX_PHY_ERROR_OFDM_SIGNAL_PARITY = 18,
AR5K_RX_PHY_ERROR_OFDM_RATE_ILLEGAL = 19,
AR5K_RX_PHY_ERROR_OFDM_LENGTH_ILLEGAL = 20,
AR5K_RX_PHY_ERROR_OFDM_POWER_DROP = 21,
AR5K_RX_PHY_ERROR_OFDM_SERVICE = 22,
AR5K_RX_PHY_ERROR_OFDM_RESTART = 23,
AR5K_RX_PHY_ERROR_CCK_TIMING = 25,
AR5K_RX_PHY_ERROR_CCK_HEADER_CRC = 26,
AR5K_RX_PHY_ERROR_CCK_RATE_ILLEGAL = 27,
AR5K_RX_PHY_ERROR_CCK_SERVICE = 30,
AR5K_RX_PHY_ERROR_CCK_RESTART = 31,
};
/*
* 5210/5211 hardware 2-word TX control descriptor
......
......@@ -113,39 +113,26 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
}
/**
* ath5k_hw_update - Update mib counters (mac layer statistics)
* ath5k_hw_update - Update MIB counters (mac layer statistics)
*
* @ah: The &struct ath5k_hw
* @stats: The &struct ieee80211_low_level_stats we use to track
* statistics on the driver
*
* Reads MIB counters from PCU and updates sw statistics. Must be
* called after a MIB interrupt.
* Reads MIB counters from PCU and updates sw statistics. Is called after a
* MIB interrupt, because one of these counters might have reached their maximum
* and triggered the MIB interrupt, to let us read and clear the counter.
*
* Is called in interrupt context!
*/
void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
struct ieee80211_low_level_stats *stats)
void ath5k_hw_update_mib_counters(struct ath5k_hw *ah)
{
ATH5K_TRACE(ah->ah_sc);
struct ath5k_statistics *stats = &ah->ah_sc->stats;
/* Read-And-Clear */
stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
/* XXX: Should we use this to track beacon count ?
* -we read it anyway to clear the register */
ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
/* Reset profile count registers on 5212*/
if (ah->ah_version == AR5K_AR5212) {
ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX);
ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX);
ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
}
/* TODO: Handle ANI stats */
stats->ack_fail += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
stats->rts_fail += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
stats->rts_ok += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
stats->fcs_error += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
}
/**
......@@ -167,9 +154,9 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
else {
u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
if (high)
AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
else
AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
else
AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
}
}
......@@ -392,7 +379,6 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
* (ACK etc).
*
* NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma
* TODO: Init ANI here
*/
void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
{
......
......@@ -980,7 +980,7 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
return -EINVAL;
data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8);
} else if ((c - (c % 5)) != 2 || c > 5435) {
} else if ((c % 5) != 2 || c > 5435) {
if (!(c % 20) && c >= 5120) {
data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
data2 = ath5k_hw_bitswap(3, 2);
......@@ -993,7 +993,7 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
} else
return -EINVAL;
} else {
data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
data0 = ath5k_hw_bitswap((10 * (c - 2 - 4800)) / 25 + 1, 8);
data2 = ath5k_hw_bitswap(0, 2);
}
......@@ -1021,7 +1021,7 @@ static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah,
data0 = ath5k_hw_bitswap((c - 2272), 8);
data2 = 0;
/* ? 5GHz ? */
} else if ((c - (c % 5)) != 2 || c > 5435) {
} else if ((c % 5) != 2 || c > 5435) {
if (!(c % 20) && c < 5120)
data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
else if (!(c % 10))
......@@ -1032,7 +1032,7 @@ static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah,
return -EINVAL;
data2 = ath5k_hw_bitswap(1, 2);
} else {
data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
data0 = ath5k_hw_bitswap((10 * (c - 2 - 4800)) / 25 + 1, 8);
data2 = ath5k_hw_bitswap(0, 2);
}
......@@ -1103,28 +1103,6 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
PHY calibration
\*****************/
void
ath5k_hw_calibration_poll(struct ath5k_hw *ah)
{
/* Calibration interval in jiffies */
unsigned long cal_intval;
cal_intval = msecs_to_jiffies(ah->ah_cal_intval * 1000);
/* Initialize timestamp if needed */
if (!ah->ah_cal_tstamp)
ah->ah_cal_tstamp = jiffies;
/* For now we always do full calibration
* Mark software interrupt mask and fire software
* interrupt (bit gets auto-cleared) */
if (time_is_before_eq_jiffies(ah->ah_cal_tstamp + cal_intval)) {
ah->ah_cal_tstamp = jiffies;
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);
......@@ -1411,7 +1389,10 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
i_coff = (-iq_corr) / i_coffd;
i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */
q_coff = (i_pwr / q_coffd) - 128;
if (ah->ah_version == AR5K_AR5211)
q_coff = (i_pwr / q_coffd) - 64;
else
q_coff = (i_pwr / q_coffd) - 128;
q_coff = clamp(q_coff, -16, 15); /* signed 5 bit */
ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
......@@ -2580,7 +2561,7 @@ ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah,
max_idx = (pdadc_n < table_size) ? pdadc_n : table_size;
/* Fill pdadc_out table */
while (pdadc_0 < max_idx)
while (pdadc_0 < max_idx && pdadc_i < 128)
pdadc_out[pdadc_i++] = pdadc_tmp[pdadc_0++];
/* Need to extrapolate above this pdgain? */
......
......@@ -212,10 +212,10 @@
* MIB control register
*/
#define AR5K_MIBC 0x0040 /* Register Address */
#define AR5K_MIBC_COW 0x00000001 /* Warn test indicator */
#define AR5K_MIBC_COW 0x00000001 /* Counter Overflow Warning */
#define AR5K_MIBC_FMC 0x00000002 /* Freeze MIB Counters */
#define AR5K_MIBC_CMC 0x00000004 /* Clean MIB Counters */
#define AR5K_MIBC_MCS 0x00000008 /* MIB counter strobe */
#define AR5K_MIBC_CMC 0x00000004 /* Clear MIB Counters */
#define AR5K_MIBC_MCS 0x00000008 /* MIB counter strobe, increment all */
/*
* Timeout prescale register
......@@ -1139,8 +1139,8 @@
#define AR5K_STA_ID1_DEFAULT_ANTENNA 0x00200000 /* Use default antenna */
#define AR5K_STA_ID1_DESC_ANTENNA 0x00400000 /* Update antenna from descriptor */
#define AR5K_STA_ID1_RTS_DEF_ANTENNA 0x00800000 /* Use default antenna for RTS */
#define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mbit/s for ACK/CTS */
#define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate for ACK/CTS [5211+] */
#define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Rate to use for ACK/CTS. 0: highest mandatory rate <= RX rate; 1: 1Mbps in B mode */
#define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* 802.11b base rate. 0: 1, 2, 5.5 and 11Mbps; 1: 1 and 2Mbps. [5211+] */
#define AR5K_STA_ID1_SELFGEN_DEF_ANT 0x04000000 /* Use def. antenna for self generated frames */
#define AR5K_STA_ID1_CRYPT_MIC_EN 0x08000000 /* Enable MIC */
#define AR5K_STA_ID1_KEYSRCH_MODE 0x10000000 /* Look up key when key id != 0 */
......@@ -1516,7 +1516,14 @@
AR5K_NAV_5210 : AR5K_NAV_5211)
/*
* RTS success register
* MIB counters:
*
* max value is 0xc000, if this is reached we get a MIB interrupt.
* they can be controlled via AR5K_MIBC and are cleared on read.
*/
/*
* RTS success (MIB counter)
*/
#define AR5K_RTS_OK_5210 0x8090
#define AR5K_RTS_OK_5211 0x8088
......@@ -1524,7 +1531,7 @@
AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211)
/*
* RTS failure register
* RTS failure (MIB counter)
*/
#define AR5K_RTS_FAIL_5210 0x8094
#define AR5K_RTS_FAIL_5211 0x808c
......@@ -1532,7 +1539,7 @@
AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211)
/*
* ACK failure register
* ACK failure (MIB counter)
*/
#define AR5K_ACK_FAIL_5210 0x8098
#define AR5K_ACK_FAIL_5211 0x8090
......@@ -1540,7 +1547,7 @@
AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211)
/*
* FCS failure register
* FCS failure (MIB counter)
*/
#define AR5K_FCS_FAIL_5210 0x809c
#define AR5K_FCS_FAIL_5211 0x8094
......@@ -1667,11 +1674,17 @@
/*
* Profile count registers
*
* These registers can be cleared and freezed with ATH5K_MIBC, but they do not
* generate a MIB interrupt.
* Instead of overflowing, they shift by one bit to the right. All registers
* shift together, i.e. when one reaches the max, all shift at the same time by
* one bit to the right. This way we should always get consistent values.
*/
#define AR5K_PROFCNT_TX 0x80ec /* Tx count */
#define AR5K_PROFCNT_RX 0x80f0 /* Rx count */
#define AR5K_PROFCNT_RXCLR 0x80f4 /* Clear Rx count */
#define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle count (?) */
#define AR5K_PROFCNT_RXCLR 0x80f4 /* Busy count */
#define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle counter */
/*
* Quiet period control registers
......@@ -1758,7 +1771,7 @@
#define AR5K_CCK_FIL_CNT 0x8128
/*
* PHY Error Counters (?)
* PHY Error Counters (same masks as AR5K_PHY_ERR_FIL)
*/
#define AR5K_PHYERR_CNT1 0x812c
#define AR5K_PHYERR_CNT1_MASK 0x8130
......@@ -1766,6 +1779,9 @@
#define AR5K_PHYERR_CNT2 0x8134
#define AR5K_PHYERR_CNT2_MASK 0x8138
/* if the PHY Error Counters reach this maximum, we get MIB interrupts */
#define ATH5K_PHYERR_CNT_MAX 0x00c00000
/*
* TSF Threshold register (?)
*/
......
......@@ -47,6 +47,7 @@ static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
}
static struct ath_bus_ops ath_ahb_bus_ops = {
.ath_bus_type = ATH_AHB,
.read_cachesize = ath_ahb_read_cachesize,
.eeprom_read = ath_ahb_eeprom_read,
};
......
......@@ -178,9 +178,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
#define BAW_WITHIN(_start, _bawsz, _seqno) \
((((_seqno) - (_start)) & 4095) < (_bawsz))
#define ATH_DS_BA_SEQ(_ds) ((_ds)->ds_us.tx.ts_seqnum)
#define ATH_DS_BA_BITMAP(_ds) (&(_ds)->ds_us.tx.ba_low)
#define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA)
#define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)])
#define ATH_TX_COMPLETE_POLL_INT 1000
......@@ -483,7 +480,6 @@ struct ath_softc {
bool ps_enabled;
bool ps_idle;
unsigned long ps_usecount;
enum ath9k_int imask;
struct ath_config config;
struct ath_rx rx;
......
......@@ -524,6 +524,7 @@ static void ath9k_beacon_init(struct ath_softc *sc,
static void ath_beacon_config_ap(struct ath_softc *sc,
struct ath_beacon_config *conf)
{
struct ath_hw *ah = sc->sc_ah;
u32 nexttbtt, intval;
/* NB: the beacon interval is kept internally in TU's */
......@@ -539,15 +540,15 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
* prepare beacon frames.
*/
intval |= ATH9K_BEACON_ENA;
sc->imask |= ATH9K_INT_SWBA;
ah->imask |= ATH9K_INT_SWBA;
ath_beaconq_config(sc);
/* Set the computed AP beacon timers */
ath9k_hw_set_interrupts(sc->sc_ah, 0);
ath9k_hw_set_interrupts(ah, 0);
ath9k_beacon_init(sc, nexttbtt, intval);
sc->beacon.bmisscnt = 0;
ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
ath9k_hw_set_interrupts(ah, ah->imask);
/* Clear the reset TSF flag, so that subsequent beacon updation
will not reset the HW TSF. */
......@@ -566,7 +567,8 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
static void ath_beacon_config_sta(struct ath_softc *sc,
struct ath_beacon_config *conf)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_beacon_state bs;
int dtimperiod, dtimcount, sleepduration;
int cfpperiod, cfpcount;
......@@ -605,7 +607,7 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
* Pull nexttbtt forward to reflect the current
* TSF and calculate dtim+cfp state for the result.
*/
tsf = ath9k_hw_gettsf64(sc->sc_ah);
tsf = ath9k_hw_gettsf64(ah);
tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
num_beacons = tsftu / intval + 1;
......@@ -678,17 +680,18 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
/* Set the computed STA beacon timers */
ath9k_hw_set_interrupts(sc->sc_ah, 0);
ath9k_hw_set_sta_beacon_timers(sc->sc_ah, &bs);
sc->imask |= ATH9K_INT_BMISS;
ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
ath9k_hw_set_interrupts(ah, 0);
ath9k_hw_set_sta_beacon_timers(ah, &bs);
ah->imask |= ATH9K_INT_BMISS;
ath9k_hw_set_interrupts(ah, ah->imask);
}
static void ath_beacon_config_adhoc(struct ath_softc *sc,
struct ath_beacon_config *conf,
struct ieee80211_vif *vif)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
u64 tsf;
u32 tsftu, intval, nexttbtt;
......@@ -703,7 +706,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
else if (intval)
nexttbtt = roundup(nexttbtt, intval);
tsf = ath9k_hw_gettsf64(sc->sc_ah);
tsf = ath9k_hw_gettsf64(ah);
tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE;
do {
nexttbtt += intval;
......@@ -719,20 +722,20 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
* self-linked tx descriptor and let the hardware deal with things.
*/
intval |= ATH9K_BEACON_ENA;
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL))
sc->imask |= ATH9K_INT_SWBA;
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_VEOL))
ah->imask |= ATH9K_INT_SWBA;
ath_beaconq_config(sc);
/* Set the computed ADHOC beacon timers */
ath9k_hw_set_interrupts(sc->sc_ah, 0);
ath9k_hw_set_interrupts(ah, 0);
ath9k_beacon_init(sc, nexttbtt, intval);
sc->beacon.bmisscnt = 0;
ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
ath9k_hw_set_interrupts(ah, ah->imask);
/* FIXME: Handle properly when vif is NULL */
if (vif && sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)
if (vif && ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)
ath_beacon_start_adhoc(sc, vif);
}
......
......@@ -18,6 +18,7 @@
/* We can tune this as we go by monitoring really low values */
#define ATH9K_NF_TOO_LOW -60
#define AR9285_CLCAL_REDO_THRESH 1
/* AR5416 may return very high value (like -31 dBm), in those cases the nf
* is incorrect and we should use the static NF value. Later we can try to
......@@ -1091,7 +1092,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)
static bool ar9285_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
......@@ -1132,6 +1133,62 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
return true;
}
static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
{
int i;
u_int32_t txgain_max;
u_int32_t clc_gain, gain_mask = 0, clc_num = 0;
u_int32_t reg_clc_I0, reg_clc_Q0;
u_int32_t i0_num = 0;
u_int32_t q0_num = 0;
u_int32_t total_num = 0;
u_int32_t reg_rf2g5_org;
bool retv = true;
if (!(ar9285_cl_cal(ah, chan)))
return false;
txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7),
AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX);
for (i = 0; i < (txgain_max+1); i++) {
clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) &
AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S;
if (!(gain_mask & (1 << clc_gain))) {
gain_mask |= (1 << clc_gain);
clc_num++;
}
}
for (i = 0; i < clc_num; i++) {
reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
& AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S;
reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
& AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S;
if (reg_clc_I0 == 0)
i0_num++;
if (reg_clc_Q0 == 0)
q0_num++;
}
total_num = i0_num + q0_num;
if (total_num > AR9285_CLCAL_REDO_THRESH) {
reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5);
if (AR_SREV_9285E_20(ah)) {
REG_WRITE(ah, AR9285_RF2G5,
(reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
AR9285_RF2G5_IC50TX_XE_SET);
} else {
REG_WRITE(ah, AR9285_RF2G5,
(reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
AR9285_RF2G5_IC50TX_SET);
}
retv = ar9285_cl_cal(ah, chan);
REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org);
}
return retv;
}
bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
......
......@@ -255,7 +255,8 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
keyix = rx_stats->rs_keyix;
if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) {
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) {
......@@ -303,88 +304,6 @@ int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
}
EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype);
/*
* Calculate the RX filter to be set in the HW.
*/
u32 ath9k_cmn_calcrxfilter(struct ieee80211_hw *hw, struct ath_hw *ah,
unsigned int rxfilter)
{
#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
u32 rfilt;
rfilt = (ath9k_hw_getrxfilter(ah) & RX_FILTER_PRESERVE)
| ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
| ATH9K_RX_FILTER_MCAST;
/* If not a STA, enable processing of Probe Requests */
if (ah->opmode != NL80211_IFTYPE_STATION)
rfilt |= ATH9K_RX_FILTER_PROBEREQ;
/*
* Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station
* mode interface or when in monitor mode. AP mode does not need this
* since it receives all in-BSS frames anyway.
*/
if (((ah->opmode != NL80211_IFTYPE_AP) &&
(rxfilter & FIF_PROMISC_IN_BSS)) ||
(ah->opmode == NL80211_IFTYPE_MONITOR))
rfilt |= ATH9K_RX_FILTER_PROM;
if (rxfilter & FIF_CONTROL)
rfilt |= ATH9K_RX_FILTER_CONTROL;
if ((ah->opmode == NL80211_IFTYPE_STATION) &&
!(rxfilter & FIF_BCN_PRBRESP_PROMISC))
rfilt |= ATH9K_RX_FILTER_MYBEACON;
else
rfilt |= ATH9K_RX_FILTER_BEACON;
if ((AR_SREV_9280_10_OR_LATER(ah) ||
AR_SREV_9285_10_OR_LATER(ah)) &&
(ah->opmode == NL80211_IFTYPE_AP) &&
(rxfilter & FIF_PSPOLL))
rfilt |= ATH9K_RX_FILTER_PSPOLL;
if (conf_is_ht(&hw->conf))
rfilt |= ATH9K_RX_FILTER_COMP_BAR;
return rfilt;
#undef RX_FILTER_PRESERVE
}
EXPORT_SYMBOL(ath9k_cmn_calcrxfilter);
/*
* Recv initialization for opmode change.
*/
void ath9k_cmn_opmode_init(struct ieee80211_hw *hw, struct ath_hw *ah,
unsigned int rxfilter)
{
struct ath_common *common = ath9k_hw_common(ah);
u32 rfilt, mfilt[2];
/* configure rx filter */
rfilt = ath9k_cmn_calcrxfilter(hw, ah, rxfilter);
ath9k_hw_setrxfilter(ah, rfilt);
/* configure bssid mask */
if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
ath_hw_setbssidmask(common);
/* configure operational mode */
ath9k_hw_setopmode(ah);
/* Handle any link-level address change. */
ath9k_hw_setmac(ah, common->macaddr);
/* calculate and install multicast filter */
mfilt[0] = mfilt[1] = ~0;
ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
}
EXPORT_SYMBOL(ath9k_cmn_opmode_init);
static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type)
{
......
......@@ -128,10 +128,6 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
int ath9k_cmn_padpos(__le16 frame_control);
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
u32 ath9k_cmn_calcrxfilter(struct ieee80211_hw *hw, struct ath_hw *ah,
unsigned int rxfilter);
void ath9k_cmn_opmode_init(struct ieee80211_hw *hw, struct ath_hw *ah,
unsigned int rxfilter);
void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
struct ath9k_channel *ichan);
struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
......
......@@ -157,10 +157,10 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
"txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n",
(val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
len += snprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x \n",
len += snprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x\n",
REG_READ_D(ah, AR_OBS_BUS_1));
len += snprintf(buf + len, DMA_BUF_LEN - len,
"AR_CR: 0x%x \n", REG_READ_D(ah, AR_CR));
"AR_CR: 0x%x\n", REG_READ_D(ah, AR_CR));
ath9k_ps_restore(sc);
......@@ -557,10 +557,8 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
}
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf)
struct ath_buf *bf, struct ath_tx_status *ts)
{
struct ath_desc *ds = bf->bf_desc;
if (bf_isampdu(bf)) {
if (bf_isxretried(bf))
TX_STAT_INC(txq->axq_qnum, a_xretries);
......@@ -570,17 +568,17 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
TX_STAT_INC(txq->axq_qnum, completed);
}
if (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO)
if (ts->ts_status & ATH9K_TXERR_FIFO)
TX_STAT_INC(txq->axq_qnum, fifo_underrun);
if (ds->ds_txstat.ts_status & ATH9K_TXERR_XTXOP)
if (ts->ts_status & ATH9K_TXERR_XTXOP)
TX_STAT_INC(txq->axq_qnum, xtxop);
if (ds->ds_txstat.ts_status & ATH9K_TXERR_TIMER_EXPIRED)
if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED)
TX_STAT_INC(txq->axq_qnum, timer_exp);
if (ds->ds_txstat.ts_flags & ATH9K_TX_DESC_CFG_ERR)
if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR)
TX_STAT_INC(txq->axq_qnum, desc_cfg_err);
if (ds->ds_txstat.ts_flags & ATH9K_TX_DATA_UNDERRUN)
if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN)
TX_STAT_INC(txq->axq_qnum, data_underrun);
if (ds->ds_txstat.ts_flags & ATH9K_TX_DELIM_UNDERRUN)
if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
TX_STAT_INC(txq->axq_qnum, delim_underrun);
}
......@@ -663,30 +661,29 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
#undef PHY_ERR
}
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_buf *bf)
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
{
#define RX_STAT_INC(c) sc->debug.stats.rxstats.c++
#define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++
struct ath_desc *ds = bf->bf_desc;
u32 phyerr;
if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC)
if (rs->rs_status & ATH9K_RXERR_CRC)
RX_STAT_INC(crc_err);
if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT)
if (rs->rs_status & ATH9K_RXERR_DECRYPT)
RX_STAT_INC(decrypt_crc_err);
if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC)
if (rs->rs_status & ATH9K_RXERR_MIC)
RX_STAT_INC(mic_err);
if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_PRE)
if (rs->rs_status & ATH9K_RX_DELIM_CRC_PRE)
RX_STAT_INC(pre_delim_crc_err);
if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_POST)
if (rs->rs_status & ATH9K_RX_DELIM_CRC_POST)
RX_STAT_INC(post_delim_crc_err);
if (ds->ds_rxstat.rs_status & ATH9K_RX_DECRYPT_BUSY)
if (rs->rs_status & ATH9K_RX_DECRYPT_BUSY)
RX_STAT_INC(decrypt_busy_err);
if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) {
if (rs->rs_status & ATH9K_RXERR_PHY) {
RX_STAT_INC(phy_err);
phyerr = ds->ds_rxstat.rs_phyerr & 0x24;
phyerr = rs->rs_phyerr & 0x24;
RX_PHY_ERR_INC(phyerr);
}
......
......@@ -167,8 +167,8 @@ void ath9k_debug_remove_root(void);
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
void ath_debug_stat_rc(struct ath_softc *sc, int final_rate);
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf);
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_buf *bf);
struct ath_buf *bf, struct ath_tx_status *ts);
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries, u8 per);
......@@ -204,12 +204,13 @@ static inline void ath_debug_stat_rc(struct ath_softc *sc,
static inline void ath_debug_stat_tx(struct ath_softc *sc,
struct ath_txq *txq,
struct ath_buf *bf)
struct ath_buf *bf,
struct ath_tx_status *ts)
{
}
static inline void ath_debug_stat_rx(struct ath_softc *sc,
struct ath_buf *bf)
struct ath_rx_status *rs)
{
}
......
......@@ -43,7 +43,7 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) {
ath_print(common, ATH_DBG_EEPROM,
"Unable to read eeprom region \n");
"Unable to read eeprom region\n");
return false;
}
eep_data++;
......
......@@ -44,7 +44,7 @@ static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah)
if (!ath9k_hw_nvram_read(common,
addr + eep_start_loc, eep_data)) {
ath_print(common, ATH_DBG_EEPROM,
"Unable to read eeprom region \n");
"Unable to read eeprom region\n");
return false;
}
eep_data++;
......
......@@ -283,22 +283,17 @@ static void ath9k_gen_timer_start(struct ath_hw *ah,
u32 timer_next,
u32 timer_period)
{
struct ath_common *common = ath9k_hw_common(ah);
struct ath_softc *sc = (struct ath_softc *) common->priv;
ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period);
if ((sc->imask & ATH9K_INT_GENTIMER) == 0) {
if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
ath9k_hw_set_interrupts(ah, 0);
sc->imask |= ATH9K_INT_GENTIMER;
ath9k_hw_set_interrupts(ah, sc->imask);
ah->imask |= ATH9K_INT_GENTIMER;
ath9k_hw_set_interrupts(ah, ah->imask);
}
}
static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
{
struct ath_common *common = ath9k_hw_common(ah);
struct ath_softc *sc = (struct ath_softc *) common->priv;
struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
ath9k_hw_gen_timer_stop(ah, timer);
......@@ -306,8 +301,8 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
/* if no timer is enabled, turn off interrupt mask */
if (timer_table->timer_mask.val == 0) {
ath9k_hw_set_interrupts(ah, 0);
sc->imask &= ~ATH9K_INT_GENTIMER;
ath9k_hw_set_interrupts(ah, sc->imask);
ah->imask &= ~ATH9K_INT_GENTIMER;
ath9k_hw_set_interrupts(ah, ah->imask);
}
}
......@@ -364,7 +359,7 @@ static void ath_btcoex_no_stomp_timer(void *arg)
bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN;
ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
"no stomp timer running \n");
"no stomp timer running\n");
spin_lock_bh(&btcoex->btcoex_lock);
......
......@@ -21,6 +21,7 @@
static struct usb_device_id ath9k_hif_usb_ids[] = {
ATH9K_FW_USB_DEV(0x9271, "ar9271.fw"),
ATH9K_FW_USB_DEV(0x1006, "ar9271.fw"),
{ },
};
......@@ -31,27 +32,15 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev);
static void hif_usb_regout_cb(struct urb *urb)
{
struct cmd_buf *cmd = (struct cmd_buf *)urb->context;
struct hif_device_usb *hif_dev = cmd->hif_dev;
if (!hif_dev) {
usb_free_urb(urb);
if (cmd) {
if (cmd->skb)
dev_kfree_skb_any(cmd->skb);
kfree(cmd);
}
return;
}
switch (urb->status) {
case 0:
break;
case -ENOENT:
case -ECONNRESET:
break;
case -ENODEV:
case -ESHUTDOWN:
return;
goto free;
default:
break;
}
......@@ -60,8 +49,12 @@ static void hif_usb_regout_cb(struct urb *urb)
ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle,
cmd->skb, 1);
kfree(cmd);
usb_free_urb(urb);
}
return;
free:
kfree_skb(cmd->skb);
kfree(cmd);
}
static int hif_usb_send_regout(struct hif_device_usb *hif_dev,
......@@ -89,11 +82,13 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev,
skb->data, skb->len,
hif_usb_regout_cb, cmd, 1);
usb_anchor_urb(urb, &hif_dev->regout_submitted);
ret = usb_submit_urb(urb, GFP_KERNEL);
if (ret) {
usb_free_urb(urb);
usb_unanchor_urb(urb);
kfree(cmd);
}
usb_free_urb(urb);
return ret;
}
......@@ -154,6 +149,13 @@ static void hif_usb_tx_cb(struct urb *urb)
}
}
static inline void ath9k_skb_queue_purge(struct sk_buff_head *list)
{
struct sk_buff *skb;
while ((skb = __skb_dequeue(list)) != NULL)
dev_kfree_skb_any(skb);
}
/* TX lock has to be taken */
static int __hif_usb_tx(struct hif_device_usb *hif_dev)
{
......@@ -212,7 +214,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev)
ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC);
if (ret) {
tx_buf->len = tx_buf->offset = 0;
__skb_queue_purge(&tx_buf->skb_queue);
ath9k_skb_queue_purge(&tx_buf->skb_queue);
__skb_queue_head_init(&tx_buf->skb_queue);
list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
hif_dev->tx.tx_buf_cnt++;
......@@ -279,7 +281,7 @@ static void hif_usb_stop(void *hif_handle, u8 pipe_id)
unsigned long flags;
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
__skb_queue_purge(&hif_dev->tx.tx_skb_queue);
ath9k_skb_queue_purge(&hif_dev->tx.tx_skb_queue);
hif_dev->tx.tx_skb_cnt = 0;
hif_dev->tx.flags |= HIF_USB_TX_STOP;
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
......@@ -299,6 +301,8 @@ static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb,
ret = hif_usb_send_regout(hif_dev, skb);
break;
default:
dev_err(&hif_dev->udev->dev,
"ath9k_htc: Invalid TX pipe: %d\n", pipe_id);
ret = -EINVAL;
break;
}
......@@ -321,12 +325,14 @@ static struct ath9k_htc_hif hif_usb = {
static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
struct sk_buff *skb)
{
struct sk_buff *nskb, *skb_pool[8];
struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER];
int index = 0, i = 0, chk_idx, len = skb->len;
int rx_remain_len = 0, rx_pkt_len = 0;
u16 pkt_len, pkt_tag, pool_index = 0;
u8 *ptr;
spin_lock(&hif_dev->rx_lock);
rx_remain_len = hif_dev->rx_remain_len;
rx_pkt_len = hif_dev->rx_transfer_len;
......@@ -353,6 +359,8 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
}
}
spin_unlock(&hif_dev->rx_lock);
while (index < len) {
ptr = (u8 *) skb->data;
......@@ -370,6 +378,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
index = index + 4 + pkt_len + pad_len;
if (index > MAX_RX_BUF_SIZE) {
spin_lock(&hif_dev->rx_lock);
hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE;
hif_dev->rx_transfer_len =
MAX_RX_BUF_SIZE - chk_idx - 4;
......@@ -381,6 +390,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
dev_err(&hif_dev->udev->dev,
"ath9k_htc: RX memory allocation"
" error\n");
spin_unlock(&hif_dev->rx_lock);
goto err;
}
skb_reserve(nskb, 32);
......@@ -391,6 +401,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
/* Record the buffer pointer */
hif_dev->remain_skb = nskb;
spin_unlock(&hif_dev->rx_lock);
} else {
nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC);
if (!nskb) {
......@@ -408,14 +419,11 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
}
} else {
RX_STAT_INC(skb_dropped);
dev_kfree_skb_any(skb);
return;
}
}
err:
dev_kfree_skb_any(skb);
for (i = 0; i < pool_index; i++) {
ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i],
skb_pool[i]->len, USB_WLAN_RX_PIPE);
......@@ -426,11 +434,13 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
static void ath9k_hif_usb_rx_cb(struct urb *urb)
{
struct sk_buff *skb = (struct sk_buff *) urb->context;
struct sk_buff *nskb;
struct hif_device_usb *hif_dev = (struct hif_device_usb *)
usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
int ret;
if (!skb)
return;
if (!hif_dev)
goto free;
......@@ -448,38 +458,23 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
if (likely(urb->actual_length != 0)) {
skb_put(skb, urb->actual_length);
nskb = __dev_alloc_skb(MAX_RX_BUF_SIZE, GFP_ATOMIC);
if (!nskb)
goto resubmit;
usb_fill_bulk_urb(urb, hif_dev->udev,
usb_rcvbulkpipe(hif_dev->udev,
USB_WLAN_RX_PIPE),
nskb->data, MAX_RX_BUF_SIZE,
ath9k_hif_usb_rx_cb, nskb);
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret) {
dev_kfree_skb_any(nskb);
goto free;
}
ath9k_hif_usb_rx_stream(hif_dev, skb);
return;
}
resubmit:
skb_reset_tail_pointer(skb);
skb_trim(skb, 0);
usb_anchor_urb(urb, &hif_dev->rx_submitted);
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret)
if (ret) {
usb_unanchor_urb(urb);
goto free;
}
return;
free:
dev_kfree_skb_any(skb);
kfree_skb(skb);
}
static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
......@@ -490,6 +485,9 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
int ret;
if (!skb)
return;
if (!hif_dev)
goto free;
......@@ -508,7 +506,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
if (likely(urb->actual_length != 0)) {
skb_put(skb, urb->actual_length);
nskb = __dev_alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC);
nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC);
if (!nskb)
goto resubmit;
......@@ -519,7 +517,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret) {
dev_kfree_skb_any(nskb);
kfree_skb(nskb);
goto free;
}
......@@ -539,7 +537,8 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
return;
free:
dev_kfree_skb_any(skb);
kfree_skb(skb);
urb->context = NULL;
}
static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
......@@ -609,78 +608,66 @@ static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev)
return -ENOMEM;
}
static void ath9k_hif_usb_dealloc_rx_skbs(struct hif_device_usb *hif_dev)
{
int i;
for (i = 0; i < MAX_RX_URB_NUM; i++) {
if (hif_dev->wlan_rx_data_urb[i]) {
if (hif_dev->wlan_rx_data_urb[i]->transfer_buffer)
dev_kfree_skb_any((void *)
hif_dev->wlan_rx_data_urb[i]->context);
}
}
}
static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev)
{
int i;
for (i = 0; i < MAX_RX_URB_NUM; i++) {
if (hif_dev->wlan_rx_data_urb[i]) {
usb_kill_urb(hif_dev->wlan_rx_data_urb[i]);
usb_free_urb(hif_dev->wlan_rx_data_urb[i]);
hif_dev->wlan_rx_data_urb[i] = NULL;
}
}
}
static int ath9k_hif_usb_prep_rx_urb(struct hif_device_usb *hif_dev,
struct urb *urb)
{
struct sk_buff *skb;
skb = __dev_alloc_skb(MAX_RX_BUF_SIZE, GFP_KERNEL);
if (!skb)
return -ENOMEM;
usb_fill_bulk_urb(urb, hif_dev->udev,
usb_rcvbulkpipe(hif_dev->udev, USB_WLAN_RX_PIPE),
skb->data, MAX_RX_BUF_SIZE,
ath9k_hif_usb_rx_cb, skb);
return 0;
usb_kill_anchored_urbs(&hif_dev->rx_submitted);
}
static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
{
struct urb *urb = NULL;
struct sk_buff *skb = NULL;
int i, ret;
init_usb_anchor(&hif_dev->rx_submitted);
spin_lock_init(&hif_dev->rx_lock);
for (i = 0; i < MAX_RX_URB_NUM; i++) {
/* Allocate URB */
hif_dev->wlan_rx_data_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
if (hif_dev->wlan_rx_data_urb[i] == NULL) {
urb = usb_alloc_urb(0, GFP_KERNEL);
if (urb == NULL) {
ret = -ENOMEM;
goto err_rx_urb;
goto err_urb;
}
/* Allocate buffer */
ret = ath9k_hif_usb_prep_rx_urb(hif_dev,
hif_dev->wlan_rx_data_urb[i]);
if (ret)
goto err_rx_urb;
skb = alloc_skb(MAX_RX_BUF_SIZE, GFP_KERNEL);
if (!skb) {
ret = -ENOMEM;
goto err_skb;
}
usb_fill_bulk_urb(urb, hif_dev->udev,
usb_rcvbulkpipe(hif_dev->udev,
USB_WLAN_RX_PIPE),
skb->data, MAX_RX_BUF_SIZE,
ath9k_hif_usb_rx_cb, skb);
/* Anchor URB */
usb_anchor_urb(urb, &hif_dev->rx_submitted);
/* Submit URB */
ret = usb_submit_urb(hif_dev->wlan_rx_data_urb[i], GFP_KERNEL);
if (ret)
goto err_rx_urb;
ret = usb_submit_urb(urb, GFP_KERNEL);
if (ret) {
usb_unanchor_urb(urb);
goto err_submit;
}
/*
* Drop reference count.
* This ensures that the URB is freed when killing them.
*/
usb_free_urb(urb);
}
return 0;
err_rx_urb:
ath9k_hif_usb_dealloc_rx_skbs(hif_dev);
err_submit:
kfree_skb(skb);
err_skb:
usb_free_urb(urb);
err_urb:
ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
return ret;
}
......@@ -689,6 +676,8 @@ static void ath9k_hif_usb_dealloc_reg_in_urb(struct hif_device_usb *hif_dev)
{
if (hif_dev->reg_in_urb) {
usb_kill_urb(hif_dev->reg_in_urb);
if (hif_dev->reg_in_urb->context)
kfree_skb((void *)hif_dev->reg_in_urb->context);
usb_free_urb(hif_dev->reg_in_urb);
hif_dev->reg_in_urb = NULL;
}
......@@ -702,7 +691,7 @@ static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev)
if (hif_dev->reg_in_urb == NULL)
return -ENOMEM;
skb = __dev_alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL);
skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL);
if (!skb)
goto err;
......@@ -712,12 +701,10 @@ static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev)
ath9k_hif_usb_reg_in_cb, skb, 1);
if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0)
goto err_skb;
goto err;
return 0;
err_skb:
dev_kfree_skb_any(skb);
err:
ath9k_hif_usb_dealloc_reg_in_urb(hif_dev);
return -ENOMEM;
......@@ -725,6 +712,9 @@ static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev)
static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev)
{
/* Register Write */
init_usb_anchor(&hif_dev->regout_submitted);
/* TX */
if (ath9k_hif_usb_alloc_tx_urbs(hif_dev) < 0)
goto err;
......@@ -733,7 +723,7 @@ static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev)
if (ath9k_hif_usb_alloc_rx_urbs(hif_dev) < 0)
goto err;
/* Register Read/Write */
/* Register Read */
if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0)
goto err;
......@@ -830,6 +820,7 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev,
static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
{
usb_kill_anchored_urbs(&hif_dev->regout_submitted);
ath9k_hif_usb_dealloc_reg_in_urb(hif_dev);
ath9k_hif_usb_dealloc_tx_urbs(hif_dev);
ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
......
......@@ -34,6 +34,7 @@
#define MAX_RX_URB_NUM 8
#define MAX_RX_BUF_SIZE 16384
#define MAX_PKT_NUM_IN_TRANSFER 10
#define MAX_REG_OUT_URB_NUM 1
#define MAX_REG_OUT_BUF_NUM 8
......@@ -85,18 +86,17 @@ struct hif_device_usb {
struct usb_interface *interface;
const struct firmware *firmware;
struct htc_target *htc_handle;
u8 flags;
struct hif_usb_tx tx;
struct urb *wlan_rx_data_urb[MAX_RX_URB_NUM];
struct urb *reg_in_urb;
struct usb_anchor regout_submitted;
struct usb_anchor rx_submitted;
struct sk_buff *remain_skb;
int rx_remain_len;
int rx_pkt_len;
int rx_transfer_len;
int rx_pad_len;
spinlock_t rx_lock;
u8 flags; /* HIF_USB_* */
};
int ath9k_hif_usb_init(void);
......
......@@ -309,6 +309,14 @@ struct ath_led {
int brightness;
};
struct htc_beacon_config {
u16 beacon_interval;
u16 listen_interval;
u16 dtim_period;
u16 bmiss_timeout;
u8 dtim_count;
};
#define OP_INVALID BIT(0)
#define OP_SCANNING BIT(1)
#define OP_FULL_RESET BIT(2)
......@@ -349,7 +357,11 @@ struct ath9k_htc_priv {
struct sk_buff *beacon;
spinlock_t beacon_lock;
bool tx_queues_stop;
spinlock_t tx_lock;
struct ieee80211_vif *vif;
struct htc_beacon_config cur_beacon_conf;
unsigned int rxfilter;
struct tasklet_struct wmi_tasklet;
struct tasklet_struct rx_tasklet;
......@@ -360,6 +372,11 @@ struct ath9k_htc_priv {
struct ath9k_htc_aggr_work aggr_work;
struct delayed_work ath9k_aggr_work;
struct delayed_work ath9k_ani_work;
struct work_struct ps_work;
struct mutex htc_pm_lock;
unsigned long ps_usecount;
bool ps_enabled;
struct ath_led radio_led;
struct ath_led assoc_led;
......@@ -386,8 +403,7 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
}
void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf);
struct ieee80211_vif *vif);
void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending);
void ath9k_htc_beacon_update(struct ath9k_htc_priv *priv,
struct ieee80211_vif *vif);
......@@ -415,6 +431,11 @@ int ath9k_rx_init(struct ath9k_htc_priv *priv);
void ath9k_rx_cleanup(struct ath9k_htc_priv *priv);
void ath9k_host_rx_init(struct ath9k_htc_priv *priv);
void ath9k_rx_tasklet(unsigned long data);
u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv);
void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv);
void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv);
void ath9k_ps_work(struct work_struct *work);
void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv);
void ath9k_init_leds(struct ath9k_htc_priv *priv);
......
......@@ -19,7 +19,7 @@
#define FUDGE 2
static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
struct ieee80211_bss_conf *bss_conf)
struct htc_beacon_config *bss_conf)
{
struct ath_common *common = ath9k_hw_common(priv->ah);
struct ath9k_beacon_state bs;
......@@ -34,8 +34,8 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
memset(&bs, 0, sizeof(bs));
intval = bss_conf->beacon_int & ATH9K_BEACON_PERIOD;
bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_int);
intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval);
/*
* Setup dtim and cfp parameters according to
......@@ -138,7 +138,7 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
}
static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
struct ieee80211_bss_conf *bss_conf)
struct htc_beacon_config *bss_conf)
{
struct ath_common *common = ath9k_hw_common(priv->ah);
enum ath9k_int imask = 0;
......@@ -146,7 +146,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
int ret;
u8 cmd_rsp;
intval = bss_conf->beacon_int & ATH9K_BEACON_PERIOD;
intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
nexttbtt = intval;
intval |= ATH9K_BEACON_ENA;
if (priv->op_flags & OP_ENABLE_BEACON)
......@@ -154,7 +154,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
ath_print(common, ATH_DBG_BEACON,
"IBSS Beacon config, intval: %d, imask: 0x%x\n",
bss_conf->beacon_int, imask);
bss_conf->beacon_interval, imask);
WMI_CMD(WMI_DISABLE_INTR_CMDID);
ath9k_hw_beaconinit(priv->ah, nexttbtt, intval);
......@@ -239,18 +239,35 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending)
spin_unlock_bh(&priv->beacon_lock);
}
void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf)
struct ieee80211_vif *vif)
{
struct ath_common *common = ath9k_hw_common(priv->ah);
switch (vif->type) {
enum nl80211_iftype iftype;
struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf;
if (vif) {
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
iftype = vif->type;
cur_conf->beacon_interval = bss_conf->beacon_int;
cur_conf->dtim_period = bss_conf->dtim_period;
cur_conf->listen_interval = 1;
cur_conf->dtim_count = 1;
cur_conf->bmiss_timeout =
ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
} else
iftype = priv->ah->opmode;
if (cur_conf->beacon_interval == 0)
cur_conf->beacon_interval = 100;
switch (iftype) {
case NL80211_IFTYPE_STATION:
ath9k_htc_beacon_config_sta(priv, bss_conf);
ath9k_htc_beacon_config_sta(priv, cur_conf);
break;
case NL80211_IFTYPE_ADHOC:
ath9k_htc_beacon_config_adhoc(priv, bss_conf);
ath9k_htc_beacon_config_adhoc(priv, cur_conf);
break;
default:
ath_print(common, ATH_DBG_CONFIG,
......
......@@ -287,6 +287,7 @@ static bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
}
static const struct ath_bus_ops ath9k_usb_bus_ops = {
.ath_bus_type = ATH_USB,
.read_cachesize = ath_usb_read_cachesize,
.eeprom_read = ath_usb_eeprom_read,
};
......@@ -421,6 +422,7 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv)
memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
priv->op_flags |= OP_TXAGGR;
priv->ah->opmode = NL80211_IFTYPE_STATION;
}
static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid)
......@@ -449,8 +451,10 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid)
spin_lock_init(&priv->wmi->wmi_lock);
spin_lock_init(&priv->beacon_lock);
spin_lock_init(&priv->tx_lock);
mutex_init(&priv->mutex);
mutex_init(&priv->aggr_work.mutex);
mutex_init(&priv->htc_pm_lock);
tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet,
(unsigned long)priv);
tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
......@@ -458,6 +462,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid)
tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv);
INIT_DELAYED_WORK(&priv->ath9k_aggr_work, ath9k_htc_aggr_work);
INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work);
INIT_WORK(&priv->ps_work, ath9k_ps_work);
/*
* Cache line size is used to size and align various
......@@ -511,12 +516,17 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_AMPDU_AGGREGATION |
IEEE80211_HW_SPECTRUM_MGMT |
IEEE80211_HW_HAS_RATE_CONTROL;
IEEE80211_HW_HAS_RATE_CONTROL |
IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK;
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC);
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
hw->queues = 4;
hw->channel_change_time = 5000;
hw->max_listen_interval = 10;
......
......@@ -65,6 +65,56 @@ static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv,
return mode;
}
static bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
enum ath9k_power_mode mode)
{
bool ret;
mutex_lock(&priv->htc_pm_lock);
ret = ath9k_hw_setpower(priv->ah, mode);
mutex_unlock(&priv->htc_pm_lock);
return ret;
}
void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv)
{
mutex_lock(&priv->htc_pm_lock);
if (++priv->ps_usecount != 1)
goto unlock;
ath9k_hw_setpower(priv->ah, ATH9K_PM_AWAKE);
unlock:
mutex_unlock(&priv->htc_pm_lock);
}
void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv)
{
mutex_lock(&priv->htc_pm_lock);
if (--priv->ps_usecount != 0)
goto unlock;
if (priv->ps_enabled)
ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP);
unlock:
mutex_unlock(&priv->htc_pm_lock);
}
void ath9k_ps_work(struct work_struct *work)
{
struct ath9k_htc_priv *priv =
container_of(work, struct ath9k_htc_priv,
ps_work);
ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
/* The chip wakes up after receiving the first beacon
while network sleep is enabled. For the driver to
be in sync with the hw, set the chip to awake and
only then set it to sleep.
*/
ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP);
}
static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
struct ieee80211_hw *hw,
struct ath9k_channel *hchan)
......@@ -87,7 +137,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
/* Fiddle around with fastcc later on, for now just use full reset */
fastcc = false;
ath9k_htc_ps_wakeup(priv);
htc_stop(priv->htc);
WMI_CMD(WMI_DISABLE_INTR_CMDID);
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
......@@ -103,6 +153,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
ath_print(common, ATH_DBG_FATAL,
"Unable to reset channel (%u Mhz) "
"reset status %d\n", channel->center_freq, ret);
ath9k_htc_ps_restore(priv);
goto err;
}
......@@ -128,6 +179,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
priv->op_flags &= ~OP_FULL_RESET;
err:
ath9k_htc_ps_restore(priv);
return ret;
}
......@@ -412,32 +464,31 @@ static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv,
if (tid > ATH9K_HTC_MAX_TID)
return -EINVAL;
memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr));
rcu_read_lock();
/* Check if we are able to retrieve the station */
sta = ieee80211_find_sta(vif, sta_addr);
if (sta) {
ista = (struct ath9k_htc_sta *) sta->drv_priv;
} else {
if (!sta) {
rcu_read_unlock();
return -EINVAL;
}
if (!ista) {
rcu_read_unlock();
return -EINVAL;
}
ista = (struct ath9k_htc_sta *) sta->drv_priv;
memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr));
if (oper)
ista->tid_state[tid] = AGGR_START;
else
ista->tid_state[tid] = AGGR_STOP;
aggr.sta_index = ista->index;
rcu_read_unlock();
aggr.tidno = tid;
aggr.aggr_enable = oper;
if (oper)
ista->tid_state[tid] = AGGR_START;
else
ista->tid_state[tid] = AGGR_STOP;
WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr);
if (ret)
ath_print(common, ATH_DBG_CONFIG,
......@@ -694,6 +745,10 @@ void ath9k_ani_work(struct work_struct *work)
short_cal_interval = ATH_STA_SHORT_CALINTERVAL;
/* Only calibrate if awake */
if (ah->power_mode != ATH9K_PM_AWAKE)
goto set_timer;
/* Long calibration runs independently of short calibration. */
if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
longcal = true;
......@@ -728,6 +783,9 @@ void ath9k_ani_work(struct work_struct *work)
/* Skip all processing if there's nothing to do. */
if (longcal || shortcal || aniflag) {
ath9k_htc_ps_wakeup(priv);
/* Call ANI routine if necessary */
if (aniflag)
ath9k_hw_ani_monitor(ah, ah->curchan);
......@@ -749,8 +807,11 @@ void ath9k_ani_work(struct work_struct *work)
ah->curchan->channelFlags,
common->ani.noise_floor);
}
ath9k_htc_ps_restore(priv);
}
set_timer:
/*
* Set timer interval based on previous results.
* The interval must be the shortest necessary to satisfy ANI,
......@@ -995,7 +1056,7 @@ static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct ieee80211_hdr *hdr;
struct ath9k_htc_priv *priv = hw->priv;
int padpos, padsize;
int padpos, padsize, ret;
hdr = (struct ieee80211_hdr *) skb->data;
......@@ -1009,8 +1070,19 @@ static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
memmove(skb->data, skb->data + padsize, padpos);
}
if (ath9k_htc_tx_start(priv, skb) != 0) {
ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, "Tx failed");
ret = ath9k_htc_tx_start(priv, skb);
if (ret != 0) {
if (ret == -ENOMEM) {
ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
"Stopping TX queues\n");
ieee80211_stop_queues(hw);
spin_lock_bh(&priv->tx_lock);
priv->tx_queues_stop = true;
spin_unlock_bh(&priv->tx_lock);
} else {
ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
"Tx failed");
}
goto fail_tx;
}
......@@ -1075,6 +1147,12 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
priv->op_flags &= ~OP_INVALID;
htc_start(priv->htc);
spin_lock_bh(&priv->tx_lock);
priv->tx_queues_stop = false;
spin_unlock_bh(&priv->tx_lock);
ieee80211_wake_queues(hw);
mutex_unlock:
mutex_unlock(&priv->mutex);
return ret;
......@@ -1096,6 +1174,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
return;
}
ath9k_htc_ps_wakeup(priv);
htc_stop(priv->htc);
WMI_CMD(WMI_DISABLE_INTR_CMDID);
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
......@@ -1103,8 +1182,10 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
ath9k_hw_phy_disable(ah);
ath9k_hw_disable(ah);
ath9k_hw_configpcipowersave(ah, 1, 1);
ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
ath9k_htc_ps_restore(priv);
ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
cancel_work_sync(&priv->ps_work);
cancel_delayed_work_sync(&priv->ath9k_ani_work);
cancel_delayed_work_sync(&priv->ath9k_aggr_work);
cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
......@@ -1145,6 +1226,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
goto out;
}
ath9k_htc_ps_wakeup(priv);
memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
memcpy(&hvif.myaddr, vif->addr, ETH_ALEN);
......@@ -1191,6 +1273,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
priv->vif = vif;
out:
ath9k_htc_ps_restore(priv);
mutex_unlock(&priv->mutex);
return ret;
}
......@@ -1259,6 +1342,16 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
}
}
if (changed & IEEE80211_CONF_CHANGE_PS) {
if (conf->flags & IEEE80211_CONF_PS) {
ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP);
priv->ps_enabled = true;
} else {
priv->ps_enabled = false;
cancel_work_sync(&priv->ps_work);
ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
}
}
if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
if (conf->flags & IEEE80211_CONF_MONITOR) {
......@@ -1295,16 +1388,18 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
mutex_lock(&priv->mutex);
ath9k_htc_ps_wakeup(priv);
changed_flags &= SUPPORTED_FILTERS;
*total_flags &= SUPPORTED_FILTERS;
priv->rxfilter = *total_flags;
rfilt = ath9k_cmn_calcrxfilter(hw, priv->ah, priv->rxfilter);
rfilt = ath9k_htc_calcrxfilter(priv);
ath9k_hw_setrxfilter(priv->ah, rfilt);
ath_print(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG,
"Set HW RX filter: 0x%x\n", rfilt);
ath9k_htc_ps_restore(priv);
mutex_unlock(&priv->mutex);
}
......@@ -1382,6 +1477,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw,
mutex_lock(&priv->mutex);
ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n");
ath9k_htc_ps_wakeup(priv);
switch (cmd) {
case SET_KEY:
......@@ -1404,6 +1500,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw,
ret = -EINVAL;
}
ath9k_htc_ps_restore(priv);
mutex_unlock(&priv->mutex);
return ret;
......@@ -1419,6 +1516,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
struct ath_common *common = ath9k_hw_common(ah);
mutex_lock(&priv->mutex);
ath9k_htc_ps_wakeup(priv);
if (changed & BSS_CHANGED_ASSOC) {
common->curaid = bss_conf->assoc ?
......@@ -1431,6 +1529,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
ath_start_ani(priv);
} else {
priv->op_flags &= ~OP_ASSOCIATED;
cancel_work_sync(&priv->ps_work);
cancel_delayed_work_sync(&priv->ath9k_ani_work);
}
}
......@@ -1450,7 +1549,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
((changed & BSS_CHANGED_BEACON_ENABLED) &&
bss_conf->enable_beacon)) {
priv->op_flags |= OP_ENABLE_BEACON;
ath9k_htc_beacon_config(priv, vif, bss_conf);
ath9k_htc_beacon_config(priv, vif);
}
if (changed & BSS_CHANGED_BEACON)
......@@ -1459,7 +1558,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
if ((changed & BSS_CHANGED_BEACON_ENABLED) &&
!bss_conf->enable_beacon) {
priv->op_flags &= ~OP_ENABLE_BEACON;
ath9k_htc_beacon_config(priv, vif, bss_conf);
ath9k_htc_beacon_config(priv, vif);
}
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
......@@ -1490,6 +1589,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
ath9k_hw_init_global_settings(ah);
}
ath9k_htc_ps_restore(priv);
mutex_unlock(&priv->mutex);
}
......@@ -1518,9 +1618,11 @@ static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw)
{
struct ath9k_htc_priv *priv = hw->priv;
ath9k_htc_ps_wakeup(priv);
mutex_lock(&priv->mutex);
ath9k_hw_reset_tsf(priv->ah);
mutex_unlock(&priv->mutex);
ath9k_htc_ps_restore(priv);
}
static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
......@@ -1569,6 +1671,7 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw)
spin_lock_bh(&priv->beacon_lock);
priv->op_flags |= OP_SCANNING;
spin_unlock_bh(&priv->beacon_lock);
cancel_work_sync(&priv->ps_work);
cancel_delayed_work_sync(&priv->ath9k_ani_work);
mutex_unlock(&priv->mutex);
}
......@@ -1577,13 +1680,17 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
{
struct ath9k_htc_priv *priv = hw->priv;
ath9k_htc_ps_wakeup(priv);
mutex_lock(&priv->mutex);
spin_lock_bh(&priv->beacon_lock);
priv->op_flags &= ~OP_SCANNING;
spin_unlock_bh(&priv->beacon_lock);
priv->op_flags |= OP_FULL_RESET;
if (priv->op_flags & OP_ASSOCIATED)
ath9k_htc_beacon_config(priv, NULL);
ath_start_ani(priv);
mutex_unlock(&priv->mutex);
ath9k_htc_ps_restore(priv);
}
static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
......
......@@ -188,10 +188,20 @@ void ath9k_tx_tasklet(unsigned long data)
hdr = (struct ieee80211_hdr *) skb->data;
fc = hdr->frame_control;
tx_info = IEEE80211_SKB_CB(skb);
sta = tx_info->control.sta;
memset(&tx_info->status, 0, sizeof(tx_info->status));
rcu_read_lock();
sta = ieee80211_find_sta(priv->vif, hdr->addr1);
if (!sta) {
rcu_read_unlock();
ieee80211_tx_status(priv->hw, skb);
continue;
}
/* Check if we need to start aggregation */
if (sta && conf_is_ht(&priv->hw->conf) &&
(priv->op_flags & OP_TXAGGR)
&& !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
......@@ -213,9 +223,21 @@ void ath9k_tx_tasklet(unsigned long data)
rcu_read_unlock();
memset(&tx_info->status, 0, sizeof(tx_info->status));
/* Send status to mac80211 */
ieee80211_tx_status(priv->hw, skb);
}
/* Wake TX queues if needed */
spin_lock_bh(&priv->tx_lock);
if (priv->tx_queues_stop) {
priv->tx_queues_stop = false;
spin_unlock_bh(&priv->tx_lock);
ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
"Waking up TX queues\n");
ieee80211_wake_queues(priv->hw);
return;
}
spin_unlock_bh(&priv->tx_lock);
}
void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb,
......@@ -290,10 +312,84 @@ bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv,
/* RX */
/******/
/*
* Calculate the RX filter to be set in the HW.
*/
u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv)
{
#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
struct ath_hw *ah = priv->ah;
u32 rfilt;
rfilt = (ath9k_hw_getrxfilter(ah) & RX_FILTER_PRESERVE)
| ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
| ATH9K_RX_FILTER_MCAST;
/* If not a STA, enable processing of Probe Requests */
if (ah->opmode != NL80211_IFTYPE_STATION)
rfilt |= ATH9K_RX_FILTER_PROBEREQ;
/*
* Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station
* mode interface or when in monitor mode. AP mode does not need this
* since it receives all in-BSS frames anyway.
*/
if (((ah->opmode != NL80211_IFTYPE_AP) &&
(priv->rxfilter & FIF_PROMISC_IN_BSS)) ||
(ah->opmode == NL80211_IFTYPE_MONITOR))
rfilt |= ATH9K_RX_FILTER_PROM;
if (priv->rxfilter & FIF_CONTROL)
rfilt |= ATH9K_RX_FILTER_CONTROL;
if ((ah->opmode == NL80211_IFTYPE_STATION) &&
!(priv->rxfilter & FIF_BCN_PRBRESP_PROMISC))
rfilt |= ATH9K_RX_FILTER_MYBEACON;
else
rfilt |= ATH9K_RX_FILTER_BEACON;
if (conf_is_ht(&priv->hw->conf))
rfilt |= ATH9K_RX_FILTER_COMP_BAR;
return rfilt;
#undef RX_FILTER_PRESERVE
}
/*
* Recv initialization for opmode change.
*/
static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv)
{
struct ath_hw *ah = priv->ah;
struct ath_common *common = ath9k_hw_common(ah);
u32 rfilt, mfilt[2];
/* configure rx filter */
rfilt = ath9k_htc_calcrxfilter(priv);
ath9k_hw_setrxfilter(ah, rfilt);
/* configure bssid mask */
if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
ath_hw_setbssidmask(common);
/* configure operational mode */
ath9k_hw_setopmode(ah);
/* Handle any link-level address change. */
ath9k_hw_setmac(ah, common->macaddr);
/* calculate and install multicast filter */
mfilt[0] = mfilt[1] = ~0;
ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
}
void ath9k_host_rx_init(struct ath9k_htc_priv *priv)
{
ath9k_hw_rxena(priv->ah);
ath9k_cmn_opmode_init(priv->hw, priv->ah, priv->rxfilter);
ath9k_htc_opmode_init(priv);
ath9k_hw_startpcureceive(priv->ah);
priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER;
}
......@@ -354,7 +450,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
padpos = ath9k_cmn_padpos(fc);
padsize = padpos & 3;
if (padsize && skb->len >= padpos+padsize) {
if (padsize && skb->len >= padpos+padsize+FCS_LEN) {
memmove(skb->data + padsize, skb->data, padpos);
skb_pull(skb, padsize);
}
......@@ -457,7 +553,7 @@ void ath9k_rx_tasklet(unsigned long data)
struct ieee80211_rx_status rx_status;
struct sk_buff *skb;
unsigned long flags;
struct ieee80211_hdr *hdr;
do {
spin_lock_irqsave(&priv->rx.rxbuflock, flags);
......@@ -484,6 +580,11 @@ void ath9k_rx_tasklet(unsigned long data)
memcpy(IEEE80211_SKB_RXCB(rxbuf->skb), &rx_status,
sizeof(struct ieee80211_rx_status));
skb = rxbuf->skb;
hdr = (struct ieee80211_hdr *) skb->data;
if (ieee80211_is_beacon(hdr->frame_control) && priv->ps_enabled)
ieee80211_queue_work(priv->hw, &priv->ps_work);
spin_unlock_irqrestore(&priv->rx.rxbuflock, flags);
ieee80211_rx(priv->hw, skb);
......@@ -550,7 +651,6 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,
spin_lock(&priv->rx.rxbuflock);
memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE);
skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);
skb->len = rxstatus->rs_datalen;
rxbuf->skb = skb;
rxbuf->in_process = true;
spin_unlock(&priv->rx.rxbuflock);
......
......@@ -146,7 +146,7 @@ static int htc_config_pipe_credits(struct htc_target *target)
struct htc_config_pipe_msg *cp_msg;
int ret, time_left;
skb = dev_alloc_skb(50 + sizeof(struct htc_frame_hdr));
skb = alloc_skb(50 + sizeof(struct htc_frame_hdr), GFP_ATOMIC);
if (!skb) {
dev_err(target->dev, "failed to allocate send buffer\n");
return -ENOMEM;
......@@ -174,7 +174,7 @@ static int htc_config_pipe_credits(struct htc_target *target)
return 0;
err:
dev_kfree_skb(skb);
kfree_skb(skb);
return -EINVAL;
}
......@@ -184,7 +184,7 @@ static int htc_setup_complete(struct htc_target *target)
struct htc_comp_msg *comp_msg;
int ret = 0, time_left;
skb = dev_alloc_skb(50 + sizeof(struct htc_frame_hdr));
skb = alloc_skb(50 + sizeof(struct htc_frame_hdr), GFP_ATOMIC);
if (!skb) {
dev_err(target->dev, "failed to allocate send buffer\n");
return -ENOMEM;
......@@ -210,7 +210,7 @@ static int htc_setup_complete(struct htc_target *target)
return 0;
err:
dev_kfree_skb(skb);
kfree_skb(skb);
return -EINVAL;
}
......@@ -250,8 +250,8 @@ int htc_connect_service(struct htc_target *target,
endpoint->dl_pipeid = service_to_dlpipe(service_connreq->service_id);
endpoint->ep_callbacks = service_connreq->ep_callbacks;
skb = dev_alloc_skb(sizeof(struct htc_conn_svc_msg) +
sizeof(struct htc_frame_hdr));
skb = alloc_skb(sizeof(struct htc_conn_svc_msg) +
sizeof(struct htc_frame_hdr), GFP_ATOMIC);
if (!skb) {
dev_err(target->dev, "Failed to allocate buf to send"
"service connect req\n");
......@@ -282,7 +282,7 @@ int htc_connect_service(struct htc_target *target,
*conn_rsp_epid = target->conn_rsp_epid;
return 0;
err:
dev_kfree_skb(skb);
kfree_skb(skb);
return ret;
}
......@@ -321,16 +321,18 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
struct sk_buff *skb, bool txok)
{
struct htc_endpoint *endpoint;
struct htc_frame_hdr *htc_hdr;
struct htc_frame_hdr *htc_hdr = NULL;
if (htc_handle->htc_flags & HTC_OP_CONFIG_PIPE_CREDITS) {
complete(&htc_handle->cmd_wait);
htc_handle->htc_flags &= ~HTC_OP_CONFIG_PIPE_CREDITS;
goto ret;
}
if (htc_handle->htc_flags & HTC_OP_START_WAIT) {
complete(&htc_handle->cmd_wait);
htc_handle->htc_flags &= ~HTC_OP_START_WAIT;
goto ret;
}
if (skb) {
......@@ -343,6 +345,14 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
htc_hdr->endpoint_id, txok);
}
}
return;
ret:
/* HTC-generated packets are freed here. */
if (htc_hdr && htc_hdr->endpoint_id != ENDPOINT0)
dev_kfree_skb_any(skb);
else
kfree_skb(skb);
}
/*
......@@ -367,7 +377,10 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,
epid = htc_hdr->endpoint_id;
if (epid >= ENDPOINT_MAX) {
dev_kfree_skb_any(skb);
if (pipe_id != USB_REG_IN_PIPE)
dev_kfree_skb_any(skb);
else
kfree_skb(skb);
return;
}
......@@ -377,7 +390,7 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,
if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) {
if (be32_to_cpu(*(u32 *) skb->data) == 0x00C60000)
/* Move past the Watchdog pattern */
htc_hdr = (struct htc_frame_hdr *) skb->data + 4;
htc_hdr = (struct htc_frame_hdr *)(skb->data + 4);
}
/* Get the message ID */
......@@ -396,7 +409,7 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,
break;
}
dev_kfree_skb_any(skb);
kfree_skb(skb);
} else {
if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER)
......
......@@ -28,9 +28,6 @@
static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan);
static u32 ath9k_hw_ini_fixup(struct ath_hw *ah,
struct ar5416_eeprom_def *pEepData,
u32 reg, u32 value);
MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
......@@ -548,7 +545,6 @@ static bool ath9k_hw_devid_supported(u16 devid)
case AR9285_DEVID_PCIE:
case AR5416_DEVID_AR9287_PCI:
case AR5416_DEVID_AR9287_PCIE:
case AR9271_USB:
case AR2427_DEVID_PCIE:
return true;
default:
......@@ -817,38 +813,46 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
/* txgain table */
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_high_power_tx_gain_9285_1_2,
ARRAY_SIZE(ar9285Modes_high_power_tx_gain_9285_1_2), 6);
if (AR_SREV_9285E_20(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_XE2_0_high_power,
ARRAY_SIZE(
ar9285Modes_XE2_0_high_power), 6);
} else {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_high_power_tx_gain_9285_1_2,
ARRAY_SIZE(
ar9285Modes_high_power_tx_gain_9285_1_2), 6);
}
} else {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_original_tx_gain_9285_1_2,
ARRAY_SIZE(ar9285Modes_original_tx_gain_9285_1_2), 6);
if (AR_SREV_9285E_20(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_XE2_0_normal_power,
ARRAY_SIZE(
ar9285Modes_XE2_0_normal_power), 6);
} else {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_original_tx_gain_9285_1_2,
ARRAY_SIZE(
ar9285Modes_original_tx_gain_9285_1_2), 6);
}
}
}
}
static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah)
{
u32 i, j;
if (ah->hw_version.devid == AR9280_DEVID_PCI) {
/* EEPROM Fixup */
for (i = 0; i < ah->iniModes.ia_rows; i++) {
u32 reg = INI_RA(&ah->iniModes, i, 0);
struct base_eep_header *pBase = &(ah->eeprom.def.baseEepHeader);
struct ath_common *common = ath9k_hw_common(ah);
for (j = 1; j < ah->iniModes.ia_columns; j++) {
u32 val = INI_RA(&ah->iniModes, i, j);
ah->need_an_top2_fixup = (ah->hw_version.devid == AR9280_DEVID_PCI) &&
(ah->eep_map != EEP_MAP_4KBITS) &&
((pBase->version & 0xff) > 0x0a) &&
(pBase->pwdclkind == 0);
INI_RA(&ah->iniModes, i, j) =
ath9k_hw_ini_fixup(ah,
&ah->eeprom.def,
reg, val);
}
}
}
if (ah->need_an_top2_fixup)
ath_print(common, ATH_DBG_EEPROM,
"needs fixup for AR_AN_TOP2 register\n");
}
int ath9k_hw_init(struct ath_hw *ah)
......@@ -856,11 +860,13 @@ int ath9k_hw_init(struct ath_hw *ah)
struct ath_common *common = ath9k_hw_common(ah);
int r = 0;
if (!ath9k_hw_devid_supported(ah->hw_version.devid)) {
ath_print(common, ATH_DBG_FATAL,
"Unsupported device ID: 0x%0x\n",
ah->hw_version.devid);
return -EOPNOTSUPP;
if (common->bus_ops->ath_bus_type != ATH_USB) {
if (!ath9k_hw_devid_supported(ah->hw_version.devid)) {
ath_print(common, ATH_DBG_FATAL,
"Unsupported device ID: 0x%0x\n",
ah->hw_version.devid);
return -EOPNOTSUPP;
}
}
ath9k_hw_init_defaults(ah);
......@@ -1121,23 +1127,23 @@ static void ath9k_hw_init_chain_masks(struct ath_hw *ah)
static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
enum nl80211_iftype opmode)
{
ah->mask_reg = AR_IMR_TXERR |
u32 imr_reg = AR_IMR_TXERR |
AR_IMR_TXURN |
AR_IMR_RXERR |
AR_IMR_RXORN |
AR_IMR_BCNMISC;
if (ah->config.rx_intr_mitigation)
ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
else
ah->mask_reg |= AR_IMR_RXOK;
imr_reg |= AR_IMR_RXOK;
ah->mask_reg |= AR_IMR_TXOK;
imr_reg |= AR_IMR_TXOK;
if (opmode == NL80211_IFTYPE_AP)
ah->mask_reg |= AR_IMR_MIB;
imr_reg |= AR_IMR_MIB;
REG_WRITE(ah, AR_IMR, ah->mask_reg);
REG_WRITE(ah, AR_IMR, imr_reg);
ah->imrs2_reg |= AR_IMR_S2_GTT;
REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
......@@ -1290,51 +1296,6 @@ static void ath9k_hw_override_ini(struct ath_hw *ah,
}
}
static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah,
struct ar5416_eeprom_def *pEepData,
u32 reg, u32 value)
{
struct base_eep_header *pBase = &(pEepData->baseEepHeader);
struct ath_common *common = ath9k_hw_common(ah);
switch (ah->hw_version.devid) {
case AR9280_DEVID_PCI:
if (reg == 0x7894) {
ath_print(common, ATH_DBG_EEPROM,
"ini VAL: %x EEPROM: %x\n", value,
(pBase->version & 0xff));
if ((pBase->version & 0xff) > 0x0a) {
ath_print(common, ATH_DBG_EEPROM,
"PWDCLKIND: %d\n",
pBase->pwdclkind);
value &= ~AR_AN_TOP2_PWDCLKIND;
value |= AR_AN_TOP2_PWDCLKIND &
(pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S);
} else {
ath_print(common, ATH_DBG_EEPROM,
"PWDCLKIND Earlier Rev\n");
}
ath_print(common, ATH_DBG_EEPROM,
"final ini VAL: %x\n", value);
}
break;
}
return value;
}
static u32 ath9k_hw_ini_fixup(struct ath_hw *ah,
struct ar5416_eeprom_def *pEepData,
u32 reg, u32 value)
{
if (ah->eep_map == EEP_MAP_4KBITS)
return value;
else
return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value);
}
static void ath9k_olc_init(struct ath_hw *ah)
{
u32 i;
......@@ -1440,6 +1401,9 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
u32 reg = INI_RA(&ah->iniModes, i, 0);
u32 val = INI_RA(&ah->iniModes, i, modesIndex);
if (reg == AR_AN_TOP2 && ah->need_an_top2_fixup)
val &= ~AR_AN_TOP2_PWDCLKIND;
REG_WRITE(ah, reg, val);
if (reg >= 0x7800 && reg < 0x78a0
......@@ -2840,7 +2804,7 @@ EXPORT_SYMBOL(ath9k_hw_getisr);
enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
{
u32 omask = ah->mask_reg;
enum ath9k_int omask = ah->imask;
u32 mask, mask2;
struct ath9k_hw_capabilities *pCap = &ah->caps;
struct ath_common *common = ath9k_hw_common(ah);
......@@ -2912,7 +2876,6 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST);
ah->imrs2_reg |= mask2;
REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
ah->mask_reg = ints;
if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
if (ints & ATH9K_INT_TIM_TIMER)
......@@ -3231,8 +3194,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
}
#endif
pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
if (AR_SREV_9271(ah))
pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
else
pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
if (AR_SREV_9280(ah) || AR_SREV_9285(ah))
pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
......
......@@ -44,8 +44,6 @@
#define AR5416_AR9100_DEVID 0x000b
#define AR9271_USB 0x9271
#define AR_SUBVENDOR_ID_NOG 0x0e11
#define AR_SUBVENDOR_ID_NEW_A 0x7065
#define AR5416_MAGIC 0x19641014
......@@ -461,6 +459,7 @@ struct ath_hw {
bool sw_mgmt_crypto;
bool is_pciexpress;
bool need_an_top2_fixup;
u16 tx_trig_level;
u16 rfsilent;
u32 rfkill_gpio;
......@@ -478,7 +477,7 @@ struct ath_hw {
struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES];
int16_t curchan_rad_index;
u32 mask_reg;
enum ath9k_int imask;
u32 imrs2_reg;
u32 txok_interrupt_mask;
u32 txerr_interrupt_mask;
......
......@@ -4184,7 +4184,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = {
{ 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 },
{ 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 },
{ 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 },
{ 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 },
{ 0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 },
{ 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 },
{ 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 },
{ 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 },
......@@ -4198,8 +4198,8 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = {
{ 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
{ 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
{ 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
{ 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 },
{ 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
{ 0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 },
{ 0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 },
{ 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
{ 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 },
{ 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 },
......@@ -4312,7 +4312,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = {
{ 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 },
{ 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 },
{ 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 },
{ 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 },
{ 0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 },
{ 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 },
{ 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 },
{ 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 },
......@@ -4326,8 +4326,8 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = {
{ 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
{ 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
{ 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
{ 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 },
{ 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
{ 0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 },
{ 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 },
{ 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
{ 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 },
{ 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 },
......@@ -4731,17 +4731,12 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = {
{ 0x00007808, 0x54214514 },
{ 0x0000780c, 0x02025830 },
{ 0x00007810, 0x71c0d388 },
{ 0x00007814, 0x924934a8 },
{ 0x0000781c, 0x00000000 },
{ 0x00007824, 0x00d86fff },
{ 0x00007828, 0x26d2491b },
{ 0x0000782c, 0x6e36d97b },
{ 0x00007830, 0xedb6d96e },
{ 0x00007834, 0x71400087 },
{ 0x0000783c, 0x0001fffe },
{ 0x00007840, 0xffeb1a20 },
{ 0x00007844, 0x000c0db6 },
{ 0x00007848, 0x6db61b6f },
{ 0x00007848, 0x6db6246f },
{ 0x0000784c, 0x6d9b66db },
{ 0x00007850, 0x6d8c6dba },
{ 0x00007854, 0x00040000 },
......@@ -4777,7 +4772,12 @@ static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = {
{ 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8 },
{ 0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b },
{ 0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e },
{ 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 },
{ 0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe },
{ 0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20 },
{ 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe },
{ 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 },
{ 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 },
......@@ -4813,7 +4813,12 @@ static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = {
{ 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8 },
{ 0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b },
{ 0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e },
{ 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 },
{ 0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe },
{ 0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20 },
{ 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 },
{ 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 },
{ 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 },
......@@ -4825,6 +4830,86 @@ static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = {
{ 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c },
};
static const u_int32_t ar9285Modes_XE2_0_normal_power[][6] = {
{ 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
{ 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 },
{ 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 },
{ 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 },
{ 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 },
{ 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 },
{ 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 },
{ 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 },
{ 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 },
{ 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 },
{ 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 },
{ 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 },
{ 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 },
{ 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 },
{ 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 },
{ 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 },
{ 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8 },
{ 0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b },
{ 0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6dbae },
{ 0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441 },
{ 0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe },
{ 0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c },
{ 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 },
{ 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 },
{ 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 },
{ 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c },
{ 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c },
{ 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c },
{ 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c },
{ 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c },
{ 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c },
};
static const u_int32_t ar9285Modes_XE2_0_high_power[][6] = {
{ 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
{ 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 },
{ 0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000 },
{ 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 },
{ 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 },
{ 0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000 },
{ 0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000 },
{ 0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000 },
{ 0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000 },
{ 0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000 },
{ 0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000 },
{ 0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 },
{ 0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000 },
{ 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 },
{ 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 },
{ 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 },
{ 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8 },
{ 0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b },
{ 0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e },
{ 0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443 },
{ 0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe },
{ 0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c },
{ 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe },
{ 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 },
{ 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 },
{ 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 },
{ 0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7 },
{ 0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 },
{ 0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 },
{ 0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 },
{ 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 },
};
static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = {
{0x00004040, 0x9248fd00 },
{0x00004040, 0x24924924 },
......
......@@ -105,7 +105,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
if (ah->tx_trig_level >= ah->config.max_txtrig_level)
return false;
omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL);
omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL);
txcfg = REG_READ(ah, AR_TXCFG);
curLevel = MS(txcfg, AR_FTRIG);
......@@ -246,79 +246,80 @@ void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds)
}
EXPORT_SYMBOL(ath9k_hw_cleartxdesc);
int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds)
int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds,
struct ath_tx_status *ts)
{
struct ar5416_desc *ads = AR5416DESC(ds);
if ((ads->ds_txstatus9 & AR_TxDone) == 0)
return -EINPROGRESS;
ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp;
ds->ds_txstat.ts_status = 0;
ds->ds_txstat.ts_flags = 0;
ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
ts->ts_tstamp = ads->AR_SendTimestamp;
ts->ts_status = 0;
ts->ts_flags = 0;
if (ads->ds_txstatus1 & AR_FrmXmitOK)
ds->ds_txstat.ts_status |= ATH9K_TX_ACKED;
ts->ts_status |= ATH9K_TX_ACKED;
if (ads->ds_txstatus1 & AR_ExcessiveRetries)
ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
ts->ts_status |= ATH9K_TXERR_XRETRY;
if (ads->ds_txstatus1 & AR_Filtered)
ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT;
ts->ts_status |= ATH9K_TXERR_FILT;
if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO;
ts->ts_status |= ATH9K_TXERR_FIFO;
ath9k_hw_updatetxtriglevel(ah, true);
}
if (ads->ds_txstatus9 & AR_TxOpExceeded)
ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP;
ts->ts_status |= ATH9K_TXERR_XTXOP;
if (ads->ds_txstatus1 & AR_TxTimerExpired)
ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
if (ads->ds_txstatus1 & AR_DescCfgErr)
ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR;
ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN;
ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
ath9k_hw_updatetxtriglevel(ah, true);
}
if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
ath9k_hw_updatetxtriglevel(ah, true);
}
if (ads->ds_txstatus0 & AR_TxBaStatus) {
ds->ds_txstat.ts_flags |= ATH9K_TX_BA;
ds->ds_txstat.ba_low = ads->AR_BaBitmapLow;
ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh;
ts->ts_flags |= ATH9K_TX_BA;
ts->ba_low = ads->AR_BaBitmapLow;
ts->ba_high = ads->AR_BaBitmapHigh;
}
ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
switch (ds->ds_txstat.ts_rateindex) {
ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
switch (ts->ts_rateindex) {
case 0:
ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
break;
case 1:
ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
break;
case 2:
ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
break;
case 3:
ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
break;
}
ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
ds->ds_txstat.evm0 = ads->AR_TxEVM0;
ds->ds_txstat.evm1 = ads->AR_TxEVM1;
ds->ds_txstat.evm2 = ads->AR_TxEVM2;
ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
ds->ds_txstat.ts_antenna = 0;
ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
ts->evm0 = ads->AR_TxEVM0;
ts->evm1 = ads->AR_TxEVM1;
ts->evm2 = ads->AR_TxEVM2;
ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
ts->ts_antenna = 0;
return 0;
}
......@@ -858,7 +859,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
EXPORT_SYMBOL(ath9k_hw_resettxqueue);
int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 pa, struct ath_desc *nds, u64 tsf)
struct ath_rx_status *rs, u64 tsf)
{
struct ar5416_desc ads;
struct ar5416_desc *adsp = AR5416DESC(ds);
......@@ -869,70 +870,70 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
ads.u.rx = adsp->u.rx;
ds->ds_rxstat.rs_status = 0;
ds->ds_rxstat.rs_flags = 0;
rs->rs_status = 0;
rs->rs_flags = 0;
ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp;
rs->rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
rs->rs_tstamp = ads.AR_RcvTimestamp;
if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
ds->ds_rxstat.rs_rssi = ATH9K_RSSI_BAD;
ds->ds_rxstat.rs_rssi_ctl0 = ATH9K_RSSI_BAD;
ds->ds_rxstat.rs_rssi_ctl1 = ATH9K_RSSI_BAD;
ds->ds_rxstat.rs_rssi_ctl2 = ATH9K_RSSI_BAD;
ds->ds_rxstat.rs_rssi_ext0 = ATH9K_RSSI_BAD;
ds->ds_rxstat.rs_rssi_ext1 = ATH9K_RSSI_BAD;
ds->ds_rxstat.rs_rssi_ext2 = ATH9K_RSSI_BAD;
rs->rs_rssi = ATH9K_RSSI_BAD;
rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD;
rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD;
rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD;
rs->rs_rssi_ext0 = ATH9K_RSSI_BAD;
rs->rs_rssi_ext1 = ATH9K_RSSI_BAD;
rs->rs_rssi_ext2 = ATH9K_RSSI_BAD;
} else {
ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
AR_RxRSSIAnt00);
ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
AR_RxRSSIAnt01);
ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
AR_RxRSSIAnt02);
ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4,
rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4,
AR_RxRSSIAnt10);
ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4,
rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4,
AR_RxRSSIAnt11);
ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4,
rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4,
AR_RxRSSIAnt12);
}
if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
rs->rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
else
ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID;
rs->rs_keyix = ATH9K_RXKEYIX_INVALID;
ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads));
ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
rs->rs_rate = RXSTATUS_RATE(ah, (&ads));
rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
ds->ds_rxstat.rs_moreaggr =
rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
rs->rs_moreaggr =
(ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
ds->ds_rxstat.rs_flags =
rs->rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
rs->rs_flags =
(ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
ds->ds_rxstat.rs_flags |=
rs->rs_flags |=
(ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
rs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST;
rs->rs_flags |= ATH9K_RX_DELIM_CRC_POST;
if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY;
rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
if (ads.ds_rxstatus8 & AR_CRCErr)
ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC;
rs->rs_status |= ATH9K_RXERR_CRC;
else if (ads.ds_rxstatus8 & AR_PHYErr) {
ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY;
rs->rs_status |= ATH9K_RXERR_PHY;
phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
ds->ds_rxstat.rs_phyerr = phyerr;
rs->rs_phyerr = phyerr;
} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT;
rs->rs_status |= ATH9K_RXERR_DECRYPT;
else if (ads.ds_rxstatus8 & AR_MichaelErr)
ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC;
rs->rs_status |= ATH9K_RXERR_MIC;
}
return 0;
......
......@@ -233,18 +233,9 @@ struct ath_desc {
u32 ds_ctl0;
u32 ds_ctl1;
u32 ds_hw[20];
union {
struct ath_tx_status tx;
struct ath_rx_status rx;
void *stats;
} ds_us;
void *ds_vdata;
} __packed;
#define ds_txstat ds_us.tx
#define ds_rxstat ds_us.rx
#define ds_stat ds_us.stats
#define ATH9K_TXDESC_CLRDMASK 0x0001
#define ATH9K_TXDESC_NOACK 0x0002
#define ATH9K_TXDESC_RTSENA 0x0004
......@@ -702,7 +693,8 @@ void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 segLen, bool firstSeg,
bool lastSeg, const struct ath_desc *ds0);
void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds);
int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds);
int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds,
struct ath_tx_status *ts);
void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
u32 keyIx, enum ath9k_key_type keyType, u32 flags);
......@@ -732,7 +724,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q);
bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q);
int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 pa, struct ath_desc *nds, u64 tsf);
struct ath_rx_status *rs, u64 tsf);
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags);
bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set);
......
......@@ -225,7 +225,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
ath_cache_conf_rate(sc, &hw->conf);
ath_update_txpow(sc);
ath9k_hw_set_interrupts(ah, sc->imask);
ath9k_hw_set_interrupts(ah, ah->imask);
ps_restore:
ath9k_ps_restore(sc);
......@@ -434,7 +434,7 @@ void ath9k_tasklet(unsigned long data)
ath_gen_timer_isr(sc->sc_ah);
/* re-enable hardware interrupt */
ath9k_hw_set_interrupts(ah, sc->imask);
ath9k_hw_set_interrupts(ah, ah->imask);
ath9k_ps_restore(sc);
}
......@@ -477,7 +477,7 @@ irqreturn_t ath_isr(int irq, void *dev)
* value to insure we only process bits we requested.
*/
ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */
status &= sc->imask; /* discard unasked-for bits */
status &= ah->imask; /* discard unasked-for bits */
/*
* If there are no status bits set, then this interrupt was not
......@@ -518,7 +518,7 @@ irqreturn_t ath_isr(int irq, void *dev)
* the interrupt.
*/
ath9k_hw_procmibevent(ah);
ath9k_hw_set_interrupts(ah, sc->imask);
ath9k_hw_set_interrupts(ah, ah->imask);
}
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
......@@ -536,7 +536,7 @@ irqreturn_t ath_isr(int irq, void *dev)
if (sched) {
/* turn off every interrupt except SWBA */
ath9k_hw_set_interrupts(ah, (sc->imask & ATH9K_INT_SWBA));
ath9k_hw_set_interrupts(ah, (ah->imask & ATH9K_INT_SWBA));
tasklet_schedule(&sc->intr_tq);
}
......@@ -887,7 +887,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
ath_beacon_config(sc, NULL); /* restart beacons */
/* Re-Enable interrupts */
ath9k_hw_set_interrupts(ah, sc->imask);
ath9k_hw_set_interrupts(ah, ah->imask);
/* Enable LED */
ath9k_hw_cfg_output(ah, ah->led_pin,
......@@ -977,7 +977,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
if (sc->sc_flags & SC_OP_BEACONS)
ath_beacon_config(sc, NULL); /* restart beacons */
ath9k_hw_set_interrupts(ah, sc->imask);
ath9k_hw_set_interrupts(ah, ah->imask);
if (retry_tx) {
int i;
......@@ -1162,23 +1162,23 @@ static int ath9k_start(struct ieee80211_hw *hw)
}
/* Setup our intr mask. */
sc->imask = ATH9K_INT_RX | ATH9K_INT_TX
ah->imask = ATH9K_INT_RX | ATH9K_INT_TX
| ATH9K_INT_RXEOL | ATH9K_INT_RXORN
| ATH9K_INT_FATAL | ATH9K_INT_GLOBAL;
if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT)
sc->imask |= ATH9K_INT_GTT;
ah->imask |= ATH9K_INT_GTT;
if (ah->caps.hw_caps & ATH9K_HW_CAP_HT)
sc->imask |= ATH9K_INT_CST;
ah->imask |= ATH9K_INT_CST;
ath_cache_conf_rate(sc, &hw->conf);
sc->sc_flags &= ~SC_OP_INVALID;
/* Disable BMISS interrupt when we're not associated */
sc->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
ath9k_hw_set_interrupts(ah, sc->imask);
ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
ath9k_hw_set_interrupts(ah, ah->imask);
ieee80211_wake_queues(hw);
......@@ -1372,14 +1372,15 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ath_vif *avp = (void *)vif->drv_priv;
enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED;
int ret = 0;
mutex_lock(&sc->mutex);
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) &&
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) &&
sc->nvifs > 0) {
ret = -ENOBUFS;
goto out;
......@@ -1414,19 +1415,19 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
sc->nvifs++;
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
ath9k_set_bssid_mask(hw);
if (sc->nvifs > 1)
goto out; /* skip global settings for secondary vif */
if (ic_opmode == NL80211_IFTYPE_AP) {
ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
ath9k_hw_set_tsfadjust(ah, 1);
sc->sc_flags |= SC_OP_TSF_RESET;
}
/* Set the device opmode */
sc->sc_ah->opmode = ic_opmode;
ah->opmode = ic_opmode;
/*
* Enable MIB interrupts when there are hardware phy counters.
......@@ -1435,11 +1436,11 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
if ((vif->type == NL80211_IFTYPE_STATION) ||
(vif->type == NL80211_IFTYPE_ADHOC) ||
(vif->type == NL80211_IFTYPE_MESH_POINT)) {
sc->imask |= ATH9K_INT_MIB;
sc->imask |= ATH9K_INT_TSFOOR;
ah->imask |= ATH9K_INT_MIB;
ah->imask |= ATH9K_INT_TSFOOR;
}
ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
ath9k_hw_set_interrupts(ah, ah->imask);
if (vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_ADHOC ||
......@@ -1495,15 +1496,16 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
void ath9k_enable_ps(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
sc->ps_enabled = true;
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) {
sc->imask |= ATH9K_INT_TIM_TIMER;
ath9k_hw_set_interrupts(sc->sc_ah,
sc->imask);
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
if ((ah->imask & ATH9K_INT_TIM_TIMER) == 0) {
ah->imask |= ATH9K_INT_TIM_TIMER;
ath9k_hw_set_interrupts(ah, ah->imask);
}
}
ath9k_hw_setrxabort(sc->sc_ah, 1);
ath9k_hw_setrxabort(ah, 1);
}
static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
......@@ -1579,10 +1581,10 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
PS_WAIT_FOR_CAB |
PS_WAIT_FOR_PSPOLL_DATA |
PS_WAIT_FOR_TX_ACK);
if (sc->imask & ATH9K_INT_TIM_TIMER) {
sc->imask &= ~ATH9K_INT_TIM_TIMER;
if (ah->imask & ATH9K_INT_TIM_TIMER) {
ah->imask &= ~ATH9K_INT_TIM_TIMER;
ath9k_hw_set_interrupts(sc->sc_ah,
sc->imask);
ah->imask);
}
}
}
......
......@@ -88,6 +88,7 @@ static void ath_pci_bt_coex_prep(struct ath_common *common)
}
static const struct ath_bus_ops ath_pci_bus_ops = {
.ath_bus_type = ATH_PCI,
.read_cachesize = ath_pci_read_cachesize,
.eeprom_read = ath_pci_eeprom_read,
.bt_coex_prep = ath_pci_bt_coex_prep,
......
......@@ -503,6 +503,8 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah,
#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24
#define AR_PHY_TX_PWRCTRL7 0xa274
#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX 0x0007E000
#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX_S 13
#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000
#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19
......@@ -513,8 +515,16 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah,
#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31
#define AR_PHY_TX_GAIN_TBL1 0xa300
#define AR_PHY_TX_GAIN 0x0007F000
#define AR_PHY_TX_GAIN_S 12
#define AR_PHY_TX_GAIN_CLC 0x0000001E
#define AR_PHY_TX_GAIN_CLC_S 1
#define AR_PHY_TX_GAIN 0x0007F000
#define AR_PHY_TX_GAIN_S 12
#define AR_PHY_CLC_TBL1 0xa35c
#define AR_PHY_CLC_I0 0x07ff0000
#define AR_PHY_CLC_I0_S 16
#define AR_PHY_CLC_Q0 0x0000ffd0
#define AR_PHY_CLC_Q0_S 5
#define AR_PHY_CH0_TX_PWRCTRL11 0xa398
#define AR_PHY_CH1_TX_PWRCTRL11 0xb398
......
......@@ -176,9 +176,9 @@ struct ath_rate_priv {
#define ATH_TX_INFO_UNDERRUN (1 << 4)
enum ath9k_internal_frame_type {
ATH9K_NOT_INTERNAL,
ATH9K_INT_PAUSE,
ATH9K_INT_UNPAUSE
ATH9K_IFT_NOT_INTERNAL,
ATH9K_IFT_PAUSE,
ATH9K_IFT_UNPAUSE
};
int ath_rate_control_register(void);
......
......@@ -477,7 +477,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
struct ath_buf *bf;
struct ath_desc *ds;
struct ath_rx_status *rx_stats;
struct sk_buff *skb = NULL, *requeue_skb;
struct ieee80211_rx_status *rxs;
struct ath_hw *ah = sc->sc_ah;
......@@ -491,6 +490,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
struct ieee80211_hdr *hdr;
int retval;
bool decrypt_error = false;
struct ath_rx_status rs;
spin_lock_bh(&sc->rx.rxbuflock);
......@@ -518,14 +518,14 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
* on. All this is necessary because of our use of
* a self-linked list to avoid rx overruns.
*/
retval = ath9k_hw_rxprocdesc(ah, ds,
bf->bf_daddr,
PA2DESC(sc, ds->ds_link),
0);
memset(&rs, 0, sizeof(rs));
retval = ath9k_hw_rxprocdesc(ah, ds, &rs, 0);
if (retval == -EINPROGRESS) {
struct ath_rx_status trs;
struct ath_buf *tbf;
struct ath_desc *tds;
memset(&trs, 0, sizeof(trs));
if (list_is_last(&bf->list, &sc->rx.rxbuf)) {
sc->rx.rxlink = NULL;
break;
......@@ -545,8 +545,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
*/
tds = tbf->bf_desc;
retval = ath9k_hw_rxprocdesc(ah, tds, tbf->bf_daddr,
PA2DESC(sc, tds->ds_link), 0);
retval = ath9k_hw_rxprocdesc(ah, tds, &trs, 0);
if (retval == -EINPROGRESS) {
break;
}
......@@ -569,9 +568,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
rxs = IEEE80211_SKB_RXCB(skb);
hw = ath_get_virt_hw(sc, hdr);
rx_stats = &ds->ds_rxstat;
ath_debug_stat_rx(sc, bf);
ath_debug_stat_rx(sc, &rs);
/*
* If we're asked to flush receive queue, directly
......@@ -580,7 +578,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
if (flush)
goto requeue;
retval = ath9k_cmn_rx_skb_preprocess(common, hw, skb, rx_stats,
retval = ath9k_cmn_rx_skb_preprocess(common, hw, skb, &rs,
rxs, &decrypt_error);
if (retval)
goto requeue;
......@@ -601,9 +599,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
common->rx_bufsize,
DMA_FROM_DEVICE);
skb_put(skb, rx_stats->rs_datalen);
skb_put(skb, rs.rs_datalen);
ath9k_cmn_rx_skb_postprocess(common, skb, rx_stats,
ath9k_cmn_rx_skb_postprocess(common, skb, &rs,
rxs, decrypt_error);
/* We will now give hardware our shiny new allocated skb */
......@@ -626,9 +624,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
* change the default rx antenna if rx diversity chooses the
* other antenna 3 times in a row.
*/
if (sc->rx.defant != ds->ds_rxstat.rs_antenna) {
if (sc->rx.defant != rs.rs_antenna) {
if (++sc->rx.rxotherant >= 3)
ath_setdefantenna(sc, rx_stats->rs_antenna);
ath_setdefantenna(sc, rs.rs_antenna);
} else {
sc->rx.rxotherant = 0;
}
......
......@@ -679,7 +679,7 @@
#define AR_WA 0x4004
#define AR_WA_D3_L1_DISABLE (1 << 14)
#define AR9285_WA_DEFAULT 0x004a05cb
#define AR9285_WA_DEFAULT 0x004a050b
#define AR9280_WA_DEFAULT 0x0040073b
#define AR_WA_DEFAULT 0x0000073f
......@@ -845,6 +845,10 @@
(AR_SREV_9271(_ah) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11))
#define AR_SREV_9285E_20(_ah) \
(AR_SREV_9285_12_OR_LATER(_ah) && \
((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
#define AR_RADIO_SREV_MAJOR 0xf0
#define AR_RAD5133_SREV_MAJOR 0xc0
#define AR_RAD2133_SREV_MAJOR 0xd0
......@@ -1181,6 +1185,13 @@ enum {
#define AR9285_AN_RF2G4_DB2_4 0x00003800
#define AR9285_AN_RF2G4_DB2_4_S 11
#define AR9285_RF2G5 0x7830
#define AR9285_RF2G5_IC50TX 0xfffff8ff
#define AR9285_RF2G5_IC50TX_SET 0x00000400
#define AR9285_RF2G5_IC50TX_XE_SET 0x00000500
#define AR9285_RF2G5_IC50TX_CLEAR 0x00000700
#define AR9285_RF2G5_IC50TX_CLEAR_S 8
/* AR9271 : 0x7828, 0x782c different setting from AR9285 */
#define AR9271_AN_RF2G3_OB_cck 0x001C0000
#define AR9271_AN_RF2G3_OB_cck_S 18
......
......@@ -220,7 +220,7 @@ static int ath9k_send_nullfunc(struct ath_wiphy *aphy,
memset(&txctl, 0, sizeof(struct ath_tx_control));
txctl.txq = &sc->tx.txq[sc->tx.hwq_map[ATH9K_WME_AC_VO]];
txctl.frame_type = ps ? ATH9K_INT_PAUSE : ATH9K_INT_UNPAUSE;
txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE;
if (ath_tx_start(aphy->hw, skb, &txctl) != 0)
goto exit;
......
......@@ -169,7 +169,7 @@ void ath9k_wmi_tasklet(unsigned long data)
break;
}
dev_kfree_skb_any(skb);
kfree_skb(skb);
}
static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb)
......@@ -207,13 +207,13 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
ath9k_wmi_rsp_callback(wmi, skb);
free_skb:
dev_kfree_skb_any(skb);
kfree_skb(skb);
}
static void ath9k_wmi_ctrl_tx(void *priv, struct sk_buff *skb,
enum htc_endpoint_id epid, bool txok)
{
dev_kfree_skb_any(skb);
kfree_skb(skb);
}
int ath9k_wmi_connect(struct htc_target *htc, struct wmi *wmi,
......@@ -269,7 +269,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
if (!wmi)
return -EINVAL;
skb = dev_alloc_skb(headroom + cmd_len);
skb = alloc_skb(headroom + cmd_len, GFP_ATOMIC);
if (!skb)
return -ENOMEM;
......@@ -313,7 +313,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
ath_print(common, ATH_DBG_WMI,
"WMI failure for: %s\n", wmi_cmd_to_name(cmd_id));
mutex_unlock(&wmi->op_mutex);
dev_kfree_skb_any(skb);
kfree_skb(skb);
return ret;
}
......@@ -19,8 +19,8 @@
#include "ath.h"
#include "reg.h"
#define REG_READ common->ops->read
#define REG_WRITE common->ops->write
#define REG_READ (common->ops->read)
#define REG_WRITE (common->ops->write)
/**
* ath_hw_set_bssid_mask - filter out bssids we listen
......
......@@ -50,6 +50,7 @@
#define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, \
ATH9K_5GHZ_5470_5850
/* This one skips what we call "mid band" */
#define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \
ATH9K_5GHZ_5725_5850
......@@ -360,7 +361,7 @@ EXPORT_SYMBOL(ath_reg_notifier_apply);
static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg)
{
u16 rd = ath_regd_get_eepromRD(reg);
u16 rd = ath_regd_get_eepromRD(reg);
int i;
if (rd & COUNTRY_ERD_FLAG) {
......
......@@ -105,7 +105,7 @@ static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
}
static void b43_chantab_radio_upload(struct b43_wldev *dev,
const struct b43_nphy_channeltab_entry *e)
const struct b43_nphy_channeltab_entry_rev2 *e)
{
b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref);
b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0);
......@@ -142,7 +142,7 @@ static void b43_chantab_radio_upload(struct b43_wldev *dev,
}
static void b43_chantab_phy_upload(struct b43_wldev *dev,
const struct b43_nphy_channeltab_entry *e)
const struct b43_phy_n_sfo_cfg *e)
{
b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a);
b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2);
......@@ -160,16 +160,16 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
static void b43_radio_2055_setup(struct b43_wldev *dev,
const struct b43_nphy_channeltab_entry *e)
const struct b43_nphy_channeltab_entry_rev2 *e)
{
B43_WARN_ON(dev->phy.rev >= 3);
b43_chantab_radio_upload(dev, e);
udelay(50);
b43_radio_write(dev, B2055_VCO_CAL10, 5);
b43_radio_write(dev, B2055_VCO_CAL10, 45);
b43_radio_write(dev, B2055_VCO_CAL10, 0x05);
b43_radio_write(dev, B2055_VCO_CAL10, 0x45);
b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
b43_radio_write(dev, B2055_VCO_CAL10, 65);
b43_radio_write(dev, B2055_VCO_CAL10, 0x65);
udelay(300);
}
......@@ -254,6 +254,16 @@ static void b43_radio_init2055(struct b43_wldev *dev)
b43_radio_init2055_post(dev);
}
/*
* Initialize a Broadcom 2056 N-radio
* http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init
*/
static void b43_radio_init2056(struct b43_wldev *dev)
{
/* TODO */
}
/*
* Upload the N-PHY tables.
* http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
......@@ -2791,7 +2801,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
}
b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
buffer);
b43_ntab_write_bulk(dev, B43_NTAB16(15, 101), 2,
b43_ntab_read_bulk(dev, B43_NTAB16(15, 101), 2,
buffer);
b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
buffer);
......@@ -3261,7 +3271,7 @@ int b43_phy_initn(struct b43_wldev *dev)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */
static void b43_nphy_chanspec_setup(struct b43_wldev *dev,
const struct b43_nphy_channeltab_entry *e,
const struct b43_phy_n_sfo_cfg *e,
struct b43_chanspec chanspec)
{
struct b43_phy *phy = &dev->phy;
......@@ -3327,13 +3337,21 @@ static int b43_nphy_set_chanspec(struct b43_wldev *dev,
{
struct b43_phy_n *nphy = dev->phy.n;
const struct b43_nphy_channeltab_entry *tabent;
const struct b43_nphy_channeltab_entry_rev2 *tabent_r2;
const struct b43_nphy_channeltab_entry_rev3 *tabent_r3;
u8 tmp;
u8 channel = chanspec.channel;
if (dev->phy.rev >= 3) {
/* TODO */
tabent_r3 = NULL;
if (!tabent_r3)
return -ESRCH;
} else {
tabent_r2 = b43_nphy_get_chantabent_rev2(dev, channel);
if (!tabent_r2)
return -ESRCH;
}
nphy->radio_chanspec = chanspec;
......@@ -3354,17 +3372,13 @@ static int b43_nphy_set_chanspec(struct b43_wldev *dev,
if (dev->phy.rev >= 3) {
tmp = (chanspec.b_freq == 1) ? 4 : 0;
b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
/* TODO: PHY Radio2056 Setup (chan_info_ptr[i]) */
/* TODO: N PHY Chanspec Setup (chan_info_ptr[i]) */
/* TODO: PHY Radio2056 Setup (dev, tabent_r3); */
b43_nphy_chanspec_setup(dev, &(tabent_r3->phy_regs), chanspec);
} else {
tabent = b43_nphy_get_chantabent(dev, channel);
if (!tabent)
return -ESRCH;
tmp = (chanspec.b_freq == 1) ? 0x0020 : 0x0050;
b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp);
b43_radio_2055_setup(dev, tabent);
b43_nphy_chanspec_setup(dev, tabent, chanspec);
b43_radio_2055_setup(dev, tabent_r2);
b43_nphy_chanspec_setup(dev, &(tabent_r2->phy_regs), chanspec);
}
return 0;
......@@ -3474,6 +3488,8 @@ static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
bool blocked)
{
struct b43_phy_n *nphy = dev->phy.n;
if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
b43err(dev->wl, "MAC not suspended\n");
......@@ -3499,8 +3515,8 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
}
} else {
if (dev->phy.rev >= 3) {
/* TODO: b43_radio_init2056(dev); */
/* TODO: PHY Set Channel Spec (dev, radio_chanspec) */
b43_radio_init2056(dev);
b43_nphy_set_chanspec(dev, nphy->radio_chanspec);
} else {
b43_radio_init2055(dev);
}
......
......@@ -318,14 +318,14 @@ void b2055_upload_inittab(struct b43_wldev *dev,
.radio_c2_tx_mxbgtrim = r21
#define PHYREGS(r0, r1, r2, r3, r4, r5) \
.phy_bw1a = r0, \
.phy_bw2 = r1, \
.phy_bw3 = r2, \
.phy_bw4 = r3, \
.phy_bw5 = r4, \
.phy_bw6 = r5
static const struct b43_nphy_channeltab_entry b43_nphy_channeltab[] = {
.phy_regs.phy_bw1a = r0, \
.phy_regs.phy_bw2 = r1, \
.phy_regs.phy_bw3 = r2, \
.phy_regs.phy_bw4 = r3, \
.phy_regs.phy_bw5 = r4, \
.phy_regs.phy_bw6 = r5
static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab[] = {
{ .channel = 184,
.freq = 4920, /* MHz */
.unk2 = 3280,
......@@ -1320,10 +1320,10 @@ static const struct b43_nphy_channeltab_entry b43_nphy_channeltab[] = {
},
};
const struct b43_nphy_channeltab_entry *
b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel)
const struct b43_nphy_channeltab_entry_rev2 *
b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel)
{
const struct b43_nphy_channeltab_entry *e;
const struct b43_nphy_channeltab_entry_rev2 *e;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab); i++) {
......
......@@ -10,6 +10,8 @@ CFLAGS_iwl-devtrace.o := -I$(src)
# AGN
obj-$(CONFIG_IWLAGN) += iwlagn.o
iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o
iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o
iwlagn-objs += iwl-agn-lib.o
iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
iwlagn-$(CONFIG_IWL5000) += iwl-5000.o
......
......@@ -71,10 +71,6 @@
#include "iwl-eeprom.h"
/* Time constants */
#define SHORT_SLOT_TIME 9
#define LONG_SLOT_TIME 20
/* RSSI to dBm */
#define IWL39_RSSI_OFFSET 95
......@@ -230,7 +226,6 @@ struct iwl3945_eeprom {
/* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */
#define IWL39_NUM_QUEUES 5
#define IWL_NUM_SCAN_RATES (2)
#define IWL_DEFAULT_TX_RETRY 15
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册