Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem

This commit is contained in:
John W. Linville 2010-10-01 11:12:36 -04:00
commit 41f4a6f71f
49 changed files with 674 additions and 489 deletions

View File

@ -50,7 +50,6 @@ obj-$(CONFIG_ATH_COMMON) += ath/
obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
obj-$(CONFIG_WL12XX) += wl12xx/ obj-$(CONFIG_WL12XX) += wl12xx/
# small builtin driver bit obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx/
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx/wl12xx_platform_data.o
obj-$(CONFIG_IWM) += iwmc3200wifi/ obj-$(CONFIG_IWM) += iwmc3200wifi/

View File

@ -217,7 +217,6 @@ static const char *statsLabels[] = {
(no spaces) list of rates (up to 8). */ (no spaces) list of rates (up to 8). */
static int rates[8]; static int rates[8];
static int basic_rate;
static char *ssids[3]; static char *ssids[3];
static int io[4]; static int io[4];
@ -250,7 +249,6 @@ MODULE_LICENSE("Dual BSD/GPL");
MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340/350"); MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340/350");
module_param_array(io, int, NULL, 0); module_param_array(io, int, NULL, 0);
module_param_array(irq, 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(rates, int, NULL, 0);
module_param_array(ssids, charp, NULL, 0); module_param_array(ssids, charp, NULL, 0);
module_param(auto_wep, int, 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]; 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); set_bit (FLAG_COMMIT, &ai->flags);
} }

View File

@ -1041,7 +1041,6 @@ struct ath5k_hw {
#define ah_modes ah_capabilities.cap_mode #define ah_modes ah_capabilities.cap_mode
#define ah_ee_version ah_capabilities.cap_eeprom.ee_version #define ah_ee_version ah_capabilities.cap_eeprom.ee_version
u32 ah_atim_window;
u32 ah_limit_tx_retries; u32 ah_limit_tx_retries;
u8 ah_coverage_class; 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_set_tsf64(struct ath5k_hw *ah, u64 tsf64);
void ath5k_hw_reset_tsf(struct ath5k_hw *ah); void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); 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 */ /* ACK bit rate */
void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
/* Clock rate related functions */ /* Clock rate related functions */

View File

@ -118,7 +118,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
ah->ah_turbo = false; ah->ah_turbo = false;
ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
ah->ah_imr = 0; ah->ah_imr = 0;
ah->ah_atim_window = 0;
ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
ah->ah_software_retry = false; ah->ah_software_retry = false;
ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;

View File

@ -1191,6 +1191,15 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
*/ */
if (hw_tu >= sc->nexttbtt) if (hw_tu >= sc->nexttbtt)
ath5k_beacon_update_timers(sc, bc_tstamp); 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_tsf = ath5k_hw_get_tsf64(ah);
hw_tu = TSF_TO_TU(hw_tsf); hw_tu = TSF_TO_TU(hw_tsf);
#define FUDGE 3 #define FUDGE AR5K_TUNE_SW_BEACON_RESP + 3
/* we use FUDGE to make sure the next TBTT is ahead of the current TU */ /* 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) { if (bc_tsf == -1) {
/* /*
* no beacons received, called internally. * no beacons received, called internally.

View File

@ -483,6 +483,59 @@ static const struct file_operations fops_antenna = {
.owner = THIS_MODULE, .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 */ /* debugfs: frameerrors */
@ -856,6 +909,10 @@ ath5k_debug_init_device(struct ath5k_softc *sc)
S_IWUSR | S_IRUSR, S_IWUSR | S_IRUSR,
sc->debug.debugfs_phydir, sc, &fops_antenna); 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", sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors",
S_IWUSR | S_IRUSR, S_IWUSR | S_IRUSR,
sc->debug.debugfs_phydir, sc, 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_beacon);
debugfs_remove(sc->debug.debugfs_reset); debugfs_remove(sc->debug.debugfs_reset);
debugfs_remove(sc->debug.debugfs_antenna); debugfs_remove(sc->debug.debugfs_antenna);
debugfs_remove(sc->debug.debugfs_misc);
debugfs_remove(sc->debug.debugfs_frameerrors); debugfs_remove(sc->debug.debugfs_frameerrors);
debugfs_remove(sc->debug.debugfs_ani); debugfs_remove(sc->debug.debugfs_ani);
debugfs_remove(sc->debug.debugfs_queue); debugfs_remove(sc->debug.debugfs_queue);

View File

@ -75,6 +75,7 @@ struct ath5k_dbg_info {
struct dentry *debugfs_beacon; struct dentry *debugfs_beacon;
struct dentry *debugfs_reset; struct dentry *debugfs_reset;
struct dentry *debugfs_antenna; struct dentry *debugfs_antenna;
struct dentry *debugfs_misc;
struct dentry *debugfs_frameerrors; struct dentry *debugfs_frameerrors;
struct dentry *debugfs_ani; struct dentry *debugfs_ani;
struct dentry *debugfs_queue; struct dentry *debugfs_queue;

View File

@ -244,7 +244,7 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
/* Force channel idle high */ /* Force channel idle high */
AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, 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 */ /* Wait a while and disable mechanism */
udelay(200); udelay(200);
@ -261,7 +261,7 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
} while (--i && pending); } while (--i && pending);
AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211, AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211,
AR5K_DIAG_SW_CHANEL_IDLE_HIGH); AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
} }
/* Clear register */ /* Clear register */

View File

@ -495,6 +495,10 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
{ {
u32 tsf_lower, tsf_upper1, tsf_upper2; u32 tsf_lower, tsf_upper1, tsf_upper2;
int i; 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 * 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; tsf_upper1 = tsf_upper2;
} }
local_irq_restore(flags);
WARN_ON( i == ATH5K_MAX_TSF_READ ); WARN_ON( i == ATH5K_MAX_TSF_READ );
return (((u64)tsf_upper1 << 32) | tsf_lower); 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 /* Timer3 marks the end of our ATIM window
* a zero length window is not allowed because * a zero length window is not allowed because
* we 'll get no beacons */ * 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. * 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 * ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class
* *

View File

@ -1257,7 +1257,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
* Disable beacons and RX/TX queues, wait * Disable beacons and RX/TX queues, wait
*/ */
AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210, 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); beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, 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 * Re-enable RX/TX and beacons
*/ */
AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210, 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); ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210);
return 0; return 0;

View File

