]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville...
authorDavid S. Miller <davem@davemloft.net>
Mon, 4 Oct 2010 05:09:32 +0000 (22:09 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 4 Oct 2010 05:09:32 +0000 (22:09 -0700)
49 files changed:
drivers/net/wireless/Makefile
drivers/net/wireless/airo.c
drivers/net/wireless/ath/ath5k/ath5k.h
drivers/net/wireless/ath/ath5k/attach.c
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath5k/debug.c
drivers/net/wireless/ath/ath5k/debug.h
drivers/net/wireless/ath/ath5k/dma.c
drivers/net/wireless/ath/ath5k/pcu.c
drivers/net/wireless/ath/ath5k/phy.c
drivers/net/wireless/ath/ath5k/reg.h
drivers/net/wireless/ath/ath9k/ar5008_phy.c
drivers/net/wireless/ath/ath9k/ar9002_calib.c
drivers/net/wireless/ath/ath9k/ar9002_hw.c
drivers/net/wireless/ath/ath9k/eeprom.h
drivers/net/wireless/ath/ath9k/eeprom_4k.c
drivers/net/wireless/ath/ath9k/eeprom_9287.c
drivers/net/wireless/ath/ath9k/eeprom_def.c
drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/reg.h
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/carl9170/Kconfig
drivers/net/wireless/ath/carl9170/carl9170.h
drivers/net/wireless/ath/carl9170/debug.c
drivers/net/wireless/ath/carl9170/main.c
drivers/net/wireless/ath/carl9170/tx.c
drivers/net/wireless/ath/carl9170/usb.c
drivers/net/wireless/wl12xx/Makefile
drivers/net/wireless/wl12xx/wl1271_boot.c
include/net/mac80211.h
net/mac80211/debugfs.c
net/mac80211/debugfs_netdev.c
net/mac80211/debugfs_sta.c
net/mac80211/ieee80211_i.h
net/mac80211/main.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/sta_info.c
net/mac80211/status.c
net/mac80211/util.c
net/mac80211/wpa.c
net/wireless/ibss.c
net/wireless/nl80211.c

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