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