@ -1387,10 +1387,9 @@
/* /*
* PCU control register * PCU Diagnostic register
* *
* Only DIS_RX is used in the code, the rest i guess are * Used for tweaking/diagnostics.
* for tweaking/diagnostics.
*/ */
#define AR5K_DIAG_SW_5210 0x8068 /* Register Address [5210] */ #define AR5K_DIAG_SW_5210 0x8068 /* Register Address [5210] */
#define AR5K_DIAG_SW_5211 0x8048 /* Register Address [5211+] */ #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_WEP_ACK 0x00000001 /* Disable ACKs if WEP key is invalid */
#define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs */ #define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs */
#define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs */ #define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs */
#define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable encryption */ #define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable HW encryption */
#define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable decryption */ #define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable HW decryption */
#define AR5K_DIAG_SW_DIS_TX 0x00000020 /* Disable transmit [5210] */ #define AR5K_DIAG_SW_DIS_TX_5210 0x00000020 /* Disable transmit [5210] */
#define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable recieve */ #define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable receive */
#define AR5K_DIAG_SW_DIS_RX_5211 0x00000020 #define AR5K_DIAG_SW_DIS_RX_5211 0x00000020
#define AR5K_DIAG_SW_DIS_RX (ah->ah_version == AR5K_AR5210 ? \ #define AR5K_DIAG_SW_DIS_RX (ah->ah_version == AR5K_AR5210 ? \
AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211) 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_5211 0x00000040
#define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \ #define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \
AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211) 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_5211 0x00000080
#define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \ #define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \
AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211) 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_5211 0x00000100
#define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \ #define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \
AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211) 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_SCVRAM_SEED 0x0003f800 /* [5210] */
#define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask */ #define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask */
#define AR5K_DIAG_SW_SCRAM_SEED_S 10 #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_5210 0x00080000
#define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000 /* Accept frames of non-zero protocol number */ #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 ? \ #define AR5K_DIAG_SW_FRAME_NV0 (ah->ah_version == AR5K_AR5210 ? \
AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211) 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_M 0x000c0000 /* Observation point select (?) */
#define AR5K_DIAG_SW_OBSPT_S 18 #define AR5K_DIAG_SW_OBSPT_S 18
#define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x0010000 /* Force RX Clear high */ #define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x00100000 /* Ignore carrier sense */
#define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x0020000 /* Ignore virtual carrier sense */ #define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x00200000 /* Ignore virtual carrier sense */
#define AR5K_DIAG_SW_CHANEL_IDLE_HIGH 0x0040000 /* Force channel idle high */ #define AR5K_DIAG_SW_CHANNEL_IDLE_HIGH 0x00400000 /* Force channel idle high */
#define AR5K_DIAG_SW_PHEAR_ME 0x0080000 /* ??? */ #define AR5K_DIAG_SW_PHEAR_ME 0x00800000 /* ??? */
/* /*
* TSF (clock) register (lower 32 bits) * TSF (clock) register (lower 32 bits)

View File

@ -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) if (!AR_SREV_5416(ah) || synth_freq >= 3000)
return; return;
BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); BUG_ON(AR_SREV_9280_20_OR_LATER(ah));
if (synth_freq < 2412) if (synth_freq < 2412)
new_bias = 0; 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); 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->analogBank0Data, ah->iniBank0.ia_rows);
ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.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; \ bank = NULL; \
} while (0); } 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->analogBank0Data);
ATH_FREE_BANK(ah->analogBank1Data); 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 * for single chip devices, that is AR9280 or anything
* after that. * after that.
*/ */
if (AR_SREV_9280_10_OR_LATER(ah)) if (AR_SREV_9280_20_OR_LATER(ah))
return true; return true;
/* Setup rf parameters */ /* 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)); 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); val = REG_READ(ah, AR_PCU_MISC_MODE2);
if (!AR_SREV_9271(ah)) if (!AR_SREV_9271(ah))
val &= ~AR_PCU_MISC_MODE2_HWWAR1; 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); val = val & (~AR_PCU_MISC_MODE2_HWWAR2);
REG_WRITE(ah, AR_PCU_MISC_MODE2, val); REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
} }
if (!AR_SREV_5416_20_OR_LATER(ah) || if (!AR_SREV_5416_20_OR_LATER(ah) ||
AR_SREV_9280_10_OR_LATER(ah)) AR_SREV_9280_20_OR_LATER(ah))
return; return;
/* /*
* Disable BB clock gating * Disable BB clock gating
@ -701,7 +701,7 @@ static void ar5008_hw_set_channel_regs(struct ath_hw *ah,
u32 phymode; u32 phymode;
u32 enableDacFifo = 0; 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) & enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) &
AR_PHY_FC_ENABLE_DAC_FIFO); AR_PHY_FC_ENABLE_DAC_FIFO);
@ -820,11 +820,11 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
REGWRITE_BUFFER_FLUSH(ah); REGWRITE_BUFFER_FLUSH(ah);
DISABLE_REGWRITE_BUFFER(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); REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites);
if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) || 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); REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
if (AR_SREV_9271_10(ah)) 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)) rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; ? 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)) ? rfMode |= (IS_CHAN_5GHZ(chan)) ?
AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ; AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;

View File

@ -567,11 +567,6 @@ static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
AR5416_EEP_TXGAIN_HIGH_POWER) AR5416_EEP_TXGAIN_HIGH_POWER)
return; 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++) for (i = 0; i < ARRAY_SIZE(regList); i++)
regList[i][1] = REG_READ(ah, regList[i][0]); 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_WRITE(ah, regList[i][0], regList[i][1]);
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); 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) 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); ar9271_hw_pa_cal(ah, is_reset);
else else
ah->pacal_info.skipcount--; 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) if (is_reset || !ah->pacal_info.skipcount)
ar9285_hw_pa_cal(ah, is_reset); ar9285_hw_pa_cal(ah, is_reset);
else 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)) if (!ar9285_hw_clc(ah, chan))
return false; return false;
} else { } else {
if (AR_SREV_9280_10_OR_LATER(ah)) { if (AR_SREV_9280_20_OR_LATER(ah)) {
if (!AR_SREV_9287_10_OR_LATER(ah)) if (!AR_SREV_9287_11_OR_LATER(ah))
REG_CLR_BIT(ah, AR_PHY_ADC_CTL, REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
AR_PHY_ADC_CTL_OFF_PWDADC); AR_PHY_ADC_CTL_OFF_PWDADC);
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, 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; return false;
} }
if (AR_SREV_9280_10_OR_LATER(ah)) { if (AR_SREV_9280_20_OR_LATER(ah)) {
if (!AR_SREV_9287_10_OR_LATER(ah)) if (!AR_SREV_9287_11_OR_LATER(ah))
REG_SET_BIT(ah, AR_PHY_ADC_CTL, REG_SET_BIT(ah, AR_PHY_ADC_CTL,
AR_PHY_ADC_CTL_OFF_PWDADC); AR_PHY_ADC_CTL_OFF_PWDADC);
REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, 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_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->iq_caldata.calData = &iq_cal_single_sample;
ah->adcgain_caldata.calData = ah->adcgain_caldata.calData =
&adc_gain_cal_single_sample; &adc_gain_cal_single_sample;

View File

@ -569,7 +569,7 @@ void ar9002_hw_attach_ops(struct ath_hw *ah)
ops->config_pci_powersave = ar9002_hw_configpcipowersave; ops->config_pci_powersave = ar9002_hw_configpcipowersave;
ar5008_hw_attach_phy_ops(ah); 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_phy_ops(ah);
ar9002_hw_attach_calib_ops(ah); ar9002_hw_attach_calib_ops(ah);

View File

@ -101,7 +101,7 @@
#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) #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) && \ #define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) 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)) ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c #define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c

View File

@ -333,7 +333,7 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah,
} }
if (i == 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)); ss = (int16_t)(0 - (minPwrT4[i] / 2));
else else
ss = 0; ss = 0;
@ -761,7 +761,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
regulatory->max_power_level = ratesArray[i]; 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++) for (i = 0; i < Ar5416RateSize; i++)
ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; 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); AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); 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, REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
pModal->switchSettling); pModal->switchSettling);
REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,

View File

@ -324,7 +324,7 @@ static void ath9k_hw_get_ar9287_gain_boundaries_pdadcs(struct ath_hw *ah,
minDelta = 0; minDelta = 0;
if (i == 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)); ss = (int16_t)(0 - (minPwrT4[i] / 2));
else else
ss = 0; ss = 0;
@ -883,7 +883,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
ratesArray[i] = AR9287_MAX_RATE_POWER; 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++) for (i = 0; i < Ar5416RateSize; i++)
ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
} }
@ -977,7 +977,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
else else
i = rate6mb; i = rate6mb;
if (AR_SREV_9280_10_OR_LATER(ah)) if (AR_SREV_9280_20_OR_LATER(ah))
regulatory->max_power_level = regulatory->max_power_level =
ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
else else

View File

@ -223,7 +223,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
} }
/* Enable fixup for AR_AN_TOP2 if necessary */ /* 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.version & 0xff) > 0x0a &&
eep->baseEepHeader.pwdclkind == 0) eep->baseEepHeader.pwdclkind == 0)
ah->need_an_top2_fixup = 1; 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) { if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
txRxAttenLocal = pModal->txRxAttenCh[i]; 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, REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
pModal->bswMargin[i]); 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, REG_RMW_FIELD(ah,
AR_PHY_RXGAIN + regChainOffset, AR_PHY_RXGAIN + regChainOffset,
AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
@ -408,7 +408,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
regChainOffset, i); regChainOffset, i);
} }
if (AR_SREV_9280_10_OR_LATER(ah)) { if (AR_SREV_9280_20_OR_LATER(ah)) {
if (IS_CHAN_2GHZ(chan)) { if (IS_CHAN_2GHZ(chan)) {
ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
AR_AN_RF2G1_CH0_OB, 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, REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
pModal->adcDesiredSize); 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, REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
AR_PHY_DESIRED_SZ_PGA, AR_PHY_DESIRED_SZ_PGA,
pModal->pgaDesiredSize); 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, REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
pModal->txEndToRxOn); 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, REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
pModal->thresh62); pModal->thresh62);
REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, 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 (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)); ss = (int16_t)(0 - (minPwrT4[i] / 2));
else else
ss = 0; ss = 0;
@ -1291,7 +1291,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
ratesArray[i] = AR5416_MAX_RATE_POWER; 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++) { for (i = 0; i < Ar5416RateSize; i++) {
int8_t pwr_table_offset; 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)) else if (IS_CHAN_HT20(chan))
i = rateHt20_0; i = rateHt20_0;
if (AR_SREV_9280_10_OR_LATER(ah)) if (AR_SREV_9280_20_OR_LATER(ah))
regulatory->max_power_level = regulatory->max_power_level =
ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2; ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2;
else else

View File

@ -235,7 +235,14 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv)
ath9k_hw_get_txq_props(ah, qnum, &qi_be); ath9k_hw_get_txq_props(ah, qnum, &qi_be);
qi.tqi_aifs = qi_be.tqi_aifs; 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; qi.tqi_cwmax = qi_be.tqi_cwmax;
if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) {

View File

@ -561,6 +561,9 @@ static void ath9k_init_crypto(struct ath9k_htc_priv *priv)
common->keymax = ATH_KEYMAX; 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 key cache since some parts do not
* reset the contents on initial power up. * reset the contents on initial power up.

View File

@ -565,7 +565,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
ath9k_hw_init_cal_settings(ah); ath9k_hw_init_cal_settings(ah);
ah->ani_function = ATH9K_ANI_ALL; 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; ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
if (!AR_SREV_9300_20_OR_LATER(ah)) if (!AR_SREV_9300_20_OR_LATER(ah))
ah->ani_function &= ~ATH9K_ANI_MRC_CCK; ah->ani_function &= ~ATH9K_ANI_MRC_CCK;
@ -1190,7 +1190,7 @@ bool ath9k_hw_check_alive(struct ath_hw *ah)
int count = 50; int count = 50;
u32 reg; u32 reg;
if (AR_SREV_9285_10_OR_LATER(ah)) if (AR_SREV_9285_12_OR_LATER(ah))
return true; return true;
do { do {
@ -1312,7 +1312,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (tsf) if (tsf)
ath9k_hw_settsf64(ah, 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); REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
if (!AR_SREV_9300_20_OR_LATER(ah)) 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; regulatory->current_rd = eeval;
eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1); 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; eeval |= AR9285_RDEXT_DEFAULT;
regulatory->current_rd_ext = eeval; regulatory->current_rd_ext = eeval;
@ -1857,8 +1857,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
/* Use rx_chainmask from EEPROM. */ /* Use rx_chainmask from EEPROM. */
pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); 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->low_2ghz_chan = 2312;
pCap->high_2ghz_chan = 2732; 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; pCap->num_gpio_pins = AR9271_NUM_GPIO;
else if (AR_DEVID_7010(ah)) else if (AR_DEVID_7010(ah))
pCap->num_gpio_pins = AR7010_NUM_GPIO; 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; 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; pCap->num_gpio_pins = AR928X_NUM_GPIO;
else else
pCap->num_gpio_pins = AR_NUM_GPIO; 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 = pCap->num_antcfg_2ghz =
ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_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)) { ath9k_hw_btcoex_supported(ah)) {
btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO; btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO;
btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_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)) if (AR_SREV_9300_20_OR_LATER(ah))
pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED; 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; pCap->hw_caps |= ATH9K_HW_CAP_SGI_20;
if (AR_SREV_9285(ah)) 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; return MS_REG_READ(AR9300, gpio) != 0;
else if (AR_SREV_9271(ah)) else if (AR_SREV_9271(ah))
return MS_REG_READ(AR9271, gpio) != 0; 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; 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; 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; return MS_REG_READ(AR928X, gpio) != 0;
else else
return MS_REG_READ(AR, gpio) != 0; 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; int used;
/* chipsets >= AR9280 are single-chip */ /* 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, used = snprintf(hw_name, len,
"Atheros AR%s Rev:%x", "Atheros AR%s Rev:%x",
ath9k_hw_mac_bb_name(ah->hw_version.macVersion), ath9k_hw_mac_bb_name(ah->hw_version.macVersion),

View File

@ -211,7 +211,7 @@ static void setup_ht_cap(struct ath_softc *sc,
else else
max_streams = 2; max_streams = 2;
if (AR_SREV_9280_10_OR_LATER(ah)) { if (AR_SREV_9280_20_OR_LATER(ah)) {
if (max_streams >= 2) if (max_streams >= 2)
ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);

View File

@ -270,6 +270,7 @@ static void ath_paprd_activate(struct ath_softc *sc)
{ {
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath9k_hw_cal_data *caldata = ah->caldata; struct ath9k_hw_cal_data *caldata = ah->caldata;
struct ath_common *common = ath9k_hw_common(ah);
int chain; int chain;
if (!caldata || !caldata->paprd_done) if (!caldata || !caldata->paprd_done)
@ -278,7 +279,7 @@ static void ath_paprd_activate(struct ath_softc *sc)
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
ar9003_paprd_enable(ah, false); ar9003_paprd_enable(ah, false);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
if (!(ah->caps.tx_chainmask & BIT(chain))) if (!(common->tx_chainmask & BIT(chain)))
continue; continue;
ar9003_paprd_populate_single_table(ah, caldata, chain); 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 ieee80211_supported_band *sband = &sc->sbands[band];
struct ath_tx_control txctl; struct ath_tx_control txctl;
struct ath9k_hw_cal_data *caldata = ah->caldata; struct ath9k_hw_cal_data *caldata = ah->caldata;
struct ath_common *common = ath9k_hw_common(ah);
int qnum, ftype; int qnum, ftype;
int chain_ok = 0; int chain_ok = 0;
int chain; int chain;
@ -333,7 +335,7 @@ void ath_paprd_calibrate(struct work_struct *work)
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
ar9003_paprd_init_table(ah); ar9003_paprd_init_table(ah);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
if (!(ah->caps.tx_chainmask & BIT(chain))) if (!(common->tx_chainmask & BIT(chain)))
continue; continue;
chain_ok = 0; chain_ok = 0;

View File

@ -454,8 +454,8 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
else else
rfilt |= ATH9K_RX_FILTER_BEACON; rfilt |= ATH9K_RX_FILTER_BEACON;
if ((AR_SREV_9280_10_OR_LATER(sc->sc_ah) || if ((AR_SREV_9280_20_OR_LATER(sc->sc_ah) ||
AR_SREV_9285_10_OR_LATER(sc->sc_ah)) && AR_SREV_9285_12_OR_LATER(sc->sc_ah)) &&
(sc->sc_ah->opmode == NL80211_IFTYPE_AP) && (sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
(sc->rx.rxfilter & FIF_PSPOLL)) (sc->rx.rxfilter & FIF_PSPOLL))
rfilt |= ATH9K_RX_FILTER_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 * 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. * 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) { if (sta) {
an = (struct ath_node *) sta->drv_priv; an = (struct ath_node *) sta->drv_priv;
if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&

View File

@ -819,49 +819,23 @@
((_ah)->hw_version.macRev == AR_SREV_REVISION_9160_11)) ((_ah)->hw_version.macRev == AR_SREV_REVISION_9160_11))
#define AR_SREV_9280(_ah) \ #define AR_SREV_9280(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280)) (((_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)) (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9280))
#define AR_SREV_9280_20(_ah) \ #define AR_SREV_9280_20(_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))
#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)))
#define AR_SREV_9285(_ah) \ #define AR_SREV_9285(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9285)) (((_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) \ #define AR_SREV_9285_12_OR_LATER(_ah) \
(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285))
(AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \
AR_SREV_REVISION_9285_12)))
#define AR_SREV_9287(_ah) \ #define AR_SREV_9287(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287)) (((_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)) (((_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) \ #define AR_SREV_9287_11(_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)) ((_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) \ #define AR_SREV_9287_12(_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_12)) ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_12))

View File

@ -328,8 +328,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
rcu_read_lock(); rcu_read_lock();
/* XXX: use ieee80211_find_sta! */ sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
sta = ieee80211_find_sta_by_hw(hw, hdr->addr1);
if (!sta) { if (!sta) {
rcu_read_unlock(); rcu_read_unlock();

View File

@ -10,7 +10,7 @@ config CARL9170
but it needs a special firmware (carl9170-1.fw) to do that. but it needs a special firmware (carl9170-1.fw) to do that.
The firmware can be downloaded from our wiki here: 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. If you choose to build a module, it'll be called carl9170.

View File

@ -364,7 +364,6 @@ struct ar9170 {
unsigned int tx_dropped; unsigned int tx_dropped;
unsigned int tx_ack_failures; unsigned int tx_ack_failures;
unsigned int tx_fcs_errors; unsigned int tx_fcs_errors;
unsigned int tx_ampdu_timeout;
unsigned int rx_dropped; unsigned int rx_dropped;
/* EEPROM */ /* EEPROM */

View File

@ -798,8 +798,6 @@ DEBUGFS_READONLY_FILE(tx_total_queued, 20, "%d",
atomic_read(&ar->tx_total_queued)); atomic_read(&ar->tx_total_queued));
DEBUGFS_READONLY_FILE(tx_ampdu_scheduler, 20, "%d", DEBUGFS_READONLY_FILE(tx_ampdu_scheduler, 20, "%d",
atomic_read(&ar->tx_ampdu_scheduler)); 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", DEBUGFS_READONLY_FILE(tx_total_pending, 20, "%d",
atomic_read(&ar->tx_total_pending)); atomic_read(&ar->tx_total_pending));
@ -872,8 +870,6 @@ void carl9170_debugfs_register(struct ar9170 *ar)
DEBUGFS_ADD(ampdu_density); DEBUGFS_ADD(ampdu_density);
DEBUGFS_ADD(ampdu_factor); DEBUGFS_ADD(ampdu_factor);
DEBUGFS_ADD(tx_ampdu_timeout);
DEBUGFS_ADD(tx_janitor_last_run); DEBUGFS_ADD(tx_janitor_last_run);
DEBUGFS_ADD(tx_status_0); DEBUGFS_ADD(tx_status_0);

View File

@ -230,8 +230,15 @@ static void carl9170_flush(struct ar9170 *ar, bool drop_queued)
for (i = 0; i < ar->hw->queues; i++) { for (i = 0; i < ar->hw->queues; i++) {
struct sk_buff *skb; 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); carl9170_tx_status(ar, skb, false);
}
} }
} }
@ -1241,7 +1248,7 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw,
switch (action) { switch (action) {
case IEEE80211_AMPDU_TX_START: case IEEE80211_AMPDU_TX_START:
if (WARN_ON_ONCE(!sta_info->ht_sta)) if (!sta_info->ht_sta)
return -EOPNOTSUPP; return -EOPNOTSUPP;
rcu_read_lock(); rcu_read_lock();
@ -1453,9 +1460,6 @@ static void carl9170_op_sta_notify(struct ieee80211_hw *hw,
while ((skb = __skb_dequeue(&tid_info->queue))) while ((skb = __skb_dequeue(&tid_info->queue)))
__skb_queue_tail(&free, skb); __skb_queue_tail(&free, skb);
spin_unlock_bh(&tid_info->lock); spin_unlock_bh(&tid_info->lock);
ieee80211_stop_tx_ba_session(sta,
tid_info->tid);
} }
rcu_read_unlock(); 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) { skb_queue_walk_safe(&ar->tx_pending[i], skb, tmp) {
struct _carl9170_tx_superframe *super; struct _carl9170_tx_superframe *super;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
struct ieee80211_tx_info *info;
super = (void *) skb->data; super = (void *) skb->data;
hdr = (void *) super->frame_data; hdr = (void *) super->frame_data;
@ -1473,6 +1478,11 @@ static void carl9170_op_sta_notify(struct ieee80211_hw *hw,
continue; continue;
__skb_unlink(skb, &ar->tx_pending[i]); __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); carl9170_tx_status(ar, skb, false);
} }
spin_unlock_bh(&ar->tx_pending[i].lock); spin_unlock_bh(&ar->tx_pending[i].lock);

