Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
7282907126
|
@ -50,7 +50,6 @@ obj-$(CONFIG_ATH_COMMON) += ath/
|
|||
obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
|
||||
|
||||
obj-$(CONFIG_WL12XX) += wl12xx/
|
||||
# small builtin driver bit
|
||||
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx/wl12xx_platform_data.o
|
||||
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx/
|
||||
|
||||
obj-$(CONFIG_IWM) += iwmc3200wifi/
|
||||
|
|
|
@ -217,7 +217,6 @@ static const char *statsLabels[] = {
|
|||
(no spaces) list of rates (up to 8). */
|
||||
|
||||
static int rates[8];
|
||||
static int basic_rate;
|
||||
static char *ssids[3];
|
||||
|
||||
static int io[4];
|
||||
|
@ -250,7 +249,6 @@ MODULE_LICENSE("Dual BSD/GPL");
|
|||
MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340/350");
|
||||
module_param_array(io, int, NULL, 0);
|
||||
module_param_array(irq, int, NULL, 0);
|
||||
module_param(basic_rate, int, 0);
|
||||
module_param_array(rates, int, NULL, 0);
|
||||
module_param_array(ssids, charp, NULL, 0);
|
||||
module_param(auto_wep, int, 0);
|
||||
|
@ -3883,15 +3881,6 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
|
|||
ai->config.rates[i] = rates[i];
|
||||
}
|
||||
}
|
||||
if ( basic_rate > 0 ) {
|
||||
for( i = 0; i < 8; i++ ) {
|
||||
if ( ai->config.rates[i] == basic_rate ||
|
||||
!ai->config.rates ) {
|
||||
ai->config.rates[i] = basic_rate | 0x80;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
set_bit (FLAG_COMMIT, &ai->flags);
|
||||
}
|
||||
|
||||
|
|
|
@ -1041,7 +1041,6 @@ struct ath5k_hw {
|
|||
#define ah_modes ah_capabilities.cap_mode
|
||||
#define ah_ee_version ah_capabilities.cap_eeprom.ee_version
|
||||
|
||||
u32 ah_atim_window;
|
||||
u32 ah_limit_tx_retries;
|
||||
u8 ah_coverage_class;
|
||||
|
||||
|
@ -1196,6 +1195,7 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah);
|
|||
void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64);
|
||||
void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
|
||||
void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval);
|
||||
bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval);
|
||||
/* ACK bit rate */
|
||||
void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
|
||||
/* Clock rate related functions */
|
||||
|
|
|
@ -118,7 +118,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
|
|||
ah->ah_turbo = false;
|
||||
ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
|
||||
ah->ah_imr = 0;
|
||||
ah->ah_atim_window = 0;
|
||||
ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
|
||||
ah->ah_software_retry = false;
|
||||
ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
|
||||
|
|
|
@ -1191,6 +1191,15 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
|
|||
*/
|
||||
if (hw_tu >= sc->nexttbtt)
|
||||
ath5k_beacon_update_timers(sc, bc_tstamp);
|
||||
|
||||
/* Check if the beacon timers are still correct, because a TSF
|
||||
* update might have created a window between them - for a
|
||||
* longer description see the comment of this function: */
|
||||
if (!ath5k_hw_check_beacon_timers(sc->ah, sc->bintval)) {
|
||||
ath5k_beacon_update_timers(sc, bc_tstamp);
|
||||
ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
|
||||
"fixed beacon timers after beacon receive\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1877,8 +1886,11 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
|
|||
hw_tsf = ath5k_hw_get_tsf64(ah);
|
||||
hw_tu = TSF_TO_TU(hw_tsf);
|
||||
|
||||
#define FUDGE 3
|
||||
/* we use FUDGE to make sure the next TBTT is ahead of the current TU */
|
||||
#define FUDGE AR5K_TUNE_SW_BEACON_RESP + 3
|
||||
/* We use FUDGE to make sure the next TBTT is ahead of the current TU.
|
||||
* Since we later substract AR5K_TUNE_SW_BEACON_RESP (10) in the timer
|
||||
* configuration we need to make sure it is bigger than that. */
|
||||
|
||||
if (bc_tsf == -1) {
|
||||
/*
|
||||
* no beacons received, called internally.
|
||||
|
|
|
@ -483,6 +483,59 @@ static const struct file_operations fops_antenna = {
|
|||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
/* debugfs: misc */
|
||||
|
||||
static ssize_t read_file_misc(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath5k_softc *sc = file->private_data;
|
||||
char buf[700];
|
||||
unsigned int len = 0;
|
||||
u32 filt = ath5k_hw_get_rx_filter(sc->ah);
|
||||
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "bssid-mask: %pM\n",
|
||||
sc->bssidmask);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "filter-flags: 0x%x ",
|
||||
filt);
|
||||
if (filt & AR5K_RX_FILTER_UCAST)
|
||||
len += snprintf(buf+len, sizeof(buf)-len, " UCAST");
|
||||
if (filt & AR5K_RX_FILTER_MCAST)
|
||||
len += snprintf(buf+len, sizeof(buf)-len, " MCAST");
|
||||
if (filt & AR5K_RX_FILTER_BCAST)
|
||||
len += snprintf(buf+len, sizeof(buf)-len, " BCAST");
|
||||
if (filt & AR5K_RX_FILTER_CONTROL)
|
||||
len += snprintf(buf+len, sizeof(buf)-len, " CONTROL");
|
||||
if (filt & AR5K_RX_FILTER_BEACON)
|
||||
len += snprintf(buf+len, sizeof(buf)-len, " BEACON");
|
||||
if (filt & AR5K_RX_FILTER_PROM)
|
||||
len += snprintf(buf+len, sizeof(buf)-len, " PROM");
|
||||
if (filt & AR5K_RX_FILTER_XRPOLL)
|
||||
len += snprintf(buf+len, sizeof(buf)-len, " XRPOLL");
|
||||
if (filt & AR5K_RX_FILTER_PROBEREQ)
|
||||
len += snprintf(buf+len, sizeof(buf)-len, " PROBEREQ");
|
||||
if (filt & AR5K_RX_FILTER_PHYERR_5212)
|
||||
len += snprintf(buf+len, sizeof(buf)-len, " PHYERR-5212");
|
||||
if (filt & AR5K_RX_FILTER_RADARERR_5212)
|
||||
len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5212");
|
||||
if (filt & AR5K_RX_FILTER_PHYERR_5211)
|
||||
snprintf(buf+len, sizeof(buf)-len, " PHYERR-5211");
|
||||
if (filt & AR5K_RX_FILTER_RADARERR_5211)
|
||||
len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5211\n");
|
||||
else
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "\n");
|
||||
|
||||
if (len > sizeof(buf))
|
||||
len = sizeof(buf);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_misc = {
|
||||
.read = read_file_misc,
|
||||
.open = ath5k_debugfs_open,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
||||
/* debugfs: frameerrors */
|
||||
|
||||
|
@ -856,6 +909,10 @@ ath5k_debug_init_device(struct ath5k_softc *sc)
|
|||
S_IWUSR | S_IRUSR,
|
||||
sc->debug.debugfs_phydir, sc, &fops_antenna);
|
||||
|
||||
sc->debug.debugfs_misc = debugfs_create_file("misc",
|
||||
S_IRUSR,
|
||||
sc->debug.debugfs_phydir, sc, &fops_misc);
|
||||
|
||||
sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors",
|
||||
S_IWUSR | S_IRUSR,
|
||||
sc->debug.debugfs_phydir, sc,
|
||||
|
@ -886,6 +943,7 @@ ath5k_debug_finish_device(struct ath5k_softc *sc)
|
|||
debugfs_remove(sc->debug.debugfs_beacon);
|
||||
debugfs_remove(sc->debug.debugfs_reset);
|
||||
debugfs_remove(sc->debug.debugfs_antenna);
|
||||
debugfs_remove(sc->debug.debugfs_misc);
|
||||
debugfs_remove(sc->debug.debugfs_frameerrors);
|
||||
debugfs_remove(sc->debug.debugfs_ani);
|
||||
debugfs_remove(sc->debug.debugfs_queue);
|
||||
|
|
|
@ -75,6 +75,7 @@ struct ath5k_dbg_info {
|
|||
struct dentry *debugfs_beacon;
|
||||
struct dentry *debugfs_reset;
|
||||
struct dentry *debugfs_antenna;
|
||||
struct dentry *debugfs_misc;
|
||||
struct dentry *debugfs_frameerrors;
|
||||
struct dentry *debugfs_ani;
|
||||
struct dentry *debugfs_queue;
|
||||
|
|
|
@ -244,7 +244,7 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
|
|||
|
||||
/* Force channel idle high */
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
|
||||
AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
|
||||
AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
|
||||
|
||||
/* Wait a while and disable mechanism */
|
||||
udelay(200);
|
||||
|
@ -261,7 +261,7 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
|
|||
} while (--i && pending);
|
||||
|
||||
AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211,
|
||||
AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
|
||||
AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
|
||||
}
|
||||
|
||||
/* Clear register */
|
||||
|
|
|
@ -495,6 +495,10 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
|
|||
{
|
||||
u32 tsf_lower, tsf_upper1, tsf_upper2;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
/* This code is time critical - we don't want to be interrupted here */
|
||||
local_irq_save(flags);
|
||||
|
||||
/*
|
||||
* While reading TSF upper and then lower part, the clock is still
|
||||
|
@ -517,6 +521,8 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
|
|||
tsf_upper1 = tsf_upper2;
|
||||
}
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
WARN_ON( i == ATH5K_MAX_TSF_READ );
|
||||
|
||||
return (((u64)tsf_upper1 << 32) | tsf_lower);
|
||||
|
@ -600,7 +606,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
|
|||
/* Timer3 marks the end of our ATIM window
|
||||
* a zero length window is not allowed because
|
||||
* we 'll get no beacons */
|
||||
timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1);
|
||||
timer3 = next_beacon + 1;
|
||||
|
||||
/*
|
||||
* Set the beacon register and enable all timers.
|
||||
|
@ -640,6 +646,97 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* ath5k_check_timer_win - Check if timer B is timer A + window
|
||||
*
|
||||
* @a: timer a (before b)
|
||||
* @b: timer b (after a)
|
||||
* @window: difference between a and b
|
||||
* @intval: timers are increased by this interval
|
||||
*
|
||||
* This helper function checks if timer B is timer A + window and covers
|
||||
* cases where timer A or B might have already been updated or wrapped
|
||||
* around (Timers are 16 bit).
|
||||
*
|
||||
* Returns true if O.K.
|
||||
*/
|
||||
static inline bool
|
||||
ath5k_check_timer_win(int a, int b, int window, int intval)
|
||||
{
|
||||
/*
|
||||
* 1.) usually B should be A + window
|
||||
* 2.) A already updated, B not updated yet
|
||||
* 3.) A already updated and has wrapped around
|
||||
* 4.) B has wrapped around
|
||||
*/
|
||||
if ((b - a == window) || /* 1.) */
|
||||
(a - b == intval - window) || /* 2.) */
|
||||
((a | 0x10000) - b == intval - window) || /* 3.) */
|
||||
((b | 0x10000) - a == window)) /* 4.) */
|
||||
return true; /* O.K. */
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* ath5k_hw_check_beacon_timers - Check if the beacon timers are correct
|
||||
*
|
||||
* @ah: The &struct ath5k_hw
|
||||
* @intval: beacon interval
|
||||
*
|
||||
* This is a workaround for IBSS mode:
|
||||
*
|
||||
* The need for this function arises from the fact that we have 4 separate
|
||||
* HW timer registers (TIMER0 - TIMER3), which are closely related to the
|
||||
* next beacon target time (NBTT), and that the HW updates these timers
|
||||
* seperately based on the current TSF value. The hardware increments each
|
||||
* timer by the beacon interval, when the local TSF coverted to TU is equal
|
||||
* to the value stored in the timer.
|
||||
*
|
||||
* The reception of a beacon with the same BSSID can update the local HW TSF
|
||||
* at any time - this is something we can't avoid. If the TSF jumps to a
|
||||
* time which is later than the time stored in a timer, this timer will not
|
||||
* be updated until the TSF in TU wraps around at 16 bit (the size of the
|
||||
* timers) and reaches the time which is stored in the timer.
|
||||
*
|
||||
* The problem is that these timers are closely related to TIMER0 (NBTT) and
|
||||
* that they define a time "window". When the TSF jumps between two timers
|
||||
* (e.g. ATIM and NBTT), the one in the past will be left behind (not
|
||||
* updated), while the one in the future will be updated every beacon
|
||||
* interval. This causes the window to get larger, until the TSF wraps
|
||||
* around as described above and the timer which was left behind gets
|
||||
* updated again. But - because the beacon interval is usually not an exact
|
||||
* divisor of the size of the timers (16 bit), an unwanted "window" between
|
||||
* these timers has developed!
|
||||
*
|
||||
* This is especially important with the ATIM window, because during
|
||||
* the ATIM window only ATIM frames and no data frames are allowed to be
|
||||
* sent, which creates transmission pauses after each beacon. This symptom
|
||||
* has been described as "ramping ping" because ping times increase linearly
|
||||
* for some time and then drop down again. A wrong window on the DMA beacon
|
||||
* timer has the same effect, so we check for these two conditions.
|
||||
*
|
||||
* Returns true if O.K.
|
||||
*/
|
||||
bool
|
||||
ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval)
|
||||
{
|
||||
unsigned int nbtt, atim, dma;
|
||||
|
||||
nbtt = ath5k_hw_reg_read(ah, AR5K_TIMER0);
|
||||
atim = ath5k_hw_reg_read(ah, AR5K_TIMER3);
|
||||
dma = ath5k_hw_reg_read(ah, AR5K_TIMER1) >> 3;
|
||||
|
||||
/* NOTE: SWBA is different. Having a wrong window there does not
|
||||
* stop us from sending data and this condition is catched thru
|
||||
* other means (SWBA interrupt) */
|
||||
|
||||
if (ath5k_check_timer_win(nbtt, atim, 1, intval) &&
|
||||
ath5k_check_timer_win(dma, nbtt, AR5K_TUNE_DMA_BEACON_RESP,
|
||||
intval))
|
||||
return true; /* O.K. */
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class
|
||||
*
|
||||
|
|
|
@ -1257,7 +1257,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
|
|||
* Disable beacons and RX/TX queues, wait
|
||||
*/
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210,
|
||||
AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
|
||||
AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210);
|
||||
beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
|
||||
ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);
|
||||
|
||||
|
@ -1336,7 +1336,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
|
|||
* Re-enable RX/TX and beacons
|
||||
*/
|
||||
AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210,
|
||||
AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
|
||||
AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210);
|
||||
ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1387,10 +1387,9 @@
|
|||
|
||||
|
||||
/*
|
||||
* PCU control register
|
||||
* PCU Diagnostic register
|
||||
*
|
||||
* Only DIS_RX is used in the code, the rest i guess are
|
||||
* for tweaking/diagnostics.
|
||||
* Used for tweaking/diagnostics.
|
||||
*/
|
||||
#define AR5K_DIAG_SW_5210 0x8068 /* Register Address [5210] */
|
||||
#define AR5K_DIAG_SW_5211 0x8048 /* Register Address [5211+] */
|
||||
|
@ -1399,22 +1398,22 @@
|
|||
#define AR5K_DIAG_SW_DIS_WEP_ACK 0x00000001 /* Disable ACKs if WEP key is invalid */
|
||||
#define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs */
|
||||
#define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs */
|
||||
#define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable encryption */
|
||||
#define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable decryption */
|
||||
#define AR5K_DIAG_SW_DIS_TX 0x00000020 /* Disable transmit [5210] */
|
||||
#define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable recieve */
|
||||
#define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable HW encryption */
|
||||
#define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable HW decryption */
|
||||
#define AR5K_DIAG_SW_DIS_TX_5210 0x00000020 /* Disable transmit [5210] */
|
||||
#define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable receive */
|
||||
#define AR5K_DIAG_SW_DIS_RX_5211 0x00000020
|
||||
#define AR5K_DIAG_SW_DIS_RX (ah->ah_version == AR5K_AR5210 ? \
|
||||
AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211)
|
||||
#define AR5K_DIAG_SW_LOOP_BACK_5210 0x00000080 /* Loopback (i guess it goes with DIS_TX) [5210] */
|
||||
#define AR5K_DIAG_SW_LOOP_BACK_5210 0x00000080 /* TX Data Loopback (i guess it goes with DIS_TX) [5210] */
|
||||
#define AR5K_DIAG_SW_LOOP_BACK_5211 0x00000040
|
||||
#define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \
|
||||
AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211)
|
||||
#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 /* Corrupted FCS */
|
||||
#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 /* Generate invalid TX FCS */
|
||||
#define AR5K_DIAG_SW_CORR_FCS_5211 0x00000080
|
||||
#define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \
|
||||
AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211)
|
||||
#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 /* Dump channel info */
|
||||
#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 /* Add 56 bytes of channel info before the frame data in the RX buffer */
|
||||
#define AR5K_DIAG_SW_CHAN_INFO_5211 0x00000100
|
||||
#define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \
|
||||
AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211)
|
||||
|
@ -1426,17 +1425,17 @@
|
|||
#define AR5K_DIAG_SW_SCVRAM_SEED 0x0003f800 /* [5210] */
|
||||
#define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask */
|
||||
#define AR5K_DIAG_SW_SCRAM_SEED_S 10
|
||||
#define AR5K_DIAG_SW_DIS_SEQ_INC 0x00040000 /* Disable seqnum increment (?)[5210] */
|
||||
#define AR5K_DIAG_SW_DIS_SEQ_INC_5210 0x00040000 /* Disable seqnum increment (?)[5210] */
|
||||
#define AR5K_DIAG_SW_FRAME_NV0_5210 0x00080000
|
||||
#define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000 /* Accept frames of non-zero protocol number */
|
||||
#define AR5K_DIAG_SW_FRAME_NV0 (ah->ah_version == AR5K_AR5210 ? \
|
||||
AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211)
|
||||
#define AR5K_DIAG_SW_OBSPT_M 0x000c0000 /* Observation point select (?) */
|
||||
#define AR5K_DIAG_SW_OBSPT_S 18
|
||||
#define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x0010000 /* Force RX Clear high */
|
||||
#define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x0020000 /* Ignore virtual carrier sense */
|
||||
#define AR5K_DIAG_SW_CHANEL_IDLE_HIGH 0x0040000 /* Force channel idle high */
|
||||
#define AR5K_DIAG_SW_PHEAR_ME 0x0080000 /* ??? */
|
||||
#define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x00100000 /* Ignore carrier sense */
|
||||
#define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x00200000 /* Ignore virtual carrier sense */
|
||||
#define AR5K_DIAG_SW_CHANNEL_IDLE_HIGH 0x00400000 /* Force channel idle high */
|
||||
#define AR5K_DIAG_SW_PHEAR_ME 0x00800000 /* ??? */
|
||||
|
||||
/*
|
||||
* TSF (clock) register (lower 32 bits)
|
||||
|
|
|
@ -118,7 +118,7 @@ static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq)
|
|||
if (!AR_SREV_5416(ah) || synth_freq >= 3000)
|
||||
return;
|
||||
|
||||
BUG_ON(AR_SREV_9280_10_OR_LATER(ah));
|
||||
BUG_ON(AR_SREV_9280_20_OR_LATER(ah));
|
||||
|
||||
if (synth_freq < 2412)
|
||||
new_bias = 0;
|
||||
|
@ -454,7 +454,7 @@ static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah)
|
|||
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
BUG_ON(AR_SREV_9280_10_OR_LATER(ah));
|
||||
BUG_ON(AR_SREV_9280_20_OR_LATER(ah));
|
||||
|
||||
ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows);
|
||||
ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows);
|
||||
|
@ -484,7 +484,7 @@ static void ar5008_hw_rf_free_ext_banks(struct ath_hw *ah)
|
|||
bank = NULL; \
|
||||
} while (0);
|
||||
|
||||
BUG_ON(AR_SREV_9280_10_OR_LATER(ah));
|
||||
BUG_ON(AR_SREV_9280_20_OR_LATER(ah));
|
||||
|
||||
ATH_FREE_BANK(ah->analogBank0Data);
|
||||
ATH_FREE_BANK(ah->analogBank1Data);
|
||||
|
@ -525,7 +525,7 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah,
|
|||
* for single chip devices, that is AR9280 or anything
|
||||
* after that.
|
||||
*/
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
return true;
|
||||
|
||||
/* Setup rf parameters */
|
||||
|
@ -663,20 +663,20 @@ static void ar5008_hw_override_ini(struct ath_hw *ah,
|
|||
*/
|
||||
REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
val = REG_READ(ah, AR_PCU_MISC_MODE2);
|
||||
|
||||
if (!AR_SREV_9271(ah))
|
||||
val &= ~AR_PCU_MISC_MODE2_HWWAR1;
|
||||
|
||||
if (AR_SREV_9287_10_OR_LATER(ah))
|
||||
if (AR_SREV_9287_11_OR_LATER(ah))
|
||||
val = val & (~AR_PCU_MISC_MODE2_HWWAR2);
|
||||
|
||||
REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
|
||||
}
|
||||
|
||||
if (!AR_SREV_5416_20_OR_LATER(ah) ||
|
||||
AR_SREV_9280_10_OR_LATER(ah))
|
||||
AR_SREV_9280_20_OR_LATER(ah))
|
||||
return;
|
||||
/*
|
||||
* Disable BB clock gating
|
||||
|
@ -701,7 +701,7 @@ static void ar5008_hw_set_channel_regs(struct ath_hw *ah,
|
|||
u32 phymode;
|
||||
u32 enableDacFifo = 0;
|
||||
|
||||
if (AR_SREV_9285_10_OR_LATER(ah))
|
||||
if (AR_SREV_9285_12_OR_LATER(ah))
|
||||
enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) &
|
||||
AR_PHY_FC_ENABLE_DAC_FIFO);
|
||||
|
||||
|
@ -820,11 +820,11 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
|
|||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
DISABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
if (AR_SREV_9280(ah) || AR_SREV_9287_10_OR_LATER(ah))
|
||||
if (AR_SREV_9280(ah) || AR_SREV_9287_11_OR_LATER(ah))
|
||||
REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites);
|
||||
|
||||
if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) ||
|
||||
AR_SREV_9287_10_OR_LATER(ah))
|
||||
AR_SREV_9287_11_OR_LATER(ah))
|
||||
REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
|
||||
|
||||
if (AR_SREV_9271_10(ah))
|
||||
|
@ -900,7 +900,7 @@ static void ar5008_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan)
|
|||
rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
|
||||
? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
|
||||
|
||||
if (!AR_SREV_9280_10_OR_LATER(ah))
|
||||
if (!AR_SREV_9280_20_OR_LATER(ah))
|
||||
rfMode |= (IS_CHAN_5GHZ(chan)) ?
|
||||
AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
|
||||
|
||||
|
|
|
@ -567,11 +567,6 @@ static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
|
|||
AR5416_EEP_TXGAIN_HIGH_POWER)
|
||||
return;
|
||||
|
||||
if (AR_SREV_9285_11(ah)) {
|
||||
REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(regList); i++)
|
||||
regList[i][1] = REG_READ(ah, regList[i][0]);
|
||||
|
||||
|
@ -651,10 +646,6 @@ static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
|
|||
REG_WRITE(ah, regList[i][0], regList[i][1]);
|
||||
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
|
||||
|
||||
if (AR_SREV_9285_11(ah))
|
||||
REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
|
||||
|
||||
}
|
||||
|
||||
static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset)
|
||||
|
@ -664,7 +655,7 @@ static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset)
|
|||
ar9271_hw_pa_cal(ah, is_reset);
|
||||
else
|
||||
ah->pacal_info.skipcount--;
|
||||
} else if (AR_SREV_9285_11_OR_LATER(ah)) {
|
||||
} else if (AR_SREV_9285_12_OR_LATER(ah)) {
|
||||
if (is_reset || !ah->pacal_info.skipcount)
|
||||
ar9285_hw_pa_cal(ah, is_reset);
|
||||
else
|
||||
|
@ -841,8 +832,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
|
|||
if (!ar9285_hw_clc(ah, chan))
|
||||
return false;
|
||||
} else {
|
||||
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
if (!AR_SREV_9287_10_OR_LATER(ah))
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
if (!AR_SREV_9287_11_OR_LATER(ah))
|
||||
REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
|
||||
AR_PHY_ADC_CTL_OFF_PWDADC);
|
||||
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
|
||||
|
@ -864,8 +855,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
if (!AR_SREV_9287_10_OR_LATER(ah))
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
if (!AR_SREV_9287_11_OR_LATER(ah))
|
||||
REG_SET_BIT(ah, AR_PHY_ADC_CTL,
|
||||
AR_PHY_ADC_CTL_OFF_PWDADC);
|
||||
REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
|
||||
|
@ -976,7 +967,7 @@ static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
|
|||
}
|
||||
|
||||
if (AR_SREV_9160_10_OR_LATER(ah)) {
|
||||
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
ah->iq_caldata.calData = &iq_cal_single_sample;
|
||||
ah->adcgain_caldata.calData =
|
||||
&adc_gain_cal_single_sample;
|
||||
|
|
|
@ -569,7 +569,7 @@ void ar9002_hw_attach_ops(struct ath_hw *ah)
|
|||
ops->config_pci_powersave = ar9002_hw_configpcipowersave;
|
||||
|
||||
ar5008_hw_attach_phy_ops(ah);
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
ar9002_hw_attach_phy_ops(ah);
|
||||
|
||||
ar9002_hw_attach_calib_ops(ah);
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK)
|
||||
#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
|
||||
ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
|
||||
#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_10_OR_LATER(ah) && \
|
||||
#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \
|
||||
ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
|
||||
|
||||
#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c
|
||||
|
|
|
@ -333,7 +333,7 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah,
|
|||
}
|
||||
|
||||
if (i == 0) {
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
ss = (int16_t)(0 - (minPwrT4[i] / 2));
|
||||
else
|
||||
ss = 0;
|
||||
|
@ -761,7 +761,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
|
|||
|
||||
regulatory->max_power_level = ratesArray[i];
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
for (i = 0; i < Ar5416RateSize; i++)
|
||||
ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
|
||||
}
|
||||
|
@ -909,9 +909,6 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
|
|||
AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
|
||||
REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
|
||||
AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
|
||||
|
||||
if (AR_SREV_9285_11(ah))
|
||||
REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1109,9 +1106,6 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
|
|||
}
|
||||
|
||||
|
||||
if (AR_SREV_9285_11(ah))
|
||||
REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
|
||||
pModal->switchSettling);
|
||||
REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
|
||||
|
|
|
@ -324,7 +324,7 @@ static void ath9k_hw_get_ar9287_gain_boundaries_pdadcs(struct ath_hw *ah,
|
|||
minDelta = 0;
|
||||
|
||||
if (i == 0) {
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
ss = (int16_t)(0 - (minPwrT4[i] / 2));
|
||||
else
|
||||
ss = 0;
|
||||
|
@ -883,7 +883,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
|
|||
ratesArray[i] = AR9287_MAX_RATE_POWER;
|
||||
}
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
for (i = 0; i < Ar5416RateSize; i++)
|
||||
ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
|
||||
}
|
||||
|
@ -977,7 +977,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
|
|||
else
|
||||
i = rate6mb;
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
regulatory->max_power_level =
|
||||
ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
|
||||
else
|
||||
|
|
|
@ -223,7 +223,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
|
|||
}
|
||||
|
||||
/* Enable fixup for AR_AN_TOP2 if necessary */
|
||||
if (AR_SREV_9280_10_OR_LATER(ah) &&
|
||||
if (AR_SREV_9280_20_OR_LATER(ah) &&
|
||||
(eep->baseEepHeader.version & 0xff) > 0x0a &&
|
||||
eep->baseEepHeader.pwdclkind == 0)
|
||||
ah->need_an_top2_fixup = 1;
|
||||
|
@ -317,7 +317,7 @@ static void ath9k_hw_def_set_gain(struct ath_hw *ah,
|
|||
if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
|
||||
txRxAttenLocal = pModal->txRxAttenCh[i];
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
|
||||
AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
|
||||
pModal->bswMargin[i]);
|
||||
|
@ -344,7 +344,7 @@ static void ath9k_hw_def_set_gain(struct ath_hw *ah,
|
|||
}
|
||||
}
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
REG_RMW_FIELD(ah,
|
||||
AR_PHY_RXGAIN + regChainOffset,
|
||||
AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
|
||||
|
@ -408,7 +408,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
|
|||
regChainOffset, i);
|
||||
}
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
if (IS_CHAN_2GHZ(chan)) {
|
||||
ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
|
||||
AR_AN_RF2G1_CH0_OB,
|
||||
|
@ -461,7 +461,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
|
|||
REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
|
||||
pModal->adcDesiredSize);
|
||||
|
||||
if (!AR_SREV_9280_10_OR_LATER(ah))
|
||||
if (!AR_SREV_9280_20_OR_LATER(ah))
|
||||
REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
|
||||
AR_PHY_DESIRED_SZ_PGA,
|
||||
pModal->pgaDesiredSize);
|
||||
|
@ -478,7 +478,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
|
|||
REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
|
||||
pModal->txEndToRxOn);
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
|
||||
pModal->thresh62);
|
||||
REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
|
||||
|
@ -696,7 +696,7 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
|
|||
}
|
||||
|
||||
if (i == 0) {
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
ss = (int16_t)(0 - (minPwrT4[i] / 2));
|
||||
else
|
||||
ss = 0;
|
||||
|
@ -1291,7 +1291,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
|
|||
ratesArray[i] = AR5416_MAX_RATE_POWER;
|
||||
}
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
for (i = 0; i < Ar5416RateSize; i++) {
|
||||
int8_t pwr_table_offset;
|
||||
|
||||
|
@ -1395,7 +1395,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
|
|||
else if (IS_CHAN_HT20(chan))
|
||||
i = rateHt20_0;
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
regulatory->max_power_level =
|
||||
ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2;
|
||||
else
|
||||
|
|
|
@ -235,7 +235,14 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv)
|
|||
ath9k_hw_get_txq_props(ah, qnum, &qi_be);
|
||||
|
||||
qi.tqi_aifs = qi_be.tqi_aifs;
|
||||
qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
|
||||
/* For WIFI Beacon Distribution
|
||||
* Long slot time : 2x cwmin
|
||||
* Short slot time : 4x cwmin
|
||||
*/
|
||||
if (ah->slottime == ATH9K_SLOT_TIME_20)
|
||||
qi.tqi_cwmin = 2*qi_be.tqi_cwmin;
|
||||
else
|
||||
qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
|
||||
qi.tqi_cwmax = qi_be.tqi_cwmax;
|
||||
|
||||
if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) {
|
||||
|
|
|
@ -561,6 +561,9 @@ static void ath9k_init_crypto(struct ath9k_htc_priv *priv)
|
|||
common->keymax = ATH_KEYMAX;
|
||||
}
|
||||
|
||||
if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
|
||||
common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
|
||||
|
||||
/*
|
||||
* Reset the key cache since some parts do not
|
||||
* reset the contents on initial power up.
|
||||
|
|
|
@ -565,7 +565,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
|
|||
ath9k_hw_init_cal_settings(ah);
|
||||
|
||||
ah->ani_function = ATH9K_ANI_ALL;
|
||||
if (AR_SREV_9280_10_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah))
|
||||
if (AR_SREV_9280_20_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah))
|
||||
ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
|
||||
if (!AR_SREV_9300_20_OR_LATER(ah))
|
||||
ah->ani_function &= ~ATH9K_ANI_MRC_CCK;
|
||||
|
@ -1190,7 +1190,7 @@ bool ath9k_hw_check_alive(struct ath_hw *ah)
|
|||
int count = 50;
|
||||
u32 reg;
|
||||
|
||||
if (AR_SREV_9285_10_OR_LATER(ah))
|
||||
if (AR_SREV_9285_12_OR_LATER(ah))
|
||||
return true;
|
||||
|
||||
do {
|
||||
|
@ -1312,7 +1312,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|||
if (tsf)
|
||||
ath9k_hw_settsf64(ah, tsf);
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
|
||||
|
||||
if (!AR_SREV_9300_20_OR_LATER(ah))
|
||||
|
@ -1787,7 +1787,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
|||
regulatory->current_rd = eeval;
|
||||
|
||||
eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1);
|
||||
if (AR_SREV_9285_10_OR_LATER(ah))
|
||||
if (AR_SREV_9285_12_OR_LATER(ah))
|
||||
eeval |= AR9285_RDEXT_DEFAULT;
|
||||
regulatory->current_rd_ext = eeval;
|
||||
|
||||
|
@ -1857,8 +1857,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
|||
/* Use rx_chainmask from EEPROM. */
|
||||
pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
|
||||
|
||||
if (!(AR_SREV_9280(ah) && (ah->hw_version.macRev == 0)))
|
||||
ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
|
||||
ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
|
||||
|
||||
pCap->low_2ghz_chan = 2312;
|
||||
pCap->high_2ghz_chan = 2732;
|
||||
|
@ -1894,9 +1893,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
|||
pCap->num_gpio_pins = AR9271_NUM_GPIO;
|
||||
else if (AR_DEVID_7010(ah))
|
||||
pCap->num_gpio_pins = AR7010_NUM_GPIO;
|
||||
else if (AR_SREV_9285_10_OR_LATER(ah))
|
||||
else if (AR_SREV_9285_12_OR_LATER(ah))
|
||||
pCap->num_gpio_pins = AR9285_NUM_GPIO;
|
||||
else if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
else if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
pCap->num_gpio_pins = AR928X_NUM_GPIO;
|
||||
else
|
||||
pCap->num_gpio_pins = AR_NUM_GPIO;
|
||||
|
@ -1953,7 +1952,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
|||
pCap->num_antcfg_2ghz =
|
||||
ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ);
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah) &&
|
||||
if (AR_SREV_9280_20_OR_LATER(ah) &&
|
||||
ath9k_hw_btcoex_supported(ah)) {
|
||||
btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO;
|
||||
btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO;
|
||||
|
@ -1990,7 +1989,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
|||
if (AR_SREV_9300_20_OR_LATER(ah))
|
||||
pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED;
|
||||
|
||||
if (AR_SREV_9287_10_OR_LATER(ah) || AR_SREV_9271(ah))
|
||||
if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah))
|
||||
pCap->hw_caps |= ATH9K_HW_CAP_SGI_20;
|
||||
|
||||
if (AR_SREV_9285(ah))
|
||||
|
@ -2074,11 +2073,11 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
|
|||
return MS_REG_READ(AR9300, gpio) != 0;
|
||||
else if (AR_SREV_9271(ah))
|
||||
return MS_REG_READ(AR9271, gpio) != 0;
|
||||
else if (AR_SREV_9287_10_OR_LATER(ah))
|
||||
else if (AR_SREV_9287_11_OR_LATER(ah))
|
||||
return MS_REG_READ(AR9287, gpio) != 0;
|
||||
else if (AR_SREV_9285_10_OR_LATER(ah))
|
||||
else if (AR_SREV_9285_12_OR_LATER(ah))
|
||||
return MS_REG_READ(AR9285, gpio) != 0;
|
||||
else if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
else if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
return MS_REG_READ(AR928X, gpio) != 0;
|
||||
else
|
||||
return MS_REG_READ(AR, gpio) != 0;
|
||||
|
@ -2575,7 +2574,7 @@ void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len)
|
|||
int used;
|
||||
|
||||
/* chipsets >= AR9280 are single-chip */
|
||||
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
used = snprintf(hw_name, len,
|
||||
"Atheros AR%s Rev:%x",
|
||||
ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
|
||||
|
|
|
@ -211,7 +211,7 @@ static void setup_ht_cap(struct ath_softc *sc,
|
|||
else
|
||||
max_streams = 2;
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
if (max_streams >= 2)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
|
||||
ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
|
||||
|
|
|
@ -270,6 +270,7 @@ static void ath_paprd_activate(struct ath_softc *sc)
|
|||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath9k_hw_cal_data *caldata = ah->caldata;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int chain;
|
||||
|
||||
if (!caldata || !caldata->paprd_done)
|
||||
|
@ -278,7 +279,7 @@ static void ath_paprd_activate(struct ath_softc *sc)
|
|||
ath9k_ps_wakeup(sc);
|
||||
ar9003_paprd_enable(ah, false);
|
||||
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
|
||||
if (!(ah->caps.tx_chainmask & BIT(chain)))
|
||||
if (!(common->tx_chainmask & BIT(chain)))
|
||||
continue;
|
||||
|
||||
ar9003_paprd_populate_single_table(ah, caldata, chain);
|
||||
|
@ -300,6 +301,7 @@ void ath_paprd_calibrate(struct work_struct *work)
|
|||
struct ieee80211_supported_band *sband = &sc->sbands[band];
|
||||
struct ath_tx_control txctl;
|
||||
struct ath9k_hw_cal_data *caldata = ah->caldata;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int qnum, ftype;
|
||||
int chain_ok = 0;
|
||||
int chain;
|
||||
|
@ -333,7 +335,7 @@ void ath_paprd_calibrate(struct work_struct *work)
|
|||
ath9k_ps_wakeup(sc);
|
||||
ar9003_paprd_init_table(ah);
|
||||
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
|
||||
if (!(ah->caps.tx_chainmask & BIT(chain)))
|
||||
if (!(common->tx_chainmask & BIT(chain)))
|
||||
continue;
|
||||
|
||||
chain_ok = 0;
|
||||
|
|
|
@ -454,8 +454,8 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
|
|||
else
|
||||
rfilt |= ATH9K_RX_FILTER_BEACON;
|
||||
|
||||
if ((AR_SREV_9280_10_OR_LATER(sc->sc_ah) ||
|
||||
AR_SREV_9285_10_OR_LATER(sc->sc_ah)) &&
|
||||
if ((AR_SREV_9280_20_OR_LATER(sc->sc_ah) ||
|
||||
AR_SREV_9285_12_OR_LATER(sc->sc_ah)) &&
|
||||
(sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
|
||||
(sc->rx.rxfilter & FIF_PSPOLL))
|
||||
rfilt |= ATH9K_RX_FILTER_PSPOLL;
|
||||
|
@ -977,7 +977,11 @@ static void ath9k_process_rssi(struct ath_common *common,
|
|||
* at least one sdata of a wiphy on mac80211 but with ath9k virtual
|
||||
* wiphy you'd have to iterate over every wiphy and each sdata.
|
||||
*/
|
||||
sta = ieee80211_find_sta_by_hw(hw, hdr->addr2);
|
||||
if (is_multicast_ether_addr(hdr->addr1))
|
||||
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
|
||||
else
|
||||
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, hdr->addr1);
|
||||
|
||||
if (sta) {
|
||||
an = (struct ath_node *) sta->drv_priv;
|
||||
if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
|
||||
|
|
|
@ -819,49 +819,23 @@
|
|||
((_ah)->hw_version.macRev == AR_SREV_REVISION_9160_11))
|
||||
#define AR_SREV_9280(_ah) \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280))
|
||||
#define AR_SREV_9280_10_OR_LATER(_ah) \
|
||||
#define AR_SREV_9280_20_OR_LATER(_ah) \
|
||||
(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9280))
|
||||
#define AR_SREV_9280_20(_ah) \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \
|
||||
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20))
|
||||
#define AR_SREV_9280_20_OR_LATER(_ah) \
|
||||
(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9280) || \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \
|
||||
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20)))
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280))
|
||||
|
||||
#define AR_SREV_9285(_ah) \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9285))
|
||||
#define AR_SREV_9285_10_OR_LATER(_ah) \
|
||||
(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285))
|
||||
#define AR_SREV_9285_11(_ah) \
|
||||
(AR_SREV_9285(ah) && \
|
||||
((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_11))
|
||||
#define AR_SREV_9285_11_OR_LATER(_ah) \
|
||||
(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \
|
||||
(AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \
|
||||
AR_SREV_REVISION_9285_11)))
|
||||
#define AR_SREV_9285_12(_ah) \
|
||||
(AR_SREV_9285(ah) && \
|
||||
((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_12))
|
||||
#define AR_SREV_9285_12_OR_LATER(_ah) \
|
||||
(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \
|
||||
(AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \
|
||||
AR_SREV_REVISION_9285_12)))
|
||||
(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285))
|
||||
|
||||
#define AR_SREV_9287(_ah) \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287))
|
||||
#define AR_SREV_9287_10_OR_LATER(_ah) \
|
||||
#define AR_SREV_9287_11_OR_LATER(_ah) \
|
||||
(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9287))
|
||||
#define AR_SREV_9287_10(_ah) \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
|
||||
((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_10))
|
||||
#define AR_SREV_9287_11(_ah) \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
|
||||
((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_11))
|
||||
#define AR_SREV_9287_11_OR_LATER(_ah) \
|
||||
(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
|
||||
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_11)))
|
||||
#define AR_SREV_9287_12(_ah) \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
|
||||
((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_12))
|
||||
|
|
|
@ -328,8 +328,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
|||
|
||||
rcu_read_lock();
|
||||
|
||||
/* XXX: use ieee80211_find_sta! */
|
||||
sta = ieee80211_find_sta_by_hw(hw, hdr->addr1);
|
||||
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
|
||||
if (!sta) {
|
||||
rcu_read_unlock();
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ config CARL9170
|
|||
but it needs a special firmware (carl9170-1.fw) to do that.
|
||||
|
||||
The firmware can be downloaded from our wiki here:
|
||||
http://wireless.kernel.org/en/users/Drivers/carl9170
|
||||
<http://wireless.kernel.org/en/users/Drivers/carl9170>
|
||||
|
||||
If you choose to build a module, it'll be called carl9170.
|
||||
|
||||
|
|
|
@ -364,7 +364,6 @@ struct ar9170 {
|
|||
unsigned int tx_dropped;
|
||||
unsigned int tx_ack_failures;
|
||||
unsigned int tx_fcs_errors;
|
||||
unsigned int tx_ampdu_timeout;
|
||||
unsigned int rx_dropped;
|
||||
|
||||
/* EEPROM */
|
||||
|
|
|
@ -798,8 +798,6 @@ DEBUGFS_READONLY_FILE(tx_total_queued, 20, "%d",
|
|||
atomic_read(&ar->tx_total_queued));
|
||||
DEBUGFS_READONLY_FILE(tx_ampdu_scheduler, 20, "%d",
|
||||
atomic_read(&ar->tx_ampdu_scheduler));
|
||||
DEBUGFS_READONLY_FILE(tx_ampdu_timeout, 20, "%d",
|
||||
ar->tx_ampdu_timeout);
|
||||
|
||||
DEBUGFS_READONLY_FILE(tx_total_pending, 20, "%d",
|
||||
atomic_read(&ar->tx_total_pending));
|
||||
|
@ -872,8 +870,6 @@ void carl9170_debugfs_register(struct ar9170 *ar)
|
|||
DEBUGFS_ADD(ampdu_density);
|
||||
DEBUGFS_ADD(ampdu_factor);
|
||||
|
||||
DEBUGFS_ADD(tx_ampdu_timeout);
|
||||
|
||||
DEBUGFS_ADD(tx_janitor_last_run);
|
||||
|
||||
DEBUGFS_ADD(tx_status_0);
|
||||
|
|
|
@ -230,8 +230,15 @@ static void carl9170_flush(struct ar9170 *ar, bool drop_queued)
|
|||
for (i = 0; i < ar->hw->queues; i++) {
|
||||
struct sk_buff *skb;
|
||||
|
||||
while ((skb = skb_dequeue(&ar->tx_pending[i])))
|
||||
while ((skb = skb_dequeue(&ar->tx_pending[i]))) {
|
||||
struct ieee80211_tx_info *info;
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||
atomic_dec(&ar->tx_ampdu_upload);
|
||||
|
||||
carl9170_tx_status(ar, skb, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1241,7 +1248,7 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw,
|
|||
|
||||
switch (action) {
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
if (WARN_ON_ONCE(!sta_info->ht_sta))
|
||||
if (!sta_info->ht_sta)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rcu_read_lock();
|
||||
|
@ -1453,9 +1460,6 @@ static void carl9170_op_sta_notify(struct ieee80211_hw *hw,
|
|||
while ((skb = __skb_dequeue(&tid_info->queue)))
|
||||
__skb_queue_tail(&free, skb);
|
||||
spin_unlock_bh(&tid_info->lock);
|
||||
|
||||
ieee80211_stop_tx_ba_session(sta,
|
||||
tid_info->tid);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
@ -1465,6 +1469,7 @@ static void carl9170_op_sta_notify(struct ieee80211_hw *hw,
|
|||
skb_queue_walk_safe(&ar->tx_pending[i], skb, tmp) {
|
||||
struct _carl9170_tx_superframe *super;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_tx_info *info;
|
||||
|
||||
super = (void *) skb->data;
|
||||
hdr = (void *) super->frame_data;
|
||||
|
@ -1473,6 +1478,11 @@ static void carl9170_op_sta_notify(struct ieee80211_hw *hw,
|
|||
continue;
|
||||
|
||||
__skb_unlink(skb, &ar->tx_pending[i]);
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||
atomic_dec(&ar->tx_ampdu_upload);
|
||||
|
||||
carl9170_tx_status(ar, skb, false);
|
||||
}
|
||||
spin_unlock_bh(&ar->tx_pending[i].lock);
|
||||
|
|
|
@ -760,8 +760,8 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
|
|||
struct carl9170_tx_info *arinfo;
|
||||
unsigned int hw_queue;
|
||||
int i;
|
||||
u16 keytype = 0;
|
||||
u16 len, icv = 0;
|
||||
__le16 mac_tmp;
|
||||
u16 len;
|
||||
bool ampdu, no_ack;
|
||||
|
||||
BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data));
|
||||
|
@ -773,6 +773,10 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
|
|||
|
||||
BUILD_BUG_ON(IEEE80211_TX_MAX_RATES < CARL9170_TX_MAX_RATES);
|
||||
|
||||
BUILD_BUG_ON(AR9170_MAX_VIRTUAL_MAC >
|
||||
((CARL9170_TX_SUPER_MISC_VIF_ID >>
|
||||
CARL9170_TX_SUPER_MISC_VIF_ID_S) + 1));
|
||||
|
||||
hw_queue = ar9170_qmap[carl9170_get_queue(ar, skb)];
|
||||
|
||||
hdr = (void *)skb->data;
|
||||
|
@ -793,20 +797,37 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
|
|||
txc = (void *)skb_push(skb, sizeof(*txc));
|
||||
memset(txc, 0, sizeof(*txc));
|
||||
|
||||
ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU);
|
||||
SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, txc->s.misc, hw_queue);
|
||||
|
||||
if (likely(cvif))
|
||||
SET_VAL(CARL9170_TX_SUPER_MISC_VIF_ID, txc->s.misc, cvif->id);
|
||||
|
||||
if (unlikely(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM))
|
||||
txc->s.misc |= CARL9170_TX_SUPER_MISC_CAB;
|
||||
|
||||
if (unlikely(ieee80211_is_probe_resp(hdr->frame_control)))
|
||||
txc->s.misc |= CARL9170_TX_SUPER_MISC_FILL_IN_TSF;
|
||||
|
||||
mac_tmp = cpu_to_le16(AR9170_TX_MAC_HW_DURATION |
|
||||
AR9170_TX_MAC_BACKOFF);
|
||||
mac_tmp |= cpu_to_le16((hw_queue << AR9170_TX_MAC_QOS_S) &&
|
||||
AR9170_TX_MAC_QOS);
|
||||
|
||||
no_ack = !!(info->flags & IEEE80211_TX_CTL_NO_ACK);
|
||||
if (unlikely(no_ack))
|
||||
mac_tmp |= cpu_to_le16(AR9170_TX_MAC_NO_ACK);
|
||||
|
||||
if (info->control.hw_key) {
|
||||
icv = info->control.hw_key->icv_len;
|
||||
len += info->control.hw_key->icv_len;
|
||||
|
||||
switch (info->control.hw_key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
keytype = AR9170_TX_MAC_ENCR_RC4;
|
||||
mac_tmp |= cpu_to_le16(AR9170_TX_MAC_ENCR_RC4);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
keytype = AR9170_TX_MAC_ENCR_AES;
|
||||
mac_tmp |= cpu_to_le16(AR9170_TX_MAC_ENCR_AES);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
|
@ -814,48 +835,58 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
|
|||
}
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(AR9170_MAX_VIRTUAL_MAC >
|
||||
((CARL9170_TX_SUPER_MISC_VIF_ID >>
|
||||
CARL9170_TX_SUPER_MISC_VIF_ID_S) + 1));
|
||||
ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU);
|
||||
if (ampdu) {
|
||||
unsigned int density, factor;
|
||||
|
||||
txc->s.len = cpu_to_le16(len + sizeof(*txc));
|
||||
txc->f.length = cpu_to_le16(len + icv + 4);
|
||||
SET_VAL(CARL9170_TX_SUPER_MISC_VIF_ID, txc->s.misc,
|
||||
cvif ? cvif->id : 0);
|
||||
if (unlikely(!sta || !cvif))
|
||||
goto err_out;
|
||||
|
||||
txc->f.mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION |
|
||||
AR9170_TX_MAC_BACKOFF);
|
||||
factor = min_t(unsigned int, 1u,
|
||||
info->control.sta->ht_cap.ampdu_factor);
|
||||
|
||||
SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, txc->s.misc, hw_queue);
|
||||
density = info->control.sta->ht_cap.ampdu_density;
|
||||
|
||||
txc->f.mac_control |= cpu_to_le16(hw_queue << AR9170_TX_MAC_QOS_S);
|
||||
txc->f.mac_control |= cpu_to_le16(keytype);
|
||||
txc->f.phy_control = cpu_to_le32(0);
|
||||
if (density) {
|
||||
/*
|
||||
* Watch out!
|
||||
*
|
||||
* Otus uses slightly different density values than
|
||||
* those from the 802.11n spec.
|
||||
*/
|
||||
|
||||
if (no_ack)
|
||||
txc->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK);
|
||||
density = max_t(unsigned int, density + 1, 7u);
|
||||
}
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM)
|
||||
txc->s.misc |= CARL9170_TX_SUPER_MISC_CAB;
|
||||
SET_VAL(CARL9170_TX_SUPER_AMPDU_DENSITY,
|
||||
txc->s.ampdu_settings, density);
|
||||
|
||||
txrate = &info->control.rates[0];
|
||||
if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack))
|
||||
txc->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS);
|
||||
else if (carl9170_tx_cts_check(ar, txrate))
|
||||
txc->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS);
|
||||
SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR,
|
||||
txc->s.ampdu_settings, factor);
|
||||
|
||||
SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count);
|
||||
txc->f.phy_control |= carl9170_tx_physet(ar, info, txrate);
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
|
||||
for (i = 1; i < CARL9170_TX_MAX_RATES; i++) {
|
||||
for (i = 0; i < CARL9170_TX_MAX_RATES; i++) {
|
||||
txrate = &info->control.rates[i];
|
||||
if (txrate->idx >= 0)
|
||||
if (txrate->idx >= 0) {
|
||||
txc->s.ri[i] =
|
||||
CARL9170_TX_SUPER_RI_AMPDU;
|
||||
|
||||
if (WARN_ON(!(txrate->flags &
|
||||
IEEE80211_TX_RC_MCS))) {
|
||||
/*
|
||||
* Not sure if it's even possible
|
||||
* to aggregate non-ht rates with
|
||||
* this HW.
|
||||
*/
|
||||
goto err_out;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
txrate->idx = 0;
|
||||
txrate->count = ar->hw->max_rate_tries;
|
||||
}
|
||||
|
||||
mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -878,57 +909,21 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
|
|||
txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS <<
|
||||
CARL9170_TX_SUPER_RI_ERP_PROT_S);
|
||||
|
||||
/*
|
||||
* unaggregated fallback, in case aggregation
|
||||
* proves to be unsuccessful and unreliable.
|
||||
*/
|
||||
if (ampdu && i < 3)
|
||||
txc->s.ri[i] |= CARL9170_TX_SUPER_RI_AMPDU;
|
||||
|
||||
txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate);
|
||||
}
|
||||
|
||||
if (ieee80211_is_probe_resp(hdr->frame_control))
|
||||
txc->s.misc |= CARL9170_TX_SUPER_MISC_FILL_IN_TSF;
|
||||
txrate = &info->control.rates[0];
|
||||
SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count);
|
||||
|
||||
if (ampdu) {
|
||||
unsigned int density, factor;
|
||||
if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack))
|
||||
mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS);
|
||||
else if (carl9170_tx_cts_check(ar, txrate))
|
||||
mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS);
|
||||
|
||||
if (unlikely(!sta || !cvif))
|
||||
goto err_out;
|
||||
|
||||
density = info->control.sta->ht_cap.ampdu_density;
|
||||
factor = info->control.sta->ht_cap.ampdu_factor;
|
||||
|
||||
if (density) {
|
||||
/*
|
||||
* Watch out!
|
||||
*
|
||||
* Otus uses slightly different density values than
|
||||
* those from the 802.11n spec.
|
||||
*/
|
||||
|
||||
density = max_t(unsigned int, density + 1, 7u);
|
||||
}
|
||||
|
||||
factor = min_t(unsigned int, 1u, factor);
|
||||
|
||||
SET_VAL(CARL9170_TX_SUPER_AMPDU_DENSITY,
|
||||
txc->s.ampdu_settings, density);
|
||||
|
||||
SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR,
|
||||
txc->s.ampdu_settings, factor);
|
||||
|
||||
if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS) {
|
||||
txc->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR);
|
||||
} else {
|
||||
/*
|
||||
* Not sure if it's even possible to aggregate
|
||||
* non-ht rates with this HW.
|
||||
*/
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
}
|
||||
txc->s.len = cpu_to_le16(skb->len);
|
||||
txc->f.length = cpu_to_le16(len + FCS_LEN);
|
||||
txc->f.mac_control = mac_tmp;
|
||||
txc->f.phy_control = carl9170_tx_physet(ar, info, txrate);
|
||||
|
||||
arinfo = (void *)info->rate_driver_data;
|
||||
arinfo->timeout = jiffies;
|
||||
|
@ -1042,41 +1037,8 @@ retry:
|
|||
queue = TID_TO_WME_AC(tid_info->tid);
|
||||
|
||||
spin_lock_bh(&tid_info->lock);
|
||||
if (tid_info->state != CARL9170_TID_STATE_XMIT) {
|
||||
first = skb_peek(&tid_info->queue);
|
||||
if (first) {
|
||||
struct ieee80211_tx_info *txinfo;
|
||||
struct carl9170_tx_info *arinfo;
|
||||
|
||||
txinfo = IEEE80211_SKB_CB(first);
|
||||
arinfo = (void *) txinfo->rate_driver_data;
|
||||
|
||||
if (time_is_after_jiffies(arinfo->timeout +
|
||||
msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT))
|
||||
== true)
|
||||
goto processed;
|
||||
|
||||
/*
|
||||
* We've been waiting for the frame which
|
||||
* matches "snx" (start sequence of the
|
||||
* next aggregate) for some time now.
|
||||
*
|
||||
* But it never arrived. Therefore
|
||||
* jump to the next available frame
|
||||
* and kick-start the transmission.
|
||||
*
|
||||
* Note: This might induce odd latency
|
||||
* spikes because the receiver will be
|
||||
* waiting for the lost frame too.
|
||||
*/
|
||||
ar->tx_ampdu_timeout++;
|
||||
|
||||
tid_info->snx = carl9170_get_seq(first);
|
||||
tid_info->state = CARL9170_TID_STATE_XMIT;
|
||||
} else {
|
||||
goto processed;
|
||||
}
|
||||
}
|
||||
if (tid_info->state != CARL9170_TID_STATE_XMIT)
|
||||
goto processed;
|
||||
|
||||
tid_info->counter++;
|
||||
first = skb_peek(&tid_info->queue);
|
||||
|
|
|
@ -606,8 +606,6 @@ int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd,
|
|||
AR9170_USB_EP_CMD), cmd, cmd->hdr.len + 4,
|
||||
carl9170_usb_cmd_complete, ar, 1);
|
||||
|
||||
urb->transfer_flags |= URB_ZERO_PACKET;
|
||||
|
||||
if (free_buf)
|
||||
urb->transfer_flags |= URB_FREE_BUFFER;
|
||||
|
||||
|
|
|
@ -16,3 +16,6 @@ wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o
|
|||
obj-$(CONFIG_WL1271) += wl1271.o
|
||||
obj-$(CONFIG_WL1271_SPI) += wl1271_spi.o
|
||||
obj-$(CONFIG_WL1271_SDIO) += wl1271_sdio.o
|
||||
|
||||
# small builtin driver bit
|
||||
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o
|
||||
|
|
|
@ -274,11 +274,11 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
|
|||
|
||||
/*
|
||||
* We've reached the first zero length, the first NVS table
|
||||
* is 7 bytes further.
|
||||
* is located at an aligned offset which is at least 7 bytes further.
|
||||
*/
|
||||
nvs_ptr += 7;
|
||||
nvs_ptr = (u8 *)wl->nvs->nvs +
|
||||
ALIGN(nvs_ptr - (u8 *)wl->nvs->nvs + 7, 4);
|
||||
nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs;
|
||||
nvs_len = ALIGN(nvs_len, 4);
|
||||
|
||||
/* FIXME: The driver sets the partition here, but this is not needed,
|
||||
since it sets to the same one as currently in use */
|
||||
|
@ -286,14 +286,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
|
|||
wl1271_set_partition(wl, &part_table[PART_WORK]);
|
||||
|
||||
/* Copy the NVS tables to a new block to ensure alignment */
|
||||
/* FIXME: We jump 3 more bytes before uploading the NVS. It seems
|
||||
that our NVS files have three extra zeros here. I'm not sure whether
|
||||
the problem is in our NVS generation or we should really jumpt these
|
||||
3 bytes here */
|
||||
nvs_ptr += 3;
|
||||
|
||||
nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); if
|
||||
(!nvs_aligned) return -ENOMEM;
|
||||
nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
|
||||
if (!nvs_aligned)
|
||||
return -ENOMEM;
|
||||
|
||||
/* And finally we upload the NVS tables */
|
||||
/* FIXME: In wl1271, we upload everything at once.
|
||||
|
|
|
@ -321,6 +321,9 @@ struct ieee80211_bss_conf {
|
|||
* @IEEE80211_TX_CTL_LDPC: tells the driver to use LDPC for this frame
|
||||
* @IEEE80211_TX_CTL_STBC: Enables Space-Time Block Coding (STBC) for this
|
||||
* frame and selects the maximum number of streams that it can use.
|
||||
*
|
||||
* Note: If you have to add new flags to the enumeration, then don't
|
||||
* forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary.
|
||||
*/
|
||||
enum mac80211_tx_control_flags {
|
||||
IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0),
|
||||
|
@ -350,6 +353,19 @@ enum mac80211_tx_control_flags {
|
|||
|
||||
#define IEEE80211_TX_CTL_STBC_SHIFT 23
|
||||
|
||||
/*
|
||||
* This definition is used as a mask to clear all temporary flags, which are
|
||||
* set by the tx handlers for each transmission attempt by the mac80211 stack.
|
||||
*/
|
||||
#define IEEE80211_TX_TEMPORARY_FLAGS (IEEE80211_TX_CTL_NO_ACK | \
|
||||
IEEE80211_TX_CTL_CLEAR_PS_FILT | IEEE80211_TX_CTL_FIRST_FRAGMENT | \
|
||||
IEEE80211_TX_CTL_SEND_AFTER_DTIM | IEEE80211_TX_CTL_AMPDU | \
|
||||
IEEE80211_TX_STAT_TX_FILTERED | IEEE80211_TX_STAT_ACK | \
|
||||
IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_STAT_AMPDU_NO_BACK | \
|
||||
IEEE80211_TX_CTL_RATE_CTRL_PROBE | IEEE80211_TX_CTL_PSPOLL_RESPONSE | \
|
||||
IEEE80211_TX_CTL_MORE_FRAMES | IEEE80211_TX_CTL_LDPC | \
|
||||
IEEE80211_TX_CTL_STBC)
|
||||
|
||||
/**
|
||||
* enum mac80211_rate_control_flags - per-rate flags set by the
|
||||
* Rate Control algorithm.
|
||||
|
@ -565,9 +581,6 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
|
|||
* @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
|
||||
* @RX_FLAG_40MHZ: HT40 (40 MHz) was used
|
||||
* @RX_FLAG_SHORT_GI: Short guard interval was used
|
||||
* @RX_FLAG_INTERNAL_CMTR: set internally after frame was reported
|
||||
* on cooked monitor to avoid double-reporting it for multiple
|
||||
* virtual interfaces
|
||||
*/
|
||||
enum mac80211_rx_flags {
|
||||
RX_FLAG_MMIC_ERROR = 1<<0,
|
||||
|
@ -581,7 +594,6 @@ enum mac80211_rx_flags {
|
|||
RX_FLAG_HT = 1<<9,
|
||||
RX_FLAG_40MHZ = 1<<10,
|
||||
RX_FLAG_SHORT_GI = 1<<11,
|
||||
RX_FLAG_INTERNAL_CMTR = 1<<12,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -602,6 +614,7 @@ enum mac80211_rx_flags {
|
|||
* @rate_idx: index of data rate into band's supported rates or MCS index if
|
||||
* HT rates are use (RX_FLAG_HT)
|
||||
* @flag: %RX_FLAG_*
|
||||
* @rx_flags: internal RX flags for mac80211
|
||||
*/
|
||||
struct ieee80211_rx_status {
|
||||
u64 mactime;
|
||||
|
@ -611,6 +624,7 @@ struct ieee80211_rx_status {
|
|||
int antenna;
|
||||
int rate_idx;
|
||||
int flag;
|
||||
unsigned int rx_flags;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2416,25 +2430,28 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
|
|||
const u8 *addr);
|
||||
|
||||
/**
|
||||
* ieee80211_find_sta_by_hw - find a station on hardware
|
||||
* ieee80211_find_sta_by_ifaddr - find a station on hardware
|
||||
*
|
||||
* @hw: pointer as obtained from ieee80211_alloc_hw()
|
||||
* @addr: station's address
|
||||
* @addr: remote station's address
|
||||
* @localaddr: local address (vif->sdata->vif.addr). Use NULL for 'any'.
|
||||
*
|
||||
* This function must be called under RCU lock and the
|
||||
* resulting pointer is only valid under RCU lock as well.
|
||||
*
|
||||
* NOTE: This function should not be used! When mac80211 is converted
|
||||
* internally to properly keep track of stations on multiple
|
||||
* virtual interfaces, it will not always know which station to
|
||||
* return here since a single address might be used by multiple
|
||||
* logical stations (e.g. consider a station connecting to another
|
||||
* BSSID on the same AP hardware without disconnecting first).
|
||||
* NOTE: You may pass NULL for localaddr, but then you will just get
|
||||
* the first STA that matches the remote address 'addr'.
|
||||
* We can have multiple STA associated with multiple
|
||||
* logical stations (e.g. consider a station connecting to another
|
||||
* BSSID on the same AP hardware without disconnecting first).
|
||||
* In this case, the result of this method with localaddr NULL
|
||||
* is not reliable.
|
||||
*
|
||||
* DO NOT USE THIS FUNCTION.
|
||||
* DO NOT USE THIS FUNCTION with localaddr NULL if at all possible.
|
||||
*/
|
||||
struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
|
||||
const u8 *addr);
|
||||
struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
|
||||
const u8 *addr,
|
||||
const u8 *localaddr);
|
||||
|
||||
/**
|
||||
* ieee80211_sta_block_awake - block station from waking up
|
||||
|
|
|
@ -368,7 +368,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
|
|||
if (!phyd)
|
||||
return;
|
||||
|
||||
local->debugfs.stations = debugfs_create_dir("stations", phyd);
|
||||
local->debugfs.keys = debugfs_create_dir("keys", phyd);
|
||||
|
||||
DEBUGFS_ADD(frequency);
|
||||
|
|
|
@ -409,6 +409,9 @@ void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
|
|||
sprintf(buf, "netdev:%s", sdata->name);
|
||||
sdata->debugfs.dir = debugfs_create_dir(buf,
|
||||
sdata->local->hw.wiphy->debugfsdir);
|
||||
if (sdata->debugfs.dir)
|
||||
sdata->debugfs.subdir_stations = debugfs_create_dir("stations",
|
||||
sdata->debugfs.dir);
|
||||
add_files(sdata);
|
||||
}
|
||||
|
||||
|
|
|
@ -300,7 +300,7 @@ STA_OPS(ht_capa);
|
|||
|
||||
void ieee80211_sta_debugfs_add(struct sta_info *sta)
|
||||
{
|
||||
struct dentry *stations_dir = sta->local->debugfs.stations;
|
||||
struct dentry *stations_dir = sta->sdata->debugfs.subdir_stations;
|
||||
u8 mac[3*ETH_ALEN];
|
||||
|
||||
sta->debugfs.add_has_run = true;
|
||||
|
|
|
@ -159,13 +159,37 @@ typedef unsigned __bitwise__ ieee80211_rx_result;
|
|||
#define RX_DROP_MONITOR ((__force ieee80211_rx_result) 2u)
|
||||
#define RX_QUEUED ((__force ieee80211_rx_result) 3u)
|
||||
|
||||
#define IEEE80211_RX_IN_SCAN BIT(0)
|
||||
/* frame is destined to interface currently processed (incl. multicast frames) */
|
||||
#define IEEE80211_RX_RA_MATCH BIT(1)
|
||||
#define IEEE80211_RX_AMSDU BIT(2)
|
||||
#define IEEE80211_RX_FRAGMENTED BIT(3)
|
||||
#define IEEE80211_MALFORMED_ACTION_FRM BIT(4)
|
||||
/* only add flags here that do not change with subframes of an aMPDU */
|
||||
/**
|
||||
* enum ieee80211_packet_rx_flags - packet RX flags
|
||||
* @IEEE80211_RX_RA_MATCH: frame is destined to interface currently processed
|
||||
* (incl. multicast frames)
|
||||
* @IEEE80211_RX_IN_SCAN: received while scanning
|
||||
* @IEEE80211_RX_FRAGMENTED: fragmented frame
|
||||
* @IEEE80211_RX_AMSDU: a-MSDU packet
|
||||
* @IEEE80211_RX_MALFORMED_ACTION_FRM: action frame is malformed
|
||||
*
|
||||
* These are per-frame flags that are attached to a frame in the
|
||||
* @rx_flags field of &struct ieee80211_rx_status.
|
||||
*/
|
||||
enum ieee80211_packet_rx_flags {
|
||||
IEEE80211_RX_IN_SCAN = BIT(0),
|
||||
IEEE80211_RX_RA_MATCH = BIT(1),
|
||||
IEEE80211_RX_FRAGMENTED = BIT(2),
|
||||
IEEE80211_RX_AMSDU = BIT(3),
|
||||
IEEE80211_RX_MALFORMED_ACTION_FRM = BIT(4),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ieee80211_rx_flags - RX data flags
|
||||
*
|
||||
* @IEEE80211_RX_CMNTR: received on cooked monitor already
|
||||
*
|
||||
* These flags are used across handling multiple interfaces
|
||||
* for a single frame.
|
||||
*/
|
||||
enum ieee80211_rx_flags {
|
||||
IEEE80211_RX_CMNTR = BIT(0),
|
||||
};
|
||||
|
||||
struct ieee80211_rx_data {
|
||||
struct sk_buff *skb;
|
||||
|
@ -564,6 +588,7 @@ struct ieee80211_sub_if_data {
|
|||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
struct {
|
||||
struct dentry *dir;
|
||||
struct dentry *subdir_stations;
|
||||
struct dentry *default_key;
|
||||
struct dentry *default_mgmt_key;
|
||||
} debugfs;
|
||||
|
@ -899,7 +924,6 @@ struct ieee80211_local {
|
|||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
struct local_debugfsdentries {
|
||||
struct dentry *rcdir;
|
||||
struct dentry *stations;
|
||||
struct dentry *keys;
|
||||
} debugfs;
|
||||
#endif
|
||||
|
@ -1256,7 +1280,8 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
|
|||
const u8 *key, u8 key_len, u8 key_idx);
|
||||
int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
|
||||
const u8 *ie, size_t ie_len,
|
||||
enum ieee80211_band band);
|
||||
enum ieee80211_band band, u32 rate_mask,
|
||||
u8 channel);
|
||||
void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
|
||||
const u8 *ssid, size_t ssid_len,
|
||||
const u8 *ie, size_t ie_len);
|
||||
|
|
|
@ -110,7 +110,8 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
|
|||
chan = scan_chan;
|
||||
channel_type = NL80211_CHAN_NO_HT;
|
||||
local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
|
||||
} else if (local->tmp_channel) {
|
||||
} else if (local->tmp_channel &&
|
||||
local->oper_channel != local->tmp_channel) {
|
||||
chan = scan_chan = local->tmp_channel;
|
||||
channel_type = local->tmp_channel_type;
|
||||
local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
|
||||
|
|
|
@ -880,14 +880,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
|
|||
sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL |
|
||||
IEEE80211_STA_BEACON_POLL);
|
||||
|
||||
/*
|
||||
* Always handle WMM once after association regardless
|
||||
* of the first value the AP uses. Setting -1 here has
|
||||
* that effect because the AP values is an unsigned
|
||||
* 4-bit value.
|
||||
*/
|
||||
sdata->u.mgd.wmm_last_param_set = -1;
|
||||
|
||||
ieee80211_led_assoc(local, 1);
|
||||
|
||||
if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD)
|
||||
|
@ -1367,6 +1359,14 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Always handle WMM once after association regardless
|
||||
* of the first value the AP uses. Setting -1 here has
|
||||
* that effect because the AP values is an unsigned
|
||||
* 4-bit value.
|
||||
*/
|
||||
ifmgd->wmm_last_param_set = -1;
|
||||
|
||||
if (elems.wmm_param)
|
||||
ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
|
||||
elems.wmm_param_len);
|
||||
|
|
|
@ -315,6 +315,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
|||
static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
||||
int tid;
|
||||
|
||||
/* does the frame have a qos control field? */
|
||||
|
@ -323,9 +324,7 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
|
|||
/* frame has qos control */
|
||||
tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
|
||||
if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
|
||||
rx->flags |= IEEE80211_RX_AMSDU;
|
||||
else
|
||||
rx->flags &= ~IEEE80211_RX_AMSDU;
|
||||
status->rx_flags |= IEEE80211_RX_AMSDU;
|
||||
} else {
|
||||
/*
|
||||
* IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"):
|
||||
|
@ -387,26 +386,25 @@ static ieee80211_rx_result debug_noinline
|
|||
ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
|
||||
{
|
||||
struct ieee80211_local *local = rx->local;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
||||
struct sk_buff *skb = rx->skb;
|
||||
|
||||
if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning)))
|
||||
if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN)))
|
||||
return RX_CONTINUE;
|
||||
|
||||
if (test_bit(SCAN_HW_SCANNING, &local->scanning))
|
||||
return ieee80211_scan_rx(rx->sdata, skb);
|
||||
|
||||
if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning) &&
|
||||
(rx->flags & IEEE80211_RX_IN_SCAN))) {
|
||||
if (test_bit(SCAN_SW_SCANNING, &local->scanning)) {
|
||||
/* drop all the other packets during a software scan anyway */
|
||||
if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED)
|
||||
dev_kfree_skb(skb);
|
||||
return RX_QUEUED;
|
||||
}
|
||||
|
||||
if (unlikely(rx->flags & IEEE80211_RX_IN_SCAN)) {
|
||||
/* scanning finished during invoking of handlers */
|
||||
I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
|
||||
return RX_DROP_UNUSABLE;
|
||||
}
|
||||
|
||||
return RX_CONTINUE;
|
||||
/* scanning finished during invoking of handlers */
|
||||
I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
|
||||
return RX_DROP_UNUSABLE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -785,13 +783,14 @@ static ieee80211_rx_result debug_noinline
|
|||
ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
||||
|
||||
/* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
|
||||
if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
|
||||
if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
|
||||
rx->sta->last_seq_ctrl[rx->queue] ==
|
||||
hdr->seq_ctrl)) {
|
||||
if (rx->flags & IEEE80211_RX_RA_MATCH) {
|
||||
if (status->rx_flags & IEEE80211_RX_RA_MATCH) {
|
||||
rx->local->dot11FrameDuplicateCount++;
|
||||
rx->sta->num_duplicates++;
|
||||
}
|
||||
|
@ -824,7 +823,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
|
|||
if ((!ieee80211_has_fromds(hdr->frame_control) &&
|
||||
!ieee80211_has_tods(hdr->frame_control) &&
|
||||
ieee80211_is_data(hdr->frame_control)) ||
|
||||
!(rx->flags & IEEE80211_RX_RA_MATCH)) {
|
||||
!(status->rx_flags & IEEE80211_RX_RA_MATCH)) {
|
||||
/* Drop IBSS frames and frames for other hosts
|
||||
* silently. */
|
||||
return RX_DROP_MONITOR;
|
||||
|
@ -881,7 +880,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
|||
* No point in finding a key and decrypting if the frame is neither
|
||||
* addressed to us nor a multicast frame.
|
||||
*/
|
||||
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
|
||||
if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
|
||||
return RX_CONTINUE;
|
||||
|
||||
/* start without a key */
|
||||
|
@ -1114,7 +1113,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
|||
sta->last_rx = jiffies;
|
||||
}
|
||||
|
||||
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
|
||||
if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
|
||||
return RX_CONTINUE;
|
||||
|
||||
if (rx->sdata->vif.type == NL80211_IFTYPE_STATION)
|
||||
|
@ -1271,6 +1270,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
|||
unsigned int frag, seq;
|
||||
struct ieee80211_fragment_entry *entry;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_rx_status *status;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)rx->skb->data;
|
||||
fc = hdr->frame_control;
|
||||
|
@ -1370,7 +1370,8 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
|||
}
|
||||
|
||||
/* Complete frame has been reassembled - process it now */
|
||||
rx->flags |= IEEE80211_RX_FRAGMENTED;
|
||||
status = IEEE80211_SKB_RXCB(rx->skb);
|
||||
status->rx_flags |= IEEE80211_RX_FRAGMENTED;
|
||||
|
||||
out:
|
||||
if (rx->sta)
|
||||
|
@ -1387,9 +1388,10 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
|
|||
{
|
||||
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
__le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
||||
|
||||
if (likely(!rx->sta || !ieee80211_is_pspoll(fc) ||
|
||||
!(rx->flags & IEEE80211_RX_RA_MATCH)))
|
||||
!(status->rx_flags & IEEE80211_RX_RA_MATCH)))
|
||||
return RX_CONTINUE;
|
||||
|
||||
if ((sdata->vif.type != NL80211_IFTYPE_AP) &&
|
||||
|
@ -1550,6 +1552,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
|
|||
struct sk_buff *skb, *xmit_skb;
|
||||
struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
|
||||
struct sta_info *dsta;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
||||
|
||||
skb = rx->skb;
|
||||
xmit_skb = NULL;
|
||||
|
@ -1557,7 +1560,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
|
|||
if ((sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
|
||||
!(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
|
||||
(rx->flags & IEEE80211_RX_RA_MATCH) &&
|
||||
(status->rx_flags & IEEE80211_RX_RA_MATCH) &&
|
||||
(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {
|
||||
if (is_multicast_ether_addr(ehdr->h_dest)) {
|
||||
/*
|
||||
|
@ -1634,6 +1637,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
|
|||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
__le16 fc = hdr->frame_control;
|
||||
struct sk_buff_head frame_list;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
||||
|
||||
if (unlikely(!ieee80211_is_data(fc)))
|
||||
return RX_CONTINUE;
|
||||
|
@ -1641,7 +1645,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
|
|||
if (unlikely(!ieee80211_is_data_present(fc)))
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
if (!(rx->flags & IEEE80211_RX_AMSDU))
|
||||
if (!(status->rx_flags & IEEE80211_RX_AMSDU))
|
||||
return RX_CONTINUE;
|
||||
|
||||
if (ieee80211_has_a4(hdr->frame_control) &&
|
||||
|
@ -1692,6 +1696,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
|||
struct sk_buff *skb = rx->skb, *fwd_skb;
|
||||
struct ieee80211_local *local = rx->local;
|
||||
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
|
@ -1737,7 +1742,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
|||
|
||||
mesh_hdr->ttl--;
|
||||
|
||||
if (rx->flags & IEEE80211_RX_RA_MATCH) {
|
||||
if (status->rx_flags & IEEE80211_RX_RA_MATCH) {
|
||||
if (!mesh_hdr->ttl)
|
||||
IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.mesh,
|
||||
dropped_frames_ttl);
|
||||
|
@ -1947,6 +1952,7 @@ static ieee80211_rx_result debug_noinline
|
|||
ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
|
||||
{
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
||||
|
||||
/*
|
||||
* From here on, look only at management frames.
|
||||
|
@ -1959,7 +1965,7 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
|
|||
if (!ieee80211_is_mgmt(mgmt->frame_control))
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
|
||||
if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
if (ieee80211_drop_unencrypted_mgmt(rx))
|
||||
|
@ -1974,6 +1980,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
|||
struct ieee80211_local *local = rx->local;
|
||||
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
||||
int len = rx->skb->len;
|
||||
|
||||
if (!ieee80211_is_action(mgmt->frame_control))
|
||||
|
@ -1986,7 +1993,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
|||
if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC)
|
||||
return RX_DROP_UNUSABLE;
|
||||
|
||||
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
|
||||
if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
|
||||
return RX_DROP_UNUSABLE;
|
||||
|
||||
switch (mgmt->u.action.category) {
|
||||
|
@ -2082,7 +2089,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
|||
return RX_CONTINUE;
|
||||
|
||||
invalid:
|
||||
rx->flags |= IEEE80211_MALFORMED_ACTION_FRM;
|
||||
status->rx_flags |= IEEE80211_RX_MALFORMED_ACTION_FRM;
|
||||
/* will return in the next handlers */
|
||||
return RX_CONTINUE;
|
||||
|
||||
|
@ -2104,10 +2111,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
|||
static ieee80211_rx_result debug_noinline
|
||||
ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
|
||||
{
|
||||
struct ieee80211_rx_status *status;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
||||
|
||||
/* skip known-bad action frames and return them in the next handler */
|
||||
if (rx->flags & IEEE80211_MALFORMED_ACTION_FRM)
|
||||
if (status->rx_flags & IEEE80211_RX_MALFORMED_ACTION_FRM)
|
||||
return RX_CONTINUE;
|
||||
|
||||
/*
|
||||
|
@ -2116,7 +2123,6 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
|
|||
* so userspace can register for those to know whether ones
|
||||
* it transmitted were processed or returned.
|
||||
*/
|
||||
status = IEEE80211_SKB_RXCB(rx->skb);
|
||||
|
||||
if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq,
|
||||
rx->skb->data, rx->skb->len,
|
||||
|
@ -2138,6 +2144,7 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
|
|||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
|
||||
struct sk_buff *nskb;
|
||||
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
||||
|
||||
if (!ieee80211_is_action(mgmt->frame_control))
|
||||
return RX_CONTINUE;
|
||||
|
@ -2152,7 +2159,7 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
|
|||
* registration mechanisms, but older ones still use cooked
|
||||
* monitor interfaces so push all frames there.
|
||||
*/
|
||||
if (!(rx->flags & IEEE80211_MALFORMED_ACTION_FRM) &&
|
||||
if (!(status->rx_flags & IEEE80211_RX_MALFORMED_ACTION_FRM) &&
|
||||
(sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN))
|
||||
return RX_DROP_MONITOR;
|
||||
|
@ -2286,8 +2293,13 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
|
|||
struct net_device *prev_dev = NULL;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
|
||||
if (status->flag & RX_FLAG_INTERNAL_CMTR)
|
||||
/*
|
||||
* If cooked monitor has been processed already, then
|
||||
* don't do it again. If not, set the flag.
|
||||
*/
|
||||
if (rx->flags & IEEE80211_RX_CMNTR)
|
||||
goto out_free_skb;
|
||||
rx->flags |= IEEE80211_RX_CMNTR;
|
||||
|
||||
if (skb_headroom(skb) < sizeof(*rthdr) &&
|
||||
pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC))
|
||||
|
@ -2343,12 +2355,8 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
|
|||
if (prev_dev) {
|
||||
skb->dev = prev_dev;
|
||||
netif_receive_skb(skb);
|
||||
skb = NULL;
|
||||
} else
|
||||
goto out_free_skb;
|
||||
|
||||
status->flag |= RX_FLAG_INTERNAL_CMTR;
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
out_free_skb:
|
||||
dev_kfree_skb(skb);
|
||||
|
@ -2409,6 +2417,7 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
|
|||
* same TID from the same station
|
||||
*/
|
||||
rx->skb = skb;
|
||||
rx->flags = 0;
|
||||
|
||||
CALL_RXH(ieee80211_rx_h_decrypt)
|
||||
CALL_RXH(ieee80211_rx_h_check_more_data)
|
||||
|
@ -2443,18 +2452,13 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
|
|||
}
|
||||
}
|
||||
|
||||
static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_rx_data *rx,
|
||||
struct sk_buff *skb)
|
||||
static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
|
||||
{
|
||||
struct sk_buff_head reorder_release;
|
||||
ieee80211_rx_result res = RX_DROP_MONITOR;
|
||||
|
||||
__skb_queue_head_init(&reorder_release);
|
||||
|
||||
rx->skb = skb;
|
||||
rx->sdata = sdata;
|
||||
|
||||
#define CALL_RXH(rxh) \
|
||||
do { \
|
||||
res = rxh(rx); \
|
||||
|
@ -2484,7 +2488,12 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
|
|||
void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
|
||||
{
|
||||
struct sk_buff_head frames;
|
||||
struct ieee80211_rx_data rx = { };
|
||||
struct ieee80211_rx_data rx = {
|
||||
.sta = sta,
|
||||
.sdata = sta->sdata,
|
||||
.local = sta->local,
|
||||
.queue = tid,
|
||||
};
|
||||
struct tid_ampdu_rx *tid_agg_rx;
|
||||
|
||||
tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
|
||||
|
@ -2493,17 +2502,6 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
|
|||
|
||||
__skb_queue_head_init(&frames);
|
||||
|
||||
/* construct rx struct */
|
||||
rx.sta = sta;
|
||||
rx.sdata = sta->sdata;
|
||||
rx.local = sta->local;
|
||||
rx.queue = tid;
|
||||
rx.flags |= IEEE80211_RX_RA_MATCH;
|
||||
|
||||
if (unlikely(test_bit(SCAN_HW_SCANNING, &sta->local->scanning) ||
|
||||
test_bit(SCAN_OFF_CHANNEL, &sta->local->scanning)))
|
||||
rx.flags |= IEEE80211_RX_IN_SCAN;
|
||||
|
||||
spin_lock(&tid_agg_rx->reorder_lock);
|
||||
ieee80211_sta_reorder_release(&sta->local->hw, tid_agg_rx, &frames);
|
||||
spin_unlock(&tid_agg_rx->reorder_lock);
|
||||
|
@ -2513,10 +2511,10 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
|
|||
|
||||
/* main receive path */
|
||||
|
||||
static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_rx_data *rx,
|
||||
static int prepare_for_handlers(struct ieee80211_rx_data *rx,
|
||||
struct ieee80211_hdr *hdr)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
struct sk_buff *skb = rx->skb;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
u8 *bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
|
||||
|
@ -2530,7 +2528,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
|
|||
compare_ether_addr(sdata->vif.addr, hdr->addr1) != 0) {
|
||||
if (!(sdata->dev->flags & IFF_PROMISC))
|
||||
return 0;
|
||||
rx->flags &= ~IEEE80211_RX_RA_MATCH;
|
||||
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
|
||||
}
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
|
@ -2540,15 +2538,15 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
|
|||
return 1;
|
||||
}
|
||||
else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) {
|
||||
if (!(rx->flags & IEEE80211_RX_IN_SCAN))
|
||||
if (!(status->rx_flags & IEEE80211_RX_IN_SCAN))
|
||||
return 0;
|
||||
rx->flags &= ~IEEE80211_RX_RA_MATCH;
|
||||
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
|
||||
} else if (!multicast &&
|
||||
compare_ether_addr(sdata->vif.addr,
|
||||
hdr->addr1) != 0) {
|
||||
if (!(sdata->dev->flags & IFF_PROMISC))
|
||||
return 0;
|
||||
rx->flags &= ~IEEE80211_RX_RA_MATCH;
|
||||
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
|
||||
} else if (!rx->sta) {
|
||||
int rate_idx;
|
||||
if (status->flag & RX_FLAG_HT)
|
||||
|
@ -2566,7 +2564,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
|
|||
if (!(sdata->dev->flags & IFF_PROMISC))
|
||||
return 0;
|
||||
|
||||
rx->flags &= ~IEEE80211_RX_RA_MATCH;
|
||||
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
|
||||
}
|
||||
break;
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
|
@ -2577,9 +2575,9 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
|
|||
return 0;
|
||||
} else if (!ieee80211_bssid_match(bssid,
|
||||
sdata->vif.addr)) {
|
||||
if (!(rx->flags & IEEE80211_RX_IN_SCAN))
|
||||
if (!(status->rx_flags & IEEE80211_RX_IN_SCAN))
|
||||
return 0;
|
||||
rx->flags &= ~IEEE80211_RX_RA_MATCH;
|
||||
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
|
||||
}
|
||||
break;
|
||||
case NL80211_IFTYPE_WDS:
|
||||
|
@ -2597,6 +2595,51 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns whether or not the SKB
|
||||
* was destined for RX processing or not, which,
|
||||
* if consume is true, is equivalent to whether
|
||||
* or not the skb was consumed.
|
||||
*/
|
||||
static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
|
||||
struct sk_buff *skb, bool consume)
|
||||
{
|
||||
struct ieee80211_local *local = rx->local;
|
||||
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
int prepares;
|
||||
|
||||
rx->skb = skb;
|
||||
status->rx_flags |= IEEE80211_RX_RA_MATCH;
|
||||
prepares = prepare_for_handlers(rx, hdr);
|
||||
|
||||
if (!prepares)
|
||||
return false;
|
||||
|
||||
if (status->flag & RX_FLAG_MMIC_ERROR) {
|
||||
if (status->rx_flags & IEEE80211_RX_RA_MATCH)
|
||||
ieee80211_rx_michael_mic_report(hdr, rx);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!consume) {
|
||||
skb = skb_copy(skb, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
if (net_ratelimit())
|
||||
wiphy_debug(local->hw.wiphy,
|
||||
"failed to copy multicast frame for %s\n",
|
||||
sdata->name);
|
||||
return true;
|
||||
}
|
||||
|
||||
rx->skb = skb;
|
||||
}
|
||||
|
||||
ieee80211_invoke_rx_handlers(rx);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the actual Rx frames handler. as it blongs to Rx path it must
|
||||
* be called with rcu_read_lock protection.
|
||||
|
@ -2610,11 +2653,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
|||
struct ieee80211_hdr *hdr;
|
||||
__le16 fc;
|
||||
struct ieee80211_rx_data rx;
|
||||
int prepares;
|
||||
struct ieee80211_sub_if_data *prev = NULL;
|
||||
struct sk_buff *skb_new;
|
||||
struct sta_info *sta, *tmp;
|
||||
bool found_sta = false;
|
||||
struct ieee80211_sub_if_data *prev;
|
||||
struct sta_info *sta, *tmp, *prev_sta;
|
||||
int err = 0;
|
||||
|
||||
fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
|
||||
|
@ -2627,7 +2667,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
|||
|
||||
if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
|
||||
test_bit(SCAN_OFF_CHANNEL, &local->scanning)))
|
||||
rx.flags |= IEEE80211_RX_IN_SCAN;
|
||||
status->rx_flags |= IEEE80211_RX_IN_SCAN;
|
||||
|
||||
if (ieee80211_is_mgmt(fc))
|
||||
err = skb_linearize(skb);
|
||||
|
@ -2644,90 +2684,67 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
|||
ieee80211_verify_alignment(&rx);
|
||||
|
||||
if (ieee80211_is_data(fc)) {
|
||||
prev_sta = NULL;
|
||||
|
||||
for_each_sta_info(local, hdr->addr2, sta, tmp) {
|
||||
rx.sta = sta;
|
||||
found_sta = true;
|
||||
rx.sdata = sta->sdata;
|
||||
|
||||
rx.flags |= IEEE80211_RX_RA_MATCH;
|
||||
prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
|
||||
if (prepares) {
|
||||
if (status->flag & RX_FLAG_MMIC_ERROR) {
|
||||
if (rx.flags & IEEE80211_RX_RA_MATCH)
|
||||
ieee80211_rx_michael_mic_report(hdr, &rx);
|
||||
} else
|
||||
prev = rx.sdata;
|
||||
if (!prev_sta) {
|
||||
prev_sta = sta;
|
||||
continue;
|
||||
}
|
||||
|
||||
rx.sta = prev_sta;
|
||||
rx.sdata = prev_sta->sdata;
|
||||
ieee80211_prepare_and_rx_handle(&rx, skb, false);
|
||||
|
||||
prev_sta = sta;
|
||||
}
|
||||
|
||||
if (prev_sta) {
|
||||
rx.sta = prev_sta;
|
||||
rx.sdata = prev_sta->sdata;
|
||||
|
||||
if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!found_sta) {
|
||||
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
|
||||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
continue;
|
||||
prev = NULL;
|
||||
|
||||
/*
|
||||
* frame is destined for this interface, but if it's
|
||||
* not also for the previous one we handle that after
|
||||
* the loop to avoid copying the SKB once too much
|
||||
*/
|
||||
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
|
||||
if (!prev) {
|
||||
prev = sdata;
|
||||
continue;
|
||||
}
|
||||
if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
|
||||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
continue;
|
||||
|
||||
rx.sta = sta_info_get_bss(prev, hdr->addr2);
|
||||
/*
|
||||
* frame is destined for this interface, but if it's
|
||||
* not also for the previous one we handle that after
|
||||
* the loop to avoid copying the SKB once too much
|
||||
*/
|
||||
|
||||
rx.flags |= IEEE80211_RX_RA_MATCH;
|
||||
prepares = prepare_for_handlers(prev, &rx, hdr);
|
||||
|
||||
if (!prepares)
|
||||
goto next;
|
||||
|
||||
if (status->flag & RX_FLAG_MMIC_ERROR) {
|
||||
rx.sdata = prev;
|
||||
if (rx.flags & IEEE80211_RX_RA_MATCH)
|
||||
ieee80211_rx_michael_mic_report(hdr,
|
||||
&rx);
|
||||
goto next;
|
||||
}
|
||||
|
||||
/*
|
||||
* frame was destined for the previous interface
|
||||
* so invoke RX handlers for it
|
||||
*/
|
||||
|
||||
skb_new = skb_copy(skb, GFP_ATOMIC);
|
||||
if (!skb_new) {
|
||||
if (net_ratelimit())
|
||||
wiphy_debug(local->hw.wiphy,
|
||||
"failed to copy multicast frame for %s\n",
|
||||
prev->name);
|
||||
goto next;
|
||||
}
|
||||
ieee80211_invoke_rx_handlers(prev, &rx, skb_new);
|
||||
next:
|
||||
if (!prev) {
|
||||
prev = sdata;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prev) {
|
||||
rx.sta = sta_info_get_bss(prev, hdr->addr2);
|
||||
rx.sta = sta_info_get_bss(prev, hdr->addr2);
|
||||
rx.sdata = prev;
|
||||
ieee80211_prepare_and_rx_handle(&rx, skb, false);
|
||||
|
||||
rx.flags |= IEEE80211_RX_RA_MATCH;
|
||||
prepares = prepare_for_handlers(prev, &rx, hdr);
|
||||
|
||||
if (!prepares)
|
||||
prev = NULL;
|
||||
}
|
||||
prev = sdata;
|
||||
}
|
||||
if (prev)
|
||||
ieee80211_invoke_rx_handlers(prev, &rx, skb);
|
||||
else
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
if (prev) {
|
||||
rx.sta = sta_info_get_bss(prev, hdr->addr2);
|
||||
rx.sdata = prev;
|
||||
|
||||
if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
|
||||
return;
|
||||
}
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2801,6 +2818,8 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
}
|
||||
}
|
||||
|
||||
status->rx_flags = 0;
|
||||
|
||||
/*
|
||||
* key references and virtual interfaces are protected using RCU
|
||||
* and this requires that we are in a read-side RCU section during
|
||||
|
|
|
@ -242,7 +242,8 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
|
|||
local->hw_scan_req->n_channels = n_chans;
|
||||
|
||||
ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie,
|
||||
req->ie, req->ie_len, band);
|
||||
req->ie, req->ie_len, band, (u32) -1,
|
||||
0);
|
||||
local->hw_scan_req->ie_len = ielen;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -838,13 +838,20 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
|
|||
mutex_unlock(&local->sta_mtx);
|
||||
}
|
||||
|
||||
struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
|
||||
const u8 *addr)
|
||||
struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
|
||||
const u8 *addr,
|
||||
const u8 *localaddr)
|
||||
{
|
||||
struct sta_info *sta, *nxt;
|
||||
|
||||
/* Just return a random station ... first in list ... */
|
||||
/*
|
||||
* Just return a random station if localaddr is NULL
|
||||
* ... first in list.
|
||||
*/
|
||||
for_each_sta_info(hw_to_local(hw), addr, sta, nxt) {
|
||||
if (localaddr &&
|
||||
compare_ether_addr(sta->sdata->vif.addr, localaddr) != 0)
|
||||
continue;
|
||||
if (!sta->uploaded)
|
||||
return NULL;
|
||||
return &sta->sta;
|
||||
|
@ -852,7 +859,7 @@ struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
|
|||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw);
|
||||
EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_ifaddr);
|
||||
|
||||
struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
|
||||
const u8 *addr)
|
||||
|
|
|
@ -58,6 +58,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
|
|||
info->control.vif = &sta->sdata->vif;
|
||||
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING |
|
||||
IEEE80211_TX_INTFL_RETRANSMISSION;
|
||||
info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
|
||||
|
||||
sta->tx_filtered_count++;
|
||||
|
||||
|
|
|
@ -895,26 +895,34 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
|
||||
const u8 *ie, size_t ie_len,
|
||||
enum ieee80211_band band)
|
||||
enum ieee80211_band band, u32 rate_mask,
|
||||
u8 channel)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
u8 *pos;
|
||||
size_t offset = 0, noffset;
|
||||
int supp_rates_len, i;
|
||||
u8 rates[32];
|
||||
int num_rates;
|
||||
int ext_rates_len;
|
||||
|
||||
sband = local->hw.wiphy->bands[band];
|
||||
|
||||
pos = buffer;
|
||||
|
||||
supp_rates_len = min_t(int, sband->n_bitrates, 8);
|
||||
num_rates = 0;
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
if ((BIT(i) & rate_mask) == 0)
|
||||
continue; /* skip rate */
|
||||
rates[num_rates++] = (u8) (sband->bitrates[i].bitrate / 5);
|
||||
}
|
||||
|
||||
supp_rates_len = min_t(int, num_rates, 8);
|
||||
|
||||
*pos++ = WLAN_EID_SUPP_RATES;
|
||||
*pos++ = supp_rates_len;
|
||||
|
||||
for (i = 0; i < supp_rates_len; i++) {
|
||||
int rate = sband->bitrates[i].bitrate;
|
||||
*pos++ = (u8) (rate / 5);
|
||||
}
|
||||
memcpy(pos, rates, supp_rates_len);
|
||||
pos += supp_rates_len;
|
||||
|
||||
/* insert "request information" if in custom IEs */
|
||||
if (ie && ie_len) {
|
||||
|
@ -932,14 +940,18 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
|
|||
offset = noffset;
|
||||
}
|
||||
|
||||
if (sband->n_bitrates > i) {
|
||||
ext_rates_len = num_rates - supp_rates_len;
|
||||
if (ext_rates_len > 0) {
|
||||
*pos++ = WLAN_EID_EXT_SUPP_RATES;
|
||||
*pos++ = sband->n_bitrates - i;
|
||||
*pos++ = ext_rates_len;
|
||||
memcpy(pos, rates + supp_rates_len, ext_rates_len);
|
||||
pos += ext_rates_len;
|
||||
}
|
||||
|
||||
for (; i < sband->n_bitrates; i++) {
|
||||
int rate = sband->bitrates[i].bitrate;
|
||||
*pos++ = (u8) (rate / 5);
|
||||
}
|
||||
if (channel && sband->band == IEEE80211_BAND_2GHZ) {
|
||||
*pos++ = WLAN_EID_DS_PARAMS;
|
||||
*pos++ = 1;
|
||||
*pos++ = channel;
|
||||
}
|
||||
|
||||
/* insert custom IEs that go before HT */
|
||||
|
@ -1008,6 +1020,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
|
|||
struct ieee80211_mgmt *mgmt;
|
||||
size_t buf_len;
|
||||
u8 *buf;
|
||||
u8 chan;
|
||||
|
||||
/* FIXME: come up with a proper value */
|
||||
buf = kmalloc(200 + ie_len, GFP_KERNEL);
|
||||
|
@ -1017,8 +1030,14 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
|
|||
return;
|
||||
}
|
||||
|
||||
chan = ieee80211_frequency_to_channel(
|
||||
local->hw.conf.channel->center_freq);
|
||||
|
||||
buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len,
|
||||
local->hw.conf.channel->band);
|
||||
local->hw.conf.channel->band,
|
||||
sdata->rc_rateidx_mask
|
||||
[local->hw.conf.channel->band],
|
||||
chan);
|
||||
|
||||
skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
|
||||
ssid, ssid_len,
|
||||
|
|
|
@ -117,7 +117,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
|
|||
key = &rx->key->conf.key[key_offset];
|
||||
michael_mic(key, hdr, data, data_len, mic);
|
||||
if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) {
|
||||
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
|
||||
if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
|
||||
return RX_DROP_UNUSABLE;
|
||||
|
||||
mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx,
|
||||
|
|
|
@ -88,6 +88,25 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
|
|||
if (wdev->ssid_len)
|
||||
return -EALREADY;
|
||||
|
||||
if (!params->basic_rates) {
|
||||
/*
|
||||
* If no rates were explicitly configured,
|
||||
* use the mandatory rate set for 11b or
|
||||
* 11a for maximum compatibility.
|
||||
*/
|
||||
struct ieee80211_supported_band *sband =
|
||||
rdev->wiphy.bands[params->channel->band];
|
||||
int j;
|
||||
u32 flag = params->channel->band == IEEE80211_BAND_5GHZ ?
|
||||
IEEE80211_RATE_MANDATORY_A :
|
||||
IEEE80211_RATE_MANDATORY_B;
|
||||
|
||||
for (j = 0; j < sband->n_bitrates; j++) {
|
||||
if (sband->bitrates[j].flags & flag)
|
||||
params->basic_rates |= BIT(j);
|
||||
}
|
||||
}
|
||||
|
||||
if (WARN_ON(wdev->connect_keys))
|
||||
kfree(wdev->connect_keys);
|
||||
wdev->connect_keys = connkeys;
|
||||
|
|
|
@ -4119,23 +4119,6 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
|
|||
goto out;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If no rates were explicitly configured,
|
||||
* use the mandatory rate set for 11b or
|
||||
* 11a for maximum compatibility.
|
||||
*/
|
||||
struct ieee80211_supported_band *sband =
|
||||
wiphy->bands[ibss.channel->band];
|
||||
int j;
|
||||
u32 flag = ibss.channel->band == IEEE80211_BAND_5GHZ ?
|
||||
IEEE80211_RATE_MANDATORY_A :
|
||||
IEEE80211_RATE_MANDATORY_B;
|
||||
|
||||
for (j = 0; j < sband->n_bitrates; j++) {
|
||||
if (sband->bitrates[j].flags & flag)
|
||||
ibss.basic_rates |= BIT(j);
|
||||
}
|
||||
}
|
||||
|
||||
err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
|
||||
|
@ -4990,7 +4973,7 @@ static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
|
||||
if (err)
|
||||
goto unlock_rdev;
|
||||
goto unlock_rtnl;
|
||||
|
||||
wdev = dev->ieee80211_ptr;
|
||||
|
||||
|
@ -5014,6 +4997,7 @@ static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
|
|||
unlock_rdev:
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
dev_put(dev);
|
||||
unlock_rtnl:
|
||||
rtnl_unlock();
|
||||
|
||||
out:
|
||||
|
|
Loading…
Reference in New Issue