View File

@ -760,8 +760,8 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
struct carl9170_tx_info *arinfo; struct carl9170_tx_info *arinfo;
unsigned int hw_queue; unsigned int hw_queue;
int i; int i;
u16 keytype = 0; __le16 mac_tmp;
u16 len, icv = 0; u16 len;
bool ampdu, no_ack; bool ampdu, no_ack;
BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); 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(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)]; hw_queue = ar9170_qmap[carl9170_get_queue(ar, skb)];
hdr = (void *)skb->data; 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)); txc = (void *)skb_push(skb, sizeof(*txc));
memset(txc, 0, 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); 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) { 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) { switch (info->control.hw_key->cipher) {
case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104: case WLAN_CIPHER_SUITE_WEP104:
case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_TKIP:
keytype = AR9170_TX_MAC_ENCR_RC4; mac_tmp |= cpu_to_le16(AR9170_TX_MAC_ENCR_RC4);
break; break;
case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_CCMP:
keytype = AR9170_TX_MAC_ENCR_AES; mac_tmp |= cpu_to_le16(AR9170_TX_MAC_ENCR_AES);
break; break;
default: default:
WARN_ON(1); 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 > ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU);
((CARL9170_TX_SUPER_MISC_VIF_ID >> if (ampdu) {
CARL9170_TX_SUPER_MISC_VIF_ID_S) + 1)); unsigned int density, factor;
txc->s.len = cpu_to_le16(len + sizeof(*txc)); if (unlikely(!sta || !cvif))
txc->f.length = cpu_to_le16(len + icv + 4); goto err_out;
SET_VAL(CARL9170_TX_SUPER_MISC_VIF_ID, txc->s.misc,
cvif ? cvif->id : 0);
txc->f.mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION | factor = min_t(unsigned int, 1u,
AR9170_TX_MAC_BACKOFF); 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); if (density) {
txc->f.mac_control |= cpu_to_le16(keytype); /*
txc->f.phy_control = cpu_to_le32(0); * Watch out!
*
* Otus uses slightly different density values than
* those from the 802.11n spec.
*/
if (no_ack) density = max_t(unsigned int, density + 1, 7u);
txc->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); }
if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) SET_VAL(CARL9170_TX_SUPER_AMPDU_DENSITY,
txc->s.misc |= CARL9170_TX_SUPER_MISC_CAB; txc->s.ampdu_settings, density);
txrate = &info->control.rates[0]; SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR,
if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) txc->s.ampdu_settings, factor);
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_RI_TRIES, txc->s.ri[0], txrate->count); for (i = 0; i < CARL9170_TX_MAX_RATES; i++) {
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++) {
txrate = &info->control.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; continue;
}
txrate->idx = 0; txrate->idx = 0;
txrate->count = ar->hw->max_rate_tries; 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 << txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS <<
CARL9170_TX_SUPER_RI_ERP_PROT_S); 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); txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate);
} }
if (ieee80211_is_probe_resp(hdr->frame_control)) txrate = &info->control.rates[0];
txc->s.misc |= CARL9170_TX_SUPER_MISC_FILL_IN_TSF; SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count);
if (ampdu) { if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack))
unsigned int density, factor; 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)) txc->s.len = cpu_to_le16(skb->len);
goto err_out; txc->f.length = cpu_to_le16(len + FCS_LEN);
txc->f.mac_control = mac_tmp;
density = info->control.sta->ht_cap.ampdu_density; txc->f.phy_control = carl9170_tx_physet(ar, info, txrate);
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);
}
}
arinfo = (void *)info->rate_driver_data; arinfo = (void *)info->rate_driver_data;
arinfo->timeout = jiffies; arinfo->timeout = jiffies;
@ -1042,41 +1037,8 @@ retry:
queue = TID_TO_WME_AC(tid_info->tid); queue = TID_TO_WME_AC(tid_info->tid);
spin_lock_bh(&tid_info->lock); spin_lock_bh(&tid_info->lock);
if (tid_info->state != CARL9170_TID_STATE_XMIT) { if (tid_info->state != CARL9170_TID_STATE_XMIT)
first = skb_peek(&tid_info->queue); goto processed;
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;
}
}
tid_info->counter++; tid_info->counter++;
first = skb_peek(&tid_info->queue); first = skb_peek(&tid_info->queue);

View File

@ -606,8 +606,6 @@ int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd,
AR9170_USB_EP_CMD), cmd, cmd->hdr.len + 4, AR9170_USB_EP_CMD), cmd, cmd->hdr.len + 4,
carl9170_usb_cmd_complete, ar, 1); carl9170_usb_cmd_complete, ar, 1);
urb->transfer_flags |= URB_ZERO_PACKET;
if (free_buf) if (free_buf)
urb->transfer_flags |= URB_FREE_BUFFER; urb->transfer_flags |= URB_FREE_BUFFER;

View File

@ -16,3 +16,6 @@ wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o
obj-$(CONFIG_WL1271) += wl1271.o obj-$(CONFIG_WL1271) += wl1271.o
obj-$(CONFIG_WL1271_SPI) += wl1271_spi.o obj-$(CONFIG_WL1271_SPI) += wl1271_spi.o
obj-$(CONFIG_WL1271_SDIO) += wl1271_sdio.o obj-$(CONFIG_WL1271_SDIO) += wl1271_sdio.o
# small builtin driver bit
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o

View File

@ -274,11 +274,11 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
/* /*
* We've reached the first zero length, the first NVS table * 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 -= nvs_ptr - (u8 *)wl->nvs->nvs;
nvs_len = ALIGN(nvs_len, 4);
/* FIXME: The driver sets the partition here, but this is not needed, /* FIXME: The driver sets the partition here, but this is not needed,
since it sets to the same one as currently in use */ 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]); wl1271_set_partition(wl, &part_table[PART_WORK]);
/* Copy the NVS tables to a new block to ensure alignment */ /* Copy the NVS tables to a new block to ensure alignment */
/* FIXME: We jump 3 more bytes before uploading the NVS. It seems nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
that our NVS files have three extra zeros here. I'm not sure whether if (!nvs_aligned)
the problem is in our NVS generation or we should really jumpt these return -ENOMEM;
3 bytes here */
nvs_ptr += 3;
nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); if
(!nvs_aligned) return -ENOMEM;
/* And finally we upload the NVS tables */ /* And finally we upload the NVS tables */
/* FIXME: In wl1271, we upload everything at once. /* FIXME: In wl1271, we upload everything at once.

View File

@ -321,6 +321,9 @@ struct ieee80211_bss_conf {
* @IEEE80211_TX_CTL_LDPC: tells the driver to use LDPC for this frame * @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 * @IEEE80211_TX_CTL_STBC: Enables Space-Time Block Coding (STBC) for this
* frame and selects the maximum number of streams that it can use. * 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 { enum mac80211_tx_control_flags {
IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0),
@ -350,6 +353,19 @@ enum mac80211_tx_control_flags {
#define IEEE80211_TX_CTL_STBC_SHIFT 23 #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 * enum mac80211_rate_control_flags - per-rate flags set by the
* Rate Control algorithm. * 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_HT: HT MCS was used and rate_idx is MCS index
* @RX_FLAG_40MHZ: HT40 (40 MHz) was used * @RX_FLAG_40MHZ: HT40 (40 MHz) was used
* @RX_FLAG_SHORT_GI: Short guard interval 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 { enum mac80211_rx_flags {
RX_FLAG_MMIC_ERROR = 1<<0, RX_FLAG_MMIC_ERROR = 1<<0,
@ -581,7 +594,6 @@ enum mac80211_rx_flags {
RX_FLAG_HT = 1<<9, RX_FLAG_HT = 1<<9,
RX_FLAG_40MHZ = 1<<10, RX_FLAG_40MHZ = 1<<10,
RX_FLAG_SHORT_GI = 1<<11, 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 * @rate_idx: index of data rate into band's supported rates or MCS index if
* HT rates are use (RX_FLAG_HT) * HT rates are use (RX_FLAG_HT)
* @flag: %RX_FLAG_* * @flag: %RX_FLAG_*
* @rx_flags: internal RX flags for mac80211
*/ */
struct ieee80211_rx_status { struct ieee80211_rx_status {
u64 mactime; u64 mactime;
@ -611,6 +624,7 @@ struct ieee80211_rx_status {
int antenna; int antenna;
int rate_idx; int rate_idx;
int flag; int flag;
unsigned int rx_flags;
}; };
/** /**
@ -2416,25 +2430,28 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
const u8 *addr); 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() * @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 * This function must be called under RCU lock and the
* resulting pointer is only valid under RCU lock as well. * resulting pointer is only valid under RCU lock as well.
* *
* NOTE: This function should not be used! When mac80211 is converted * NOTE: You may pass NULL for localaddr, but then you will just get
* internally to properly keep track of stations on multiple * the first STA that matches the remote address 'addr'.
* virtual interfaces, it will not always know which station to * We can have multiple STA associated with multiple
* return here since a single address might be used by multiple * logical stations (e.g. consider a station connecting to another
* logical stations (e.g. consider a station connecting to another * BSSID on the same AP hardware without disconnecting first).
* 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, struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
const u8 *addr); const u8 *addr,
const u8 *localaddr);
/** /**
* ieee80211_sta_block_awake - block station from waking up * ieee80211_sta_block_awake - block station from waking up

View File

@ -368,7 +368,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
if (!phyd) if (!phyd)
return; return;
local->debugfs.stations = debugfs_create_dir("stations", phyd);
local->debugfs.keys = debugfs_create_dir("keys", phyd); local->debugfs.keys = debugfs_create_dir("keys", phyd);
DEBUGFS_ADD(frequency); DEBUGFS_ADD(frequency);

View File

@ -409,6 +409,9 @@ void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
sprintf(buf, "netdev:%s", sdata->name); sprintf(buf, "netdev:%s", sdata->name);
sdata->debugfs.dir = debugfs_create_dir(buf, sdata->debugfs.dir = debugfs_create_dir(buf,
sdata->local->hw.wiphy->debugfsdir); sdata->local->hw.wiphy->debugfsdir);
if (sdata->debugfs.dir)
sdata->debugfs.subdir_stations = debugfs_create_dir("stations",
sdata->debugfs.dir);
add_files(sdata); add_files(sdata);
} }

View File

@ -300,7 +300,7 @@ STA_OPS(ht_capa);
void ieee80211_sta_debugfs_add(struct sta_info *sta) 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]; u8 mac[3*ETH_ALEN];
sta->debugfs.add_has_run = true; sta->debugfs.add_has_run = true;

View File

@ -159,13 +159,37 @@ typedef unsigned __bitwise__ ieee80211_rx_result;
#define RX_DROP_MONITOR ((__force ieee80211_rx_result) 2u) #define RX_DROP_MONITOR ((__force ieee80211_rx_result) 2u)
#define RX_QUEUED ((__force ieee80211_rx_result) 3u) #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) */ * enum ieee80211_packet_rx_flags - packet RX flags
#define IEEE80211_RX_RA_MATCH BIT(1) * @IEEE80211_RX_RA_MATCH: frame is destined to interface currently processed
#define IEEE80211_RX_AMSDU BIT(2) * (incl. multicast frames)
#define IEEE80211_RX_FRAGMENTED BIT(3) * @IEEE80211_RX_IN_SCAN: received while scanning
#define IEEE80211_MALFORMED_ACTION_FRM BIT(4) * @IEEE80211_RX_FRAGMENTED: fragmented frame
/* only add flags here that do not change with subframes of an aMPDU */ * @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 ieee80211_rx_data {
struct sk_buff *skb; struct sk_buff *skb;
@ -564,6 +588,7 @@ struct ieee80211_sub_if_data {
#ifdef CONFIG_MAC80211_DEBUGFS #ifdef CONFIG_MAC80211_DEBUGFS
struct { struct {
struct dentry *dir; struct dentry *dir;
struct dentry *subdir_stations;
struct dentry *default_key; struct dentry *default_key;
struct dentry *default_mgmt_key; struct dentry *default_mgmt_key;
} debugfs; } debugfs;
@ -899,7 +924,6 @@ struct ieee80211_local {
#ifdef CONFIG_MAC80211_DEBUGFS #ifdef CONFIG_MAC80211_DEBUGFS
struct local_debugfsdentries { struct local_debugfsdentries {
struct dentry *rcdir; struct dentry *rcdir;
struct dentry *stations;
struct dentry *keys; struct dentry *keys;
} debugfs; } debugfs;
#endif #endif
@ -1256,7 +1280,8 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
const u8 *key, u8 key_len, u8 key_idx); const u8 *key, u8 key_len, u8 key_idx);
int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
const u8 *ie, size_t ie_len, 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, void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
const u8 *ssid, size_t ssid_len, const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len); const u8 *ie, size_t ie_len);

View File

@ -110,7 +110,8 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
chan = scan_chan; chan = scan_chan;
channel_type = NL80211_CHAN_NO_HT; channel_type = NL80211_CHAN_NO_HT;
local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; 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; chan = scan_chan = local->tmp_channel;
channel_type = local->tmp_channel_type; channel_type = local->tmp_channel_type;
local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;

View File

@ -880,14 +880,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL |
IEEE80211_STA_BEACON_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); ieee80211_led_assoc(local, 1);
if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD)
@ -1367,6 +1359,14 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
return false; 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) if (elems.wmm_param)
ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
elems.wmm_param_len); elems.wmm_param_len);

View File

@ -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) static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
{ {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
int tid; int tid;
/* does the frame have a qos control field? */ /* 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 */ /* frame has qos control */
tid = *qc & IEEE80211_QOS_CTL_TID_MASK; tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
rx->flags |= IEEE80211_RX_AMSDU; status->rx_flags |= IEEE80211_RX_AMSDU;
else
rx->flags &= ~IEEE80211_RX_AMSDU;
} else { } else {
/* /*
* IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"): * 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) ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
{ {
struct ieee80211_local *local = rx->local; struct ieee80211_local *local = rx->local;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
struct sk_buff *skb = 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); return ieee80211_scan_rx(rx->sdata, skb);
if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning) && if (test_bit(SCAN_SW_SCANNING, &local->scanning)) {
(rx->flags & IEEE80211_RX_IN_SCAN))) {
/* drop all the other packets during a software scan anyway */ /* drop all the other packets during a software scan anyway */
if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED) if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED)
dev_kfree_skb(skb); dev_kfree_skb(skb);
return RX_QUEUED; return RX_QUEUED;
} }
if (unlikely(rx->flags & IEEE80211_RX_IN_SCAN)) { /* scanning finished during invoking of handlers */
/* scanning finished during invoking of handlers */ I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
I802_DEBUG_INC(local->rx_handlers_drop_passive_scan); return RX_DROP_UNUSABLE;
return RX_DROP_UNUSABLE;
}
return RX_CONTINUE;
} }
@ -785,13 +783,14 @@ static ieee80211_rx_result debug_noinline
ieee80211_rx_h_check(struct ieee80211_rx_data *rx) ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
{ {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; 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) */ /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) { if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
if (unlikely(ieee80211_has_retry(hdr->frame_control) && if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
rx->sta->last_seq_ctrl[rx->queue] == rx->sta->last_seq_ctrl[rx->queue] ==
hdr->seq_ctrl)) { hdr->seq_ctrl)) {
if (rx->flags & IEEE80211_RX_RA_MATCH) { if (status->rx_flags & IEEE80211_RX_RA_MATCH) {
rx->local->dot11FrameDuplicateCount++; rx->local->dot11FrameDuplicateCount++;
rx->sta->num_duplicates++; rx->sta->num_duplicates++;
} }
@ -824,7 +823,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
if ((!ieee80211_has_fromds(hdr->frame_control) && if ((!ieee80211_has_fromds(hdr->frame_control) &&
!ieee80211_has_tods(hdr->frame_control) && !ieee80211_has_tods(hdr->frame_control) &&
ieee80211_is_data(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 /* Drop IBSS frames and frames for other hosts
* silently. */ * silently. */
return RX_DROP_MONITOR; 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 * No point in finding a key and decrypting if the frame is neither
* addressed to us nor a multicast frame. * 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; return RX_CONTINUE;
/* start without a key */ /* start without a key */
@ -1114,7 +1113,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
sta->last_rx = jiffies; sta->last_rx = jiffies;
} }
if (!(rx->flags & IEEE80211_RX_RA_MATCH)) if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
return RX_CONTINUE; return RX_CONTINUE;
if (rx->sdata->vif.type == NL80211_IFTYPE_STATION) 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; unsigned int frag, seq;
struct ieee80211_fragment_entry *entry; struct ieee80211_fragment_entry *entry;
struct sk_buff *skb; struct sk_buff *skb;
struct ieee80211_rx_status *status;
hdr = (struct ieee80211_hdr *)rx->skb->data; hdr = (struct ieee80211_hdr *)rx->skb->data;
fc = hdr->frame_control; 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 */ /* 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: out:
if (rx->sta) 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; struct ieee80211_sub_if_data *sdata = rx->sdata;
__le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control; __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) || if (likely(!rx->sta || !ieee80211_is_pspoll(fc) ||
!(rx->flags & IEEE80211_RX_RA_MATCH))) !(status->rx_flags & IEEE80211_RX_RA_MATCH)))
return RX_CONTINUE; return RX_CONTINUE;
if ((sdata->vif.type != NL80211_IFTYPE_AP) && 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 sk_buff *skb, *xmit_skb;
struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
struct sta_info *dsta; struct sta_info *dsta;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
skb = rx->skb; skb = rx->skb;
xmit_skb = NULL; xmit_skb = NULL;
@ -1557,7 +1560,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
if ((sdata->vif.type == NL80211_IFTYPE_AP || if ((sdata->vif.type == NL80211_IFTYPE_AP ||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
!(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && !(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)) { (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {
if (is_multicast_ether_addr(ehdr->h_dest)) { 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; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
__le16 fc = hdr->frame_control; __le16 fc = hdr->frame_control;
struct sk_buff_head frame_list; struct sk_buff_head frame_list;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
if (unlikely(!ieee80211_is_data(fc))) if (unlikely(!ieee80211_is_data(fc)))
return RX_CONTINUE; return RX_CONTINUE;
@ -1641,7 +1645,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
if (unlikely(!ieee80211_is_data_present(fc))) if (unlikely(!ieee80211_is_data_present(fc)))
return RX_DROP_MONITOR; return RX_DROP_MONITOR;
if (!(rx->flags & IEEE80211_RX_AMSDU)) if (!(status->rx_flags & IEEE80211_RX_AMSDU))
return RX_CONTINUE; return RX_CONTINUE;
if (ieee80211_has_a4(hdr->frame_control) && 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 sk_buff *skb = rx->skb, *fwd_skb;
struct ieee80211_local *local = rx->local; struct ieee80211_local *local = rx->local;
struct ieee80211_sub_if_data *sdata = rx->sdata; struct ieee80211_sub_if_data *sdata = rx->sdata;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
hdr = (struct ieee80211_hdr *) skb->data; hdr = (struct ieee80211_hdr *) skb->data;
hdrlen = ieee80211_hdrlen(hdr->frame_control); hdrlen = ieee80211_hdrlen(hdr->frame_control);
@ -1737,7 +1742,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
mesh_hdr->ttl--; mesh_hdr->ttl--;
if (rx->flags & IEEE80211_RX_RA_MATCH) { if (status->rx_flags & IEEE80211_RX_RA_MATCH) {
if (!mesh_hdr->ttl) if (!mesh_hdr->ttl)
IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.mesh, IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.mesh,
dropped_frames_ttl); dropped_frames_ttl);
@ -1947,6 +1952,7 @@ static ieee80211_rx_result debug_noinline
ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
{ {
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; 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. * 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)) if (!ieee80211_is_mgmt(mgmt->frame_control))
return RX_DROP_MONITOR; return RX_DROP_MONITOR;
if (!(rx->flags & IEEE80211_RX_RA_MATCH)) if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
return RX_DROP_MONITOR; return RX_DROP_MONITOR;
if (ieee80211_drop_unencrypted_mgmt(rx)) 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_local *local = rx->local;
struct ieee80211_sub_if_data *sdata = rx->sdata; struct ieee80211_sub_if_data *sdata = rx->sdata;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; 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; int len = rx->skb->len;
if (!ieee80211_is_action(mgmt->frame_control)) 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) if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC)
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
if (!(rx->flags & IEEE80211_RX_RA_MATCH)) if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
switch (mgmt->u.action.category) { switch (mgmt->u.action.category) {
@ -2082,7 +2089,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
return RX_CONTINUE; return RX_CONTINUE;
invalid: invalid:
rx->flags |= IEEE80211_MALFORMED_ACTION_FRM; status->rx_flags |= IEEE80211_RX_MALFORMED_ACTION_FRM;
/* will return in the next handlers */ /* will return in the next handlers */
return RX_CONTINUE; return RX_CONTINUE;
@ -2104,10 +2111,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
static ieee80211_rx_result debug_noinline static ieee80211_rx_result debug_noinline
ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx) 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 */ /* 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; 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 * so userspace can register for those to know whether ones
* it transmitted were processed or returned. * it transmitted were processed or returned.
*/ */
status = IEEE80211_SKB_RXCB(rx->skb);
if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq, if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq,
rx->skb->data, rx->skb->len, 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 ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
struct sk_buff *nskb; struct sk_buff *nskb;
struct ieee80211_sub_if_data *sdata = rx->sdata; 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)) if (!ieee80211_is_action(mgmt->frame_control))
return RX_CONTINUE; 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 * registration mechanisms, but older ones still use cooked
* monitor interfaces so push all frames there. * 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 ||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) sdata->vif.type == NL80211_IFTYPE_AP_VLAN))
return RX_DROP_MONITOR; 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 net_device *prev_dev = NULL;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 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; goto out_free_skb;
rx->flags |= IEEE80211_RX_CMNTR;
if (skb_headroom(skb) < sizeof(*rthdr) && if (skb_headroom(skb) < sizeof(*rthdr) &&
pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) 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) { if (prev_dev) {
skb->dev = prev_dev; skb->dev = prev_dev;
netif_receive_skb(skb); netif_receive_skb(skb);
skb = NULL; return;
} else }
goto out_free_skb;
status->flag |= RX_FLAG_INTERNAL_CMTR;
return;
out_free_skb: out_free_skb:
dev_kfree_skb(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 * same TID from the same station
*/ */
rx->skb = skb; rx->skb = skb;
rx->flags = 0;
CALL_RXH(ieee80211_rx_h_decrypt) CALL_RXH(ieee80211_rx_h_decrypt)
CALL_RXH(ieee80211_rx_h_check_more_data) 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, static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
struct ieee80211_rx_data *rx,
struct sk_buff *skb)
{ {
struct sk_buff_head reorder_release; struct sk_buff_head reorder_release;
ieee80211_rx_result res = RX_DROP_MONITOR; ieee80211_rx_result res = RX_DROP_MONITOR;
__skb_queue_head_init(&reorder_release); __skb_queue_head_init(&reorder_release);
rx->skb = skb;
rx->sdata = sdata;
#define CALL_RXH(rxh) \ #define CALL_RXH(rxh) \
do { \ do { \
res = rxh(rx); \ 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) void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
{ {
struct sk_buff_head frames; 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; struct tid_ampdu_rx *tid_agg_rx;
tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]); 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); __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); spin_lock(&tid_agg_rx->reorder_lock);
ieee80211_sta_reorder_release(&sta->local->hw, tid_agg_rx, &frames); ieee80211_sta_reorder_release(&sta->local->hw, tid_agg_rx, &frames);
spin_unlock(&tid_agg_rx->reorder_lock); 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 */ /* main receive path */
static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, static int prepare_for_handlers(struct ieee80211_rx_data *rx,
struct ieee80211_rx_data *rx,
struct ieee80211_hdr *hdr) struct ieee80211_hdr *hdr)
{ {
struct ieee80211_sub_if_data *sdata = rx->sdata;
struct sk_buff *skb = rx->skb; struct sk_buff *skb = rx->skb;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
u8 *bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type); 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) { compare_ether_addr(sdata->vif.addr, hdr->addr1) != 0) {
if (!(sdata->dev->flags & IFF_PROMISC)) if (!(sdata->dev->flags & IFF_PROMISC))
return 0; return 0;
rx->flags &= ~IEEE80211_RX_RA_MATCH; status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
} }
break; break;
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
@ -2540,15 +2538,15 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
return 1; return 1;
} }
else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) { 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; return 0;
rx->flags &= ~IEEE80211_RX_RA_MATCH; status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
} else if (!multicast && } else if (!multicast &&
compare_ether_addr(sdata->vif.addr, compare_ether_addr(sdata->vif.addr,
hdr->addr1) != 0) { hdr->addr1) != 0) {
if (!(sdata->dev->flags & IFF_PROMISC)) if (!(sdata->dev->flags & IFF_PROMISC))
return 0; return 0;
rx->flags &= ~IEEE80211_RX_RA_MATCH; status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
} else if (!rx->sta) { } else if (!rx->sta) {
int rate_idx; int rate_idx;
if (status->flag & RX_FLAG_HT) 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)) if (!(sdata->dev->flags & IFF_PROMISC))
return 0; return 0;
rx->flags &= ~IEEE80211_RX_RA_MATCH; status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
} }
break; break;
case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_AP_VLAN:
@ -2577,9 +2575,9 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
return 0; return 0;
} else if (!ieee80211_bssid_match(bssid, } else if (!ieee80211_bssid_match(bssid,
sdata->vif.addr)) { sdata->vif.addr)) {
if (!(rx->flags & IEEE80211_RX_IN_SCAN)) if (!(status->rx_flags & IEEE80211_RX_IN_SCAN))
return 0; return 0;
rx->flags &= ~IEEE80211_RX_RA_MATCH; status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
} }
break; break;
case NL80211_IFTYPE_WDS: case NL80211_IFTYPE_WDS:
@ -2597,6 +2595,51 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
return 1; 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 * This is the actual Rx frames handler. as it blongs to Rx path it must
* be called with rcu_read_lock protection. * 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; struct ieee80211_hdr *hdr;
__le16 fc; __le16 fc;
struct ieee80211_rx_data rx; struct ieee80211_rx_data rx;
int prepares; struct ieee80211_sub_if_data *prev;
struct ieee80211_sub_if_data *prev = NULL; struct sta_info *sta, *tmp, *prev_sta;
struct sk_buff *skb_new;
struct sta_info *sta, *tmp;
bool found_sta = false;
int err = 0; int err = 0;
fc = ((struct ieee80211_hdr *)skb->data)->frame_control; 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) || if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
test_bit(SCAN_OFF_CHANNEL, &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)) if (ieee80211_is_mgmt(fc))
err = skb_linearize(skb); err = skb_linearize(skb);
@ -2644,90 +2684,67 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
ieee80211_verify_alignment(&rx); ieee80211_verify_alignment(&rx);
if (ieee80211_is_data(fc)) { if (ieee80211_is_data(fc)) {
prev_sta = NULL;
for_each_sta_info(local, hdr->addr2, sta, tmp) { for_each_sta_info(local, hdr->addr2, sta, tmp) {
rx.sta = sta; if (!prev_sta) {
found_sta = true; prev_sta = sta;
rx.sdata = sta->sdata; continue;
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;
} }
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 || prev = NULL;
sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
continue;
/* list_for_each_entry_rcu(sdata, &local->interfaces, list) {
* frame is destined for this interface, but if it's if (!ieee80211_sdata_running(sdata))
* not also for the previous one we handle that after continue;
* the loop to avoid copying the SKB once too much
*/
if (!prev) { if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
prev = sdata; sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
continue; 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; if (!prev) {
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:
prev = sdata; 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; prev = sdata;
prepares = prepare_for_handlers(prev, &rx, hdr);
if (!prepares)
prev = NULL;
}
} }
if (prev)
ieee80211_invoke_rx_handlers(prev, &rx, skb); if (prev) {
else rx.sta = sta_info_get_bss(prev, hdr->addr2);
dev_kfree_skb(skb); 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 * key references and virtual interfaces are protected using RCU
* and this requires that we are in a read-side RCU section during * and this requires that we are in a read-side RCU section during

View File

@ -242,7 +242,8 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
local->hw_scan_req->n_channels = n_chans; local->hw_scan_req->n_channels = n_chans;
ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie, 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; local->hw_scan_req->ie_len = ielen;
return true; return true;

View File

@ -838,13 +838,20 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
mutex_unlock(&local->sta_mtx); mutex_unlock(&local->sta_mtx);
} }
struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
const u8 *addr) const u8 *addr,
const u8 *localaddr)
{ {
struct sta_info *sta, *nxt; 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) { 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) if (!sta->uploaded)
return NULL; return NULL;
return &sta->sta; return &sta->sta;
@ -852,7 +859,7 @@ struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
return NULL; 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, struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
const u8 *addr) const u8 *addr)

View File

@ -58,6 +58,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
info->control.vif = &sta->sdata->vif; info->control.vif = &sta->sdata->vif;
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING |
IEEE80211_TX_INTFL_RETRANSMISSION; IEEE80211_TX_INTFL_RETRANSMISSION;
info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
sta->tx_filtered_count++; sta->tx_filtered_count++;

View File

@ -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, int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
const u8 *ie, size_t ie_len, 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; struct ieee80211_supported_band *sband;
u8 *pos; u8 *pos;
size_t offset = 0, noffset; size_t offset = 0, noffset;
int supp_rates_len, i; int supp_rates_len, i;
u8 rates[32];
int num_rates;
int ext_rates_len;
sband = local->hw.wiphy->bands[band]; sband = local->hw.wiphy->bands[band];
pos = buffer; 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++ = WLAN_EID_SUPP_RATES;
*pos++ = supp_rates_len; *pos++ = supp_rates_len;
memcpy(pos, rates, supp_rates_len);
for (i = 0; i < supp_rates_len; i++) { pos += supp_rates_len;
int rate = sband->bitrates[i].bitrate;
*pos++ = (u8) (rate / 5);
}
/* insert "request information" if in custom IEs */ /* insert "request information" if in custom IEs */
if (ie && ie_len) { if (ie && ie_len) {
@ -932,14 +940,18 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
offset = noffset; 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++ = 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++) { if (channel && sband->band == IEEE80211_BAND_2GHZ) {
int rate = sband->bitrates[i].bitrate; *pos++ = WLAN_EID_DS_PARAMS;
*pos++ = (u8) (rate / 5); *pos++ = 1;
} *pos++ = channel;
} }
/* insert custom IEs that go before HT */ /* 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; struct ieee80211_mgmt *mgmt;
size_t buf_len; size_t buf_len;
u8 *buf; u8 *buf;
u8 chan;
/* FIXME: come up with a proper value */ /* FIXME: come up with a proper value */
buf = kmalloc(200 + ie_len, GFP_KERNEL); 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; return;
} }
chan = ieee80211_frequency_to_channel(
local->hw.conf.channel->center_freq);
buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, 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, skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
ssid, ssid_len, ssid, ssid_len,

View File

@ -117,7 +117,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
key = &rx->key->conf.key[key_offset]; key = &rx->key->conf.key[key_offset];
michael_mic(key, hdr, data, data_len, mic); michael_mic(key, hdr, data, data_len, mic);
if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) { 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; return RX_DROP_UNUSABLE;
mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx, mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx,

View File

@ -88,6 +88,25 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
if (wdev->ssid_len) if (wdev->ssid_len)
return -EALREADY; 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)) if (WARN_ON(wdev->connect_keys))
kfree(wdev->connect_keys); kfree(wdev->connect_keys);
wdev->connect_keys = connkeys; wdev->connect_keys = connkeys;

View File

@ -4119,23 +4119,6 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
goto out; 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); 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); err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err) if (err)
goto unlock_rdev; goto unlock_rtnl;
wdev = dev->ieee80211_ptr; wdev = dev->ieee80211_ptr;
@ -5014,6 +4997,7 @@ static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
unlock_rdev: unlock_rdev:
cfg80211_unlock_rdev(rdev); cfg80211_unlock_rdev(rdev);
dev_put(dev); dev_put(dev);
unlock_rtnl:
rtnl_unlock(); rtnl_unlock();
out: out: