mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-03 22:44:27 -05:00 
			
		
		
		
	mac80211: update to wireless-testing 2010-11-10 + some pending work
SVN-Revision: 23968
This commit is contained in:
		
							parent
							
								
									51fa01f42c
								
							
						
					
					
						commit
						d9d3dfe983
					
				@ -10,12 +10,12 @@ include $(INCLUDE_DIR)/kernel.mk
 | 
			
		||||
 | 
			
		||||
PKG_NAME:=mac80211
 | 
			
		||||
 | 
			
		||||
PKG_VERSION:=2010-10-19
 | 
			
		||||
PKG_VERSION:=2010-11-10
 | 
			
		||||
PKG_RELEASE:=1
 | 
			
		||||
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
 | 
			
		||||
#	http://www.orbit-lab.org/kernel/compat-wireless-2.6/2010/11 \
 | 
			
		||||
#	http://wireless.kernel.org/download/compat-wireless-2.6
 | 
			
		||||
PKG_MD5SUM:=3bad1752f0154baa57a4d94774bd2ccf
 | 
			
		||||
PKG_MD5SUM:=b0df7d2a89818ae96aaa1b3723a51fb7
 | 
			
		||||
 | 
			
		||||
PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2
 | 
			
		||||
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
 | 
			
		||||
 | 
			
		||||
@ -81,7 +81,7 @@
 | 
			
		||||
 void ath_deinit_leds(struct ath_softc *sc)
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
 | 
			
		||||
@@ -860,6 +860,7 @@ static void ath9k_led_brightness_work(st
 | 
			
		||||
@@ -822,6 +822,7 @@ static void ath9k_led_brightness_work(st
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@ -89,7 +89,7 @@
 | 
			
		||||
 static void ath9k_led_brightness(struct led_classdev *led_cdev,
 | 
			
		||||
 				 enum led_brightness brightness)
 | 
			
		||||
 {
 | 
			
		||||
@@ -871,6 +872,7 @@ static void ath9k_led_brightness(struct 
 | 
			
		||||
@@ -833,6 +834,7 @@ static void ath9k_led_brightness(struct 
 | 
			
		||||
 		ieee80211_queue_delayed_work(priv->hw,
 | 
			
		||||
 					     &led->brightness_work, 0);
 | 
			
		||||
 }
 | 
			
		||||
@ -97,7 +97,7 @@
 | 
			
		||||
 
 | 
			
		||||
 static void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv)
 | 
			
		||||
 {
 | 
			
		||||
@@ -883,6 +885,7 @@ static void ath9k_led_stop_brightness(st
 | 
			
		||||
@@ -845,6 +847,7 @@ static void ath9k_led_stop_brightness(st
 | 
			
		||||
 static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led,
 | 
			
		||||
 			      char *trigger)
 | 
			
		||||
 {
 | 
			
		||||
@ -105,7 +105,7 @@
 | 
			
		||||
 	int ret;
 | 
			
		||||
 
 | 
			
		||||
 	led->priv = priv;
 | 
			
		||||
@@ -900,14 +903,19 @@ static int ath9k_register_led(struct ath
 | 
			
		||||
@@ -862,14 +865,19 @@ static int ath9k_register_led(struct ath
 | 
			
		||||
 	INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work);
 | 
			
		||||
 
 | 
			
		||||
 	return ret;
 | 
			
		||||
 | 
			
		||||
@ -1,33 +0,0 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath5k/base.h
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath5k/base.h
 | 
			
		||||
@@ -46,7 +46,7 @@
 | 
			
		||||
 #include <linux/wireless.h>
 | 
			
		||||
 #include <linux/if_ether.h>
 | 
			
		||||
 #include <linux/leds.h>
 | 
			
		||||
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31))
 | 
			
		||||
+#if 0
 | 
			
		||||
 #include <linux/rfkill.h>
 | 
			
		||||
 #else
 | 
			
		||||
 #include <linux/rfkill_backport.h>
 | 
			
		||||
--- a/net/wireless/core.h
 | 
			
		||||
+++ b/net/wireless/core.h
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 #include <linux/kref.h>
 | 
			
		||||
 #include <linux/rbtree.h>
 | 
			
		||||
 #include <linux/debugfs.h>
 | 
			
		||||
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31))
 | 
			
		||||
+#if 0
 | 
			
		||||
 #include <linux/rfkill.h>
 | 
			
		||||
 #else
 | 
			
		||||
 #include <linux/rfkill_backport.h>
 | 
			
		||||
--- a/include/linux/rfkill_backport.h
 | 
			
		||||
+++ b/include/linux/rfkill_backport.h
 | 
			
		||||
@@ -149,7 +149,7 @@ struct rfkill_ops {
 | 
			
		||||
 	int	(*set_block)(void *data, bool blocked);
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
-#if defined(CONFIG_RFKILL_BACKPORT) || defined(CONFIG_RFKILL_BACKPORT_MODULE)
 | 
			
		||||
+#if 0
 | 
			
		||||
 /**
 | 
			
		||||
  * rfkill_alloc - allocate rfkill structure
 | 
			
		||||
  * @name: name of the struct -- the string is not copied internally
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
--- a/include/linux/compat-2.6.36.h
 | 
			
		||||
+++ b/include/linux/compat-2.6.36.h
 | 
			
		||||
@@ -56,6 +56,8 @@ static inline int pcmcia_write_config_by
 | 
			
		||||
 	return pcmcia_access_configuration_register(p_dev, ®);
 | 
			
		||||
 }
 | 
			
		||||
@@ -90,6 +90,8 @@ struct pm_qos_request_list {
 | 
			
		||||
 
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
+#define PCI_EEPROM_WIDTH_93C86   8
 | 
			
		||||
+
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
--- a/compat/compat-2.6.28.c
 | 
			
		||||
+++ b/compat/compat-2.6.28.c
 | 
			
		||||
@@ -89,7 +89,7 @@ EXPORT_SYMBOL_GPL(usb_poison_urb);
 | 
			
		||||
@@ -86,7 +86,7 @@ EXPORT_SYMBOL_GPL(usb_poison_urb);
 | 
			
		||||
 #endif
 | 
			
		||||
 #endif /* CONFIG_USB */
 | 
			
		||||
 
 | 
			
		||||
@ -11,8 +11,8 @@
 | 
			
		||||
 struct pcmcia_cfg_mem {
 | 
			
		||||
--- a/compat/compat-2.6.33.c
 | 
			
		||||
+++ b/compat/compat-2.6.33.c
 | 
			
		||||
@@ -14,7 +14,7 @@
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 #include <linux/compat.h>
 | 
			
		||||
 #include <linux/autoconf.h>
 | 
			
		||||
 
 | 
			
		||||
-#if defined(CONFIG_PCCARD) || defined(CONFIG_PCCARD_MODULE)
 | 
			
		||||
@ -20,7 +20,7 @@
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
  * pccard_loop_tuple() - loop over tuples in the CIS
 | 
			
		||||
@@ -76,7 +76,7 @@ next_entry:
 | 
			
		||||
@@ -73,7 +73,7 @@ next_entry:
 | 
			
		||||
 EXPORT_SYMBOL(pccard_loop_tuple);
 | 
			
		||||
 /* Source: drivers/pcmcia/cistpl.c */
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
--- a/compat/compat-2.6.28.c
 | 
			
		||||
+++ b/compat/compat-2.6.28.c
 | 
			
		||||
@@ -168,7 +168,7 @@ EXPORT_SYMBOL(pcmcia_loop_config);
 | 
			
		||||
@@ -165,7 +165,7 @@ EXPORT_SYMBOL(pcmcia_loop_config);
 | 
			
		||||
 
 | 
			
		||||
 #endif /* CONFIG_PCMCIA */
 | 
			
		||||
 
 | 
			
		||||
@ -11,7 +11,7 @@
 | 
			
		||||
 {
 | 
			
		||||
--- a/compat/compat-2.6.29.c
 | 
			
		||||
+++ b/compat/compat-2.6.29.c
 | 
			
		||||
@@ -52,7 +52,7 @@ void netdev_attach_ops(struct net_device
 | 
			
		||||
@@ -49,7 +49,7 @@ void netdev_attach_ops(struct net_device
 | 
			
		||||
 EXPORT_SYMBOL(netdev_attach_ops);
 | 
			
		||||
 
 | 
			
		||||
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23))
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
 | 
			
		||||
@@ -920,6 +920,12 @@ int ath9k_init_debug(struct ath_hw *ah)
 | 
			
		||||
@@ -932,6 +932,12 @@ int ath9k_init_debug(struct ath_hw *ah)
 | 
			
		||||
 			sc->debug.debugfs_phy, &ah->config.cwm_ignore_extcca))
 | 
			
		||||
 		goto err;
 | 
			
		||||
 
 | 
			
		||||
@ -15,7 +15,7 @@
 | 
			
		||||
 err:
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
 | 
			
		||||
@@ -743,6 +743,8 @@ struct ath_hw {
 | 
			
		||||
@@ -751,6 +751,8 @@ struct ath_hw {
 | 
			
		||||
 	int initPDADC;
 | 
			
		||||
 	int PDADCdelta;
 | 
			
		||||
 	u8 led_pin;
 | 
			
		||||
@ -26,7 +26,7 @@
 | 
			
		||||
 	struct ar5416IniArray iniCommon;
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
 | 
			
		||||
@@ -1178,6 +1178,20 @@ static bool ath9k_hw_channel_change(stru
 | 
			
		||||
@@ -1182,6 +1182,20 @@ static bool ath9k_hw_channel_change(stru
 | 
			
		||||
 	return true;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@ -47,7 +47,7 @@
 | 
			
		||||
 bool ath9k_hw_check_alive(struct ath_hw *ah)
 | 
			
		||||
 {
 | 
			
		||||
 	int count = 50;
 | 
			
		||||
@@ -1464,6 +1478,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
 | 
			
		||||
@@ -1468,6 +1482,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
 | 
			
		||||
 	if (AR_SREV_9300_20_OR_LATER(ah))
 | 
			
		||||
 		ar9003_hw_bb_watchdog_config(ah);
 | 
			
		||||
 
 | 
			
		||||
@ -1,13 +0,0 @@
 | 
			
		||||
--- a/net/wireless/nl80211.c
 | 
			
		||||
+++ b/net/wireless/nl80211.c
 | 
			
		||||
@@ -224,8 +224,8 @@ static int nl80211_prepare_netdev_dump(s
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	*rdev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
 | 
			
		||||
-	if (IS_ERR(dev)) {
 | 
			
		||||
-		err = PTR_ERR(dev);
 | 
			
		||||
+	if (IS_ERR(*rdev)) {
 | 
			
		||||
+		err = PTR_ERR(*rdev);
 | 
			
		||||
 		goto out_rtnl;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
@ -1,16 +1,16 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/main.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
 | 
			
		||||
@@ -15,6 +15,7 @@
 | 
			
		||||
  */
 | 
			
		||||
@@ -16,6 +16,7 @@
 | 
			
		||||
 
 | 
			
		||||
 #include <linux/nl80211.h>
 | 
			
		||||
 #include <linux/pm_qos_params.h>
 | 
			
		||||
+#include <linux/ath9k_platform.h>
 | 
			
		||||
 #include "ath9k.h"
 | 
			
		||||
 #include "btcoex.h"
 | 
			
		||||
 
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/init.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
 | 
			
		||||
@@ -559,6 +559,7 @@ static int ath9k_init_softc(u16 devid, s
 | 
			
		||||
@@ -522,6 +522,7 @@ static int ath9k_init_softc(u16 devid, s
 | 
			
		||||
 {
 | 
			
		||||
 	struct ath_hw *ah = NULL;
 | 
			
		||||
 	struct ath_common *common;
 | 
			
		||||
@ -18,7 +18,7 @@
 | 
			
		||||
 	int ret = 0, i;
 | 
			
		||||
 	int csz = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -570,6 +571,10 @@ static int ath9k_init_softc(u16 devid, s
 | 
			
		||||
@@ -533,6 +534,10 @@ static int ath9k_init_softc(u16 devid, s
 | 
			
		||||
 	ah->hw_version.subsysid = subsysid;
 | 
			
		||||
 	sc->sc_ah = ah;
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
 | 
			
		||||
@@ -1434,7 +1434,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
 | 
			
		||||
@@ -1438,7 +1438,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
 | 
			
		||||
 
 | 
			
		||||
 	if (ah->config.rx_intr_mitigation) {
 | 
			
		||||
 		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
 | 
			
		||||
 | 
			
		||||
@ -1,14 +1,14 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/init.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
 | 
			
		||||
@@ -16,6 +16,7 @@
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@
 | 
			
		||||
 #include <linux/slab.h>
 | 
			
		||||
 #include <linux/pm_qos_params.h>
 | 
			
		||||
 
 | 
			
		||||
+#include "linux/ath9k_platform.h"
 | 
			
		||||
 #include "ath9k.h"
 | 
			
		||||
 
 | 
			
		||||
 static char *dev_info = "ath9k";
 | 
			
		||||
@@ -572,8 +573,14 @@ static int ath9k_init_softc(u16 devid, s
 | 
			
		||||
@@ -535,8 +536,14 @@ static int ath9k_init_softc(u16 devid, s
 | 
			
		||||
 	sc->sc_ah = ah;
 | 
			
		||||
 
 | 
			
		||||
 	pdata = (struct ath9k_platform_data *) sc->dev->platform_data;
 | 
			
		||||
@ -26,7 +26,7 @@
 | 
			
		||||
 	common->ops = &ath9k_common_ops;
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
 | 
			
		||||
@@ -742,7 +742,7 @@ struct ath_hw {
 | 
			
		||||
@@ -750,7 +750,7 @@ struct ath_hw {
 | 
			
		||||
 	u32 originalGain[22];
 | 
			
		||||
 	int initPDADC;
 | 
			
		||||
 	int PDADCdelta;
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
 | 
			
		||||
@@ -861,6 +861,53 @@ static const struct file_operations fops
 | 
			
		||||
 	.owner = THIS_MODULE
 | 
			
		||||
@@ -873,6 +873,53 @@ static const struct file_operations fops
 | 
			
		||||
 	.llseek = default_llseek,
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
+static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
 | 
			
		||||
@ -54,7 +54,7 @@
 | 
			
		||||
 int ath9k_init_debug(struct ath_hw *ah)
 | 
			
		||||
 {
 | 
			
		||||
 	struct ath_common *common = ath9k_hw_common(ah);
 | 
			
		||||
@@ -926,6 +973,10 @@ int ath9k_init_debug(struct ath_hw *ah)
 | 
			
		||||
@@ -938,6 +985,10 @@ int ath9k_init_debug(struct ath_hw *ah)
 | 
			
		||||
 	debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR,
 | 
			
		||||
 			   sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -1,13 +0,0 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
 | 
			
		||||
@@ -177,8 +177,8 @@ void ath_descdma_cleanup(struct ath_soft
 | 
			
		||||
 
 | 
			
		||||
 /* returns delimiter padding required given the packet length */
 | 
			
		||||
 #define ATH_AGGR_GET_NDELIM(_len)					\
 | 
			
		||||
-	(((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ?           \
 | 
			
		||||
-	  (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
 | 
			
		||||
+	(((_len) >= ATH_AGGR_MINPLEN) ? 0 :				\
 | 
			
		||||
+	 DIV_ROUND_UP(ATH_AGGR_MINPLEN - (_len), ATH_AGGR_DELIM_SZ))
 | 
			
		||||
 
 | 
			
		||||
 #define BAW_WITHIN(_start, _bawsz, _seqno) \
 | 
			
		||||
 	((((_seqno) - (_start)) & 4095) < (_bawsz))
 | 
			
		||||
							
								
								
									
										3644
									
								
								package/mac80211/patches/510-pending_work.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3644
									
								
								package/mac80211/patches/510-pending_work.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -1,18 +0,0 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
 | 
			
		||||
@@ -2133,6 +2133,7 @@ static void ath9k_hw_ar9300_set_txpower(
 | 
			
		||||
 					u8 twiceMaxRegulatoryPower,
 | 
			
		||||
 					u8 powerLimit)
 | 
			
		||||
 {
 | 
			
		||||
+	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 | 
			
		||||
 	struct ath_common *common = ath9k_hw_common(ah);
 | 
			
		||||
 	u8 targetPowerValT2[ar9300RateSize];
 | 
			
		||||
 	unsigned int i = 0;
 | 
			
		||||
@@ -2180,6 +2181,7 @@ static void ath9k_hw_ar9300_set_txpower(
 | 
			
		||||
 		i = ALL_TARGET_HT20_0_8_16; /* ht20 */
 | 
			
		||||
 
 | 
			
		||||
 	ah->txpower_limit = targetPowerValT2[i];
 | 
			
		||||
+	regulatory->max_power_level = ratesArray[i];
 | 
			
		||||
 
 | 
			
		||||
 	ar9003_hw_calibration_apply(ah, chan->channel);
 | 
			
		||||
 }
 | 
			
		||||
@ -1,327 +0,0 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
 | 
			
		||||
@@ -680,7 +680,8 @@ struct eeprom_ops {
 | 
			
		||||
 	void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
 | 
			
		||||
 	void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
 | 
			
		||||
 			   u16 cfgCtl, u8 twiceAntennaReduction,
 | 
			
		||||
-			   u8 twiceMaxRegulatoryPower, u8 powerLimit);
 | 
			
		||||
+			   u8 twiceMaxRegulatoryPower, u8 powerLimit,
 | 
			
		||||
+			   bool test);
 | 
			
		||||
 	u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
 | 
			
		||||
@@ -726,7 +726,7 @@ static void ath9k_hw_4k_set_txpower(stru
 | 
			
		||||
 				    u16 cfgCtl,
 | 
			
		||||
 				    u8 twiceAntennaReduction,
 | 
			
		||||
 				    u8 twiceMaxRegulatoryPower,
 | 
			
		||||
-				    u8 powerLimit)
 | 
			
		||||
+				    u8 powerLimit, bool test)
 | 
			
		||||
 {
 | 
			
		||||
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 | 
			
		||||
 	struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
 | 
			
		||||
@@ -751,15 +751,20 @@ static void ath9k_hw_4k_set_txpower(stru
 | 
			
		||||
 
 | 
			
		||||
 	ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
 | 
			
		||||
 
 | 
			
		||||
+	regulatory->max_power_level = 0;
 | 
			
		||||
 	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
 | 
			
		||||
 		ratesArray[i] =	(int16_t)(txPowerIndexOffset + ratesArray[i]);
 | 
			
		||||
 		if (ratesArray[i] > AR5416_MAX_RATE_POWER)
 | 
			
		||||
 			ratesArray[i] = AR5416_MAX_RATE_POWER;
 | 
			
		||||
+
 | 
			
		||||
+		if (ratesArray[i] > regulatory->max_power_level)
 | 
			
		||||
+			regulatory->max_power_level = ratesArray[i];
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	if (test)
 | 
			
		||||
+	    return;
 | 
			
		||||
 
 | 
			
		||||
 	/* Update regulatory */
 | 
			
		||||
-
 | 
			
		||||
 	i = rate6mb;
 | 
			
		||||
 	if (IS_CHAN_HT40(chan))
 | 
			
		||||
 		i = rateHt40_0;
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
 | 
			
		||||
@@ -853,7 +853,7 @@ static void ath9k_hw_ar9287_set_txpower(
 | 
			
		||||
 					struct ath9k_channel *chan, u16 cfgCtl,
 | 
			
		||||
 					u8 twiceAntennaReduction,
 | 
			
		||||
 					u8 twiceMaxRegulatoryPower,
 | 
			
		||||
-					u8 powerLimit)
 | 
			
		||||
+					u8 powerLimit, bool test)
 | 
			
		||||
 {
 | 
			
		||||
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 | 
			
		||||
 	struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
 | 
			
		||||
@@ -877,12 +877,26 @@ static void ath9k_hw_ar9287_set_txpower(
 | 
			
		||||
 
 | 
			
		||||
 	ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset);
 | 
			
		||||
 
 | 
			
		||||
+	regulatory->max_power_level = 0;
 | 
			
		||||
 	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
 | 
			
		||||
 		ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
 | 
			
		||||
 		if (ratesArray[i] > AR9287_MAX_RATE_POWER)
 | 
			
		||||
 			ratesArray[i] = AR9287_MAX_RATE_POWER;
 | 
			
		||||
+
 | 
			
		||||
+		if (ratesArray[i] > regulatory->max_power_level)
 | 
			
		||||
+			regulatory->max_power_level = ratesArray[i];
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	if (test)
 | 
			
		||||
+		return;
 | 
			
		||||
+
 | 
			
		||||
+	if (IS_CHAN_2GHZ(chan))
 | 
			
		||||
+		i = rate1l;
 | 
			
		||||
+	else
 | 
			
		||||
+		i = rate6mb;
 | 
			
		||||
+
 | 
			
		||||
+	regulatory->max_power_level = ratesArray[i];
 | 
			
		||||
+
 | 
			
		||||
 	if (AR_SREV_9280_20_OR_LATER(ah)) {
 | 
			
		||||
 		for (i = 0; i < Ar5416RateSize; i++)
 | 
			
		||||
 			ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
 | 
			
		||||
@@ -971,17 +985,6 @@ static void ath9k_hw_ar9287_set_txpower(
 | 
			
		||||
 			  | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
 | 
			
		||||
 			  | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
 | 
			
		||||
 	}
 | 
			
		||||
-
 | 
			
		||||
-	if (IS_CHAN_2GHZ(chan))
 | 
			
		||||
-		i = rate1l;
 | 
			
		||||
-	else
 | 
			
		||||
-		i = rate6mb;
 | 
			
		||||
-
 | 
			
		||||
-	if (AR_SREV_9280_20_OR_LATER(ah))
 | 
			
		||||
-		regulatory->max_power_level =
 | 
			
		||||
-			ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
 | 
			
		||||
-	else
 | 
			
		||||
-		regulatory->max_power_level = ratesArray[i];
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah,
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
 | 
			
		||||
@@ -1258,7 +1258,7 @@ static void ath9k_hw_def_set_txpower(str
 | 
			
		||||
 				    u16 cfgCtl,
 | 
			
		||||
 				    u8 twiceAntennaReduction,
 | 
			
		||||
 				    u8 twiceMaxRegulatoryPower,
 | 
			
		||||
-				    u8 powerLimit)
 | 
			
		||||
+				    u8 powerLimit, bool test)
 | 
			
		||||
 {
 | 
			
		||||
 #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
 | 
			
		||||
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 | 
			
		||||
@@ -1285,12 +1285,44 @@ static void ath9k_hw_def_set_txpower(str
 | 
			
		||||
 
 | 
			
		||||
 	ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
 | 
			
		||||
 
 | 
			
		||||
+	regulatory->max_power_level = 0;
 | 
			
		||||
 	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
 | 
			
		||||
 		ratesArray[i] =	(int16_t)(txPowerIndexOffset + ratesArray[i]);
 | 
			
		||||
 		if (ratesArray[i] > AR5416_MAX_RATE_POWER)
 | 
			
		||||
 			ratesArray[i] = AR5416_MAX_RATE_POWER;
 | 
			
		||||
+		if (ratesArray[i] > regulatory->max_power_level)
 | 
			
		||||
+			regulatory->max_power_level = ratesArray[i];
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	if (!test) {
 | 
			
		||||
+		i = rate6mb;
 | 
			
		||||
+
 | 
			
		||||
+		if (IS_CHAN_HT40(chan))
 | 
			
		||||
+			i = rateHt40_0;
 | 
			
		||||
+		else if (IS_CHAN_HT20(chan))
 | 
			
		||||
+			i = rateHt20_0;
 | 
			
		||||
+
 | 
			
		||||
+		regulatory->max_power_level = ratesArray[i];
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	switch(ar5416_get_ntxchains(ah->txchainmask)) {
 | 
			
		||||
+	case 1:
 | 
			
		||||
+		break;
 | 
			
		||||
+	case 2:
 | 
			
		||||
+		regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
 | 
			
		||||
+		break;
 | 
			
		||||
+	case 3:
 | 
			
		||||
+		regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
 | 
			
		||||
+		break;
 | 
			
		||||
+	default:
 | 
			
		||||
+		ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM,
 | 
			
		||||
+			  "Invalid chainmask configuration\n");
 | 
			
		||||
+		break;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	if (test)
 | 
			
		||||
+		return;
 | 
			
		||||
+
 | 
			
		||||
 	if (AR_SREV_9280_20_OR_LATER(ah)) {
 | 
			
		||||
 		for (i = 0; i < Ar5416RateSize; i++) {
 | 
			
		||||
 			int8_t pwr_table_offset;
 | 
			
		||||
@@ -1387,34 +1419,6 @@ static void ath9k_hw_def_set_txpower(str
 | 
			
		||||
 	REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
 | 
			
		||||
 		  ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
 | 
			
		||||
 		  | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
 | 
			
		||||
-
 | 
			
		||||
-	i = rate6mb;
 | 
			
		||||
-
 | 
			
		||||
-	if (IS_CHAN_HT40(chan))
 | 
			
		||||
-		i = rateHt40_0;
 | 
			
		||||
-	else if (IS_CHAN_HT20(chan))
 | 
			
		||||
-		i = rateHt20_0;
 | 
			
		||||
-
 | 
			
		||||
-	if (AR_SREV_9280_20_OR_LATER(ah))
 | 
			
		||||
-		regulatory->max_power_level =
 | 
			
		||||
-			ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2;
 | 
			
		||||
-	else
 | 
			
		||||
-		regulatory->max_power_level = ratesArray[i];
 | 
			
		||||
-
 | 
			
		||||
-	switch(ar5416_get_ntxchains(ah->txchainmask)) {
 | 
			
		||||
-	case 1:
 | 
			
		||||
-		break;
 | 
			
		||||
-	case 2:
 | 
			
		||||
-		regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
 | 
			
		||||
-		break;
 | 
			
		||||
-	case 3:
 | 
			
		||||
-		regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
 | 
			
		||||
-		break;
 | 
			
		||||
-	default:
 | 
			
		||||
-		ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM,
 | 
			
		||||
-			  "Invalid chainmask configuration\n");
 | 
			
		||||
-		break;
 | 
			
		||||
-	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
 | 
			
		||||
@@ -2131,7 +2131,7 @@ static void ath9k_hw_ar9300_set_txpower(
 | 
			
		||||
 					struct ath9k_channel *chan, u16 cfgCtl,
 | 
			
		||||
 					u8 twiceAntennaReduction,
 | 
			
		||||
 					u8 twiceMaxRegulatoryPower,
 | 
			
		||||
-					u8 powerLimit)
 | 
			
		||||
+					u8 powerLimit, bool test)
 | 
			
		||||
 {
 | 
			
		||||
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 | 
			
		||||
 	struct ath_common *common = ath9k_hw_common(ah);
 | 
			
		||||
@@ -2145,7 +2145,16 @@ static void ath9k_hw_ar9300_set_txpower(
 | 
			
		||||
 					   twiceMaxRegulatoryPower,
 | 
			
		||||
 					   powerLimit);
 | 
			
		||||
 
 | 
			
		||||
-	while (i < ar9300RateSize) {
 | 
			
		||||
+	regulatory->max_power_level = 0;
 | 
			
		||||
+	for (i = 0; i < ar9300RateSize; i++) {
 | 
			
		||||
+		if (targetPowerValT2[i] > regulatory->max_power_level)
 | 
			
		||||
+			regulatory->max_power_level = targetPowerValT2[i];
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	if (test)
 | 
			
		||||
+		return;
 | 
			
		||||
+
 | 
			
		||||
+	for (i = 0; i < ar9300RateSize; i++) {
 | 
			
		||||
 		ath_print(common, ATH_DBG_EEPROM,
 | 
			
		||||
 			  "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
 | 
			
		||||
 		i++;
 | 
			
		||||
@@ -2160,9 +2169,6 @@ static void ath9k_hw_ar9300_set_txpower(
 | 
			
		||||
 		i++;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	/* Write target power array to registers */
 | 
			
		||||
-	ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
 | 
			
		||||
-
 | 
			
		||||
 	/*
 | 
			
		||||
 	 * This is the TX power we send back to driver core,
 | 
			
		||||
 	 * and it can use to pass to userspace to display our
 | 
			
		||||
@@ -2181,8 +2187,10 @@ static void ath9k_hw_ar9300_set_txpower(
 | 
			
		||||
 		i = ALL_TARGET_HT20_0_8_16; /* ht20 */
 | 
			
		||||
 
 | 
			
		||||
 	ah->txpower_limit = targetPowerValT2[i];
 | 
			
		||||
-	regulatory->max_power_level = ratesArray[i];
 | 
			
		||||
+	regulatory->max_power_level = targetPowerValT2[i];
 | 
			
		||||
 
 | 
			
		||||
+	/* Write target power array to registers */
 | 
			
		||||
+	ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
 | 
			
		||||
 	ar9003_hw_calibration_apply(ah, chan->channel);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
 | 
			
		||||
@@ -1178,7 +1178,7 @@ static bool ath9k_hw_channel_change(stru
 | 
			
		||||
 			     channel->max_antenna_gain * 2,
 | 
			
		||||
 			     channel->max_power * 2,
 | 
			
		||||
 			     min((u32) MAX_RATE_POWER,
 | 
			
		||||
-			     (u32) regulatory->power_limit));
 | 
			
		||||
+			     (u32) regulatory->power_limit), false);
 | 
			
		||||
 
 | 
			
		||||
 	ath9k_hw_rfbus_done(ah);
 | 
			
		||||
 
 | 
			
		||||
@@ -2193,7 +2193,7 @@ bool ath9k_hw_disable(struct ath_hw *ah)
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL(ath9k_hw_disable);
 | 
			
		||||
 
 | 
			
		||||
-void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
 | 
			
		||||
+void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
 | 
			
		||||
 {
 | 
			
		||||
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 | 
			
		||||
 	struct ath9k_channel *chan = ah->curchan;
 | 
			
		||||
@@ -2206,7 +2206,7 @@ void ath9k_hw_set_txpowerlimit(struct at
 | 
			
		||||
 				 channel->max_antenna_gain * 2,
 | 
			
		||||
 				 channel->max_power * 2,
 | 
			
		||||
 				 min((u32) MAX_RATE_POWER,
 | 
			
		||||
-				 (u32) regulatory->power_limit));
 | 
			
		||||
+				 (u32) regulatory->power_limit), test);
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
 | 
			
		||||
 
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
 | 
			
		||||
@@ -862,7 +862,7 @@ u32 ath9k_hw_getrxfilter(struct ath_hw *
 | 
			
		||||
 void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits);
 | 
			
		||||
 bool ath9k_hw_phy_disable(struct ath_hw *ah);
 | 
			
		||||
 bool ath9k_hw_disable(struct ath_hw *ah);
 | 
			
		||||
-void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit);
 | 
			
		||||
+void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test);
 | 
			
		||||
 void ath9k_hw_setopmode(struct ath_hw *ah);
 | 
			
		||||
 void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
 | 
			
		||||
 void ath9k_hw_setbssidmask(struct ath_hw *ah);
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/main.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
 | 
			
		||||
@@ -24,7 +24,7 @@ static void ath_update_txpow(struct ath_
 | 
			
		||||
 	struct ath_hw *ah = sc->sc_ah;
 | 
			
		||||
 
 | 
			
		||||
 	if (sc->curtxpow != sc->config.txpowlimit) {
 | 
			
		||||
-		ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit);
 | 
			
		||||
+		ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
 | 
			
		||||
 		/* read back in case value is clamped */
 | 
			
		||||
 		sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
 | 
			
		||||
 	}
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
 | 
			
		||||
@@ -614,7 +614,7 @@ static int ar9003_hw_process_ini(struct 
 | 
			
		||||
 				 channel->max_antenna_gain * 2,
 | 
			
		||||
 				 channel->max_power * 2,
 | 
			
		||||
 				 min((u32) MAX_RATE_POWER,
 | 
			
		||||
-				 (u32) regulatory->power_limit));
 | 
			
		||||
+				 (u32) regulatory->power_limit), false);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
 | 
			
		||||
@@ -875,7 +875,7 @@ static int ar5008_hw_process_ini(struct 
 | 
			
		||||
 				 channel->max_antenna_gain * 2,
 | 
			
		||||
 				 channel->max_power * 2,
 | 
			
		||||
 				 min((u32) MAX_RATE_POWER,
 | 
			
		||||
-				 (u32) regulatory->power_limit));
 | 
			
		||||
+				 (u32) regulatory->power_limit), false);
 | 
			
		||||
 
 | 
			
		||||
 	/* Write analog registers */
 | 
			
		||||
 	if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
 | 
			
		||||
@@ -29,7 +29,7 @@ static void ath_update_txpow(struct ath9
 | 
			
		||||
 	struct ath_hw *ah = priv->ah;
 | 
			
		||||
 
 | 
			
		||||
 	if (priv->curtxpow != priv->txpowlimit) {
 | 
			
		||||
-		ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit);
 | 
			
		||||
+		ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit, false);
 | 
			
		||||
 		/* read back in case value is clamped */
 | 
			
		||||
 		priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
 | 
			
		||||
 	}
 | 
			
		||||
@ -1,115 +0,0 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/init.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
 | 
			
		||||
@@ -654,6 +654,37 @@ err_hw:
 | 
			
		||||
 	return ret;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
 | 
			
		||||
+{
 | 
			
		||||
+	struct ieee80211_supported_band *sband;
 | 
			
		||||
+	struct ieee80211_channel *chan;
 | 
			
		||||
+	struct ath_hw *ah = sc->sc_ah;
 | 
			
		||||
+	struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
 | 
			
		||||
+	int i;
 | 
			
		||||
+
 | 
			
		||||
+	sband = &sc->sbands[band];
 | 
			
		||||
+	for (i = 0; i < sband->n_channels; i++) {
 | 
			
		||||
+		chan = &sband->channels[i];
 | 
			
		||||
+		ah->curchan = &ah->channels[chan->hw_value];
 | 
			
		||||
+		ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
 | 
			
		||||
+		ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
 | 
			
		||||
+		chan->max_power = reg->max_power_level / 2;
 | 
			
		||||
+	}
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void ath9k_init_txpower_limits(struct ath_softc *sc)
 | 
			
		||||
+{
 | 
			
		||||
+	struct ath_hw *ah = sc->sc_ah;
 | 
			
		||||
+	struct ath9k_channel *curchan = ah->curchan;
 | 
			
		||||
+
 | 
			
		||||
+	if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
 | 
			
		||||
+		ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
 | 
			
		||||
+	if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
 | 
			
		||||
+		ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
 | 
			
		||||
+
 | 
			
		||||
+	ah->curchan = curchan;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
 | 
			
		||||
 {
 | 
			
		||||
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 | 
			
		||||
@@ -748,6 +779,8 @@ int ath9k_init_device(u16 devid, struct 
 | 
			
		||||
 	if (error != 0)
 | 
			
		||||
 		goto error_rx;
 | 
			
		||||
 
 | 
			
		||||
+	ath9k_init_txpower_limits(sc);
 | 
			
		||||
+
 | 
			
		||||
 	/* Register with mac80211 */
 | 
			
		||||
 	error = ieee80211_register_hw(hw);
 | 
			
		||||
 	if (error)
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/common.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/common.c
 | 
			
		||||
@@ -107,12 +107,10 @@ static u32 ath9k_get_extchanmode(struct 
 | 
			
		||||
 /*
 | 
			
		||||
  * Update internal channel flags.
 | 
			
		||||
  */
 | 
			
		||||
-void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
 | 
			
		||||
-			       struct ath9k_channel *ichan)
 | 
			
		||||
+void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
 | 
			
		||||
+			       struct ieee80211_channel *chan,
 | 
			
		||||
+			       enum nl80211_channel_type channel_type)
 | 
			
		||||
 {
 | 
			
		||||
-	struct ieee80211_channel *chan = hw->conf.channel;
 | 
			
		||||
-	struct ieee80211_conf *conf = &hw->conf;
 | 
			
		||||
-
 | 
			
		||||
 	ichan->channel = chan->center_freq;
 | 
			
		||||
 	ichan->chan = chan;
 | 
			
		||||
 
 | 
			
		||||
@@ -124,9 +122,8 @@ void ath9k_cmn_update_ichannel(struct ie
 | 
			
		||||
 		ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	if (conf_is_ht(conf))
 | 
			
		||||
-		ichan->chanmode = ath9k_get_extchanmode(chan,
 | 
			
		||||
-							conf->channel_type);
 | 
			
		||||
+	if (channel_type != NL80211_CHAN_NO_HT)
 | 
			
		||||
+		ichan->chanmode = ath9k_get_extchanmode(chan, channel_type);
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL(ath9k_cmn_update_ichannel);
 | 
			
		||||
 
 | 
			
		||||
@@ -142,7 +139,7 @@ struct ath9k_channel *ath9k_cmn_get_curc
 | 
			
		||||
 
 | 
			
		||||
 	chan_idx = curchan->hw_value;
 | 
			
		||||
 	channel = &ah->channels[chan_idx];
 | 
			
		||||
-	ath9k_cmn_update_ichannel(hw, channel);
 | 
			
		||||
+	ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type);
 | 
			
		||||
 
 | 
			
		||||
 	return channel;
 | 
			
		||||
 }
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/common.h
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/common.h
 | 
			
		||||
@@ -62,8 +62,9 @@ enum ath_stomp_type {
 | 
			
		||||
 
 | 
			
		||||
 int ath9k_cmn_padpos(__le16 frame_control);
 | 
			
		||||
 int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
 | 
			
		||||
-void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
 | 
			
		||||
-			       struct ath9k_channel *ichan);
 | 
			
		||||
+void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
 | 
			
		||||
+			       struct ieee80211_channel *chan,
 | 
			
		||||
+			       enum nl80211_channel_type channel_type);
 | 
			
		||||
 struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
 | 
			
		||||
 					       struct ath_hw *ah);
 | 
			
		||||
 int ath9k_cmn_count_streams(unsigned int chainmask, int max);
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
 | 
			
		||||
@@ -1405,7 +1405,9 @@ static int ath9k_htc_config(struct ieee8
 | 
			
		||||
 		ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
 | 
			
		||||
 			  curchan->center_freq);
 | 
			
		||||
 
 | 
			
		||||
-		ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]);
 | 
			
		||||
+		ath9k_cmn_update_ichannel(&priv->ah->channels[pos],
 | 
			
		||||
+					  hw->conf.channel,
 | 
			
		||||
+					  hw->conf.channel_type);
 | 
			
		||||
 
 | 
			
		||||
 		if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
 | 
			
		||||
 			ath_print(common, ATH_DBG_FATAL,
 | 
			
		||||
@ -1,363 +0,0 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
 | 
			
		||||
@@ -309,7 +309,6 @@ struct ath_rx {
 | 
			
		||||
 	u8 rxotherant;
 | 
			
		||||
 	u32 *rxlink;
 | 
			
		||||
 	unsigned int rxfilter;
 | 
			
		||||
-	spinlock_t rxflushlock;
 | 
			
		||||
 	spinlock_t rxbuflock;
 | 
			
		||||
 	struct list_head rxbuf;
 | 
			
		||||
 	struct ath_descdma rxdma;
 | 
			
		||||
@@ -599,9 +598,9 @@ struct ath_softc {
 | 
			
		||||
 	struct ath_hw *sc_ah;
 | 
			
		||||
 	void __iomem *mem;
 | 
			
		||||
 	int irq;
 | 
			
		||||
-	spinlock_t sc_resetlock;
 | 
			
		||||
 	spinlock_t sc_serial_rw;
 | 
			
		||||
 	spinlock_t sc_pm_lock;
 | 
			
		||||
+	spinlock_t sc_pcu_lock;
 | 
			
		||||
 	struct mutex mutex;
 | 
			
		||||
 	struct work_struct paprd_work;
 | 
			
		||||
 	struct work_struct hw_check_work;
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/main.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
 | 
			
		||||
@@ -228,6 +228,8 @@ int ath_set_channel(struct ath_softc *sc
 | 
			
		||||
 
 | 
			
		||||
 	ath9k_ps_wakeup(sc);
 | 
			
		||||
 
 | 
			
		||||
+	spin_lock_bh(&sc->sc_pcu_lock);
 | 
			
		||||
+
 | 
			
		||||
 	/*
 | 
			
		||||
 	 * This is only performed if the channel settings have
 | 
			
		||||
 	 * actually changed.
 | 
			
		||||
@@ -239,6 +241,7 @@ int ath_set_channel(struct ath_softc *sc
 | 
			
		||||
 	 */
 | 
			
		||||
 	ath9k_hw_disable_interrupts(ah);
 | 
			
		||||
 	ath_drain_all_txq(sc, false);
 | 
			
		||||
+
 | 
			
		||||
 	stopped = ath_stoprecv(sc);
 | 
			
		||||
 
 | 
			
		||||
 	/* XXX: do not flush receive queue here. We don't want
 | 
			
		||||
@@ -257,18 +260,14 @@ int ath_set_channel(struct ath_softc *sc
 | 
			
		||||
 		  channel->center_freq, conf_is_ht40(conf),
 | 
			
		||||
 		  fastcc);
 | 
			
		||||
 
 | 
			
		||||
-	spin_lock_bh(&sc->sc_resetlock);
 | 
			
		||||
-
 | 
			
		||||
 	r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
 | 
			
		||||
 	if (r) {
 | 
			
		||||
 		ath_print(common, ATH_DBG_FATAL,
 | 
			
		||||
 			  "Unable to reset channel (%u MHz), "
 | 
			
		||||
 			  "reset status %d\n",
 | 
			
		||||
 			  channel->center_freq, r);
 | 
			
		||||
-		spin_unlock_bh(&sc->sc_resetlock);
 | 
			
		||||
 		goto ps_restore;
 | 
			
		||||
 	}
 | 
			
		||||
-	spin_unlock_bh(&sc->sc_resetlock);
 | 
			
		||||
 
 | 
			
		||||
 	if (ath_startrecv(sc) != 0) {
 | 
			
		||||
 		ath_print(common, ATH_DBG_FATAL,
 | 
			
		||||
@@ -287,6 +286,8 @@ int ath_set_channel(struct ath_softc *sc
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
  ps_restore:
 | 
			
		||||
+	spin_unlock_bh(&sc->sc_pcu_lock);
 | 
			
		||||
+
 | 
			
		||||
 	ath9k_ps_restore(sc);
 | 
			
		||||
 	return r;
 | 
			
		||||
 }
 | 
			
		||||
@@ -600,6 +601,8 @@ void ath9k_tasklet(unsigned long data)
 | 
			
		||||
 		return;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	spin_lock_bh(&sc->sc_pcu_lock);
 | 
			
		||||
+
 | 
			
		||||
 	if (!ath9k_hw_check_alive(ah))
 | 
			
		||||
 		ieee80211_queue_work(sc->hw, &sc->hw_check_work);
 | 
			
		||||
 
 | 
			
		||||
@@ -610,15 +613,12 @@ void ath9k_tasklet(unsigned long data)
 | 
			
		||||
 		rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
 | 
			
		||||
 
 | 
			
		||||
 	if (status & rxmask) {
 | 
			
		||||
-		spin_lock_bh(&sc->rx.rxflushlock);
 | 
			
		||||
-
 | 
			
		||||
 		/* Check for high priority Rx first */
 | 
			
		||||
 		if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
 | 
			
		||||
 		    (status & ATH9K_INT_RXHP))
 | 
			
		||||
 			ath_rx_tasklet(sc, 0, true);
 | 
			
		||||
 
 | 
			
		||||
 		ath_rx_tasklet(sc, 0, false);
 | 
			
		||||
-		spin_unlock_bh(&sc->rx.rxflushlock);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	if (status & ATH9K_INT_TX) {
 | 
			
		||||
@@ -644,6 +644,8 @@ void ath9k_tasklet(unsigned long data)
 | 
			
		||||
 
 | 
			
		||||
 	/* re-enable hardware interrupt */
 | 
			
		||||
 	ath9k_hw_enable_interrupts(ah);
 | 
			
		||||
+
 | 
			
		||||
+	spin_unlock_bh(&sc->sc_pcu_lock);
 | 
			
		||||
 	ath9k_ps_restore(sc);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -871,12 +873,13 @@ void ath_radio_enable(struct ath_softc *
 | 
			
		||||
 	int r;
 | 
			
		||||
 
 | 
			
		||||
 	ath9k_ps_wakeup(sc);
 | 
			
		||||
+	spin_lock_bh(&sc->sc_pcu_lock);
 | 
			
		||||
+
 | 
			
		||||
 	ath9k_hw_configpcipowersave(ah, 0, 0);
 | 
			
		||||
 
 | 
			
		||||
 	if (!ah->curchan)
 | 
			
		||||
 		ah->curchan = ath_get_curchannel(sc, sc->hw);
 | 
			
		||||
 
 | 
			
		||||
-	spin_lock_bh(&sc->sc_resetlock);
 | 
			
		||||
 	r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
 | 
			
		||||
 	if (r) {
 | 
			
		||||
 		ath_print(common, ATH_DBG_FATAL,
 | 
			
		||||
@@ -884,15 +887,14 @@ void ath_radio_enable(struct ath_softc *
 | 
			
		||||
 			  "reset status %d\n",
 | 
			
		||||
 			  channel->center_freq, r);
 | 
			
		||||
 	}
 | 
			
		||||
-	spin_unlock_bh(&sc->sc_resetlock);
 | 
			
		||||
 
 | 
			
		||||
 	ath_update_txpow(sc);
 | 
			
		||||
 	if (ath_startrecv(sc) != 0) {
 | 
			
		||||
 		ath_print(common, ATH_DBG_FATAL,
 | 
			
		||||
 			  "Unable to restart recv logic\n");
 | 
			
		||||
+		spin_unlock_bh(&sc->sc_pcu_lock);
 | 
			
		||||
 		return;
 | 
			
		||||
 	}
 | 
			
		||||
-
 | 
			
		||||
 	if (sc->sc_flags & SC_OP_BEACONS)
 | 
			
		||||
 		ath_beacon_config(sc, NULL);	/* restart beacons */
 | 
			
		||||
 
 | 
			
		||||
@@ -905,6 +907,8 @@ void ath_radio_enable(struct ath_softc *
 | 
			
		||||
 	ath9k_hw_set_gpio(ah, ah->led_pin, 0);
 | 
			
		||||
 
 | 
			
		||||
 	ieee80211_wake_queues(hw);
 | 
			
		||||
+	spin_unlock_bh(&sc->sc_pcu_lock);
 | 
			
		||||
+
 | 
			
		||||
 	ath9k_ps_restore(sc);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -915,6 +919,8 @@ void ath_radio_disable(struct ath_softc 
 | 
			
		||||
 	int r;
 | 
			
		||||
 
 | 
			
		||||
 	ath9k_ps_wakeup(sc);
 | 
			
		||||
+	spin_lock_bh(&sc->sc_pcu_lock);
 | 
			
		||||
+
 | 
			
		||||
 	ieee80211_stop_queues(hw);
 | 
			
		||||
 
 | 
			
		||||
 	/*
 | 
			
		||||
@@ -930,13 +936,13 @@ void ath_radio_disable(struct ath_softc 
 | 
			
		||||
 	ath9k_hw_disable_interrupts(ah);
 | 
			
		||||
 
 | 
			
		||||
 	ath_drain_all_txq(sc, false);	/* clear pending tx frames */
 | 
			
		||||
+
 | 
			
		||||
 	ath_stoprecv(sc);		/* turn off frame recv */
 | 
			
		||||
 	ath_flushrecv(sc);		/* flush recv queue */
 | 
			
		||||
 
 | 
			
		||||
 	if (!ah->curchan)
 | 
			
		||||
 		ah->curchan = ath_get_curchannel(sc, hw);
 | 
			
		||||
 
 | 
			
		||||
-	spin_lock_bh(&sc->sc_resetlock);
 | 
			
		||||
 	r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
 | 
			
		||||
 	if (r) {
 | 
			
		||||
 		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
 | 
			
		||||
@@ -944,11 +950,14 @@ void ath_radio_disable(struct ath_softc 
 | 
			
		||||
 			  "reset status %d\n",
 | 
			
		||||
 			  channel->center_freq, r);
 | 
			
		||||
 	}
 | 
			
		||||
-	spin_unlock_bh(&sc->sc_resetlock);
 | 
			
		||||
 
 | 
			
		||||
 	ath9k_hw_phy_disable(ah);
 | 
			
		||||
+
 | 
			
		||||
 	ath9k_hw_configpcipowersave(ah, 1, 1);
 | 
			
		||||
+
 | 
			
		||||
+	spin_unlock_bh(&sc->sc_pcu_lock);
 | 
			
		||||
 	ath9k_ps_restore(sc);
 | 
			
		||||
+
 | 
			
		||||
 	ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -962,19 +971,20 @@ int ath_reset(struct ath_softc *sc, bool
 | 
			
		||||
 	/* Stop ANI */
 | 
			
		||||
 	del_timer_sync(&common->ani.timer);
 | 
			
		||||
 
 | 
			
		||||
+	spin_lock_bh(&sc->sc_pcu_lock);
 | 
			
		||||
+
 | 
			
		||||
 	ieee80211_stop_queues(hw);
 | 
			
		||||
 
 | 
			
		||||
 	ath9k_hw_disable_interrupts(ah);
 | 
			
		||||
 	ath_drain_all_txq(sc, retry_tx);
 | 
			
		||||
+
 | 
			
		||||
 	ath_stoprecv(sc);
 | 
			
		||||
 	ath_flushrecv(sc);
 | 
			
		||||
 
 | 
			
		||||
-	spin_lock_bh(&sc->sc_resetlock);
 | 
			
		||||
 	r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
 | 
			
		||||
 	if (r)
 | 
			
		||||
 		ath_print(common, ATH_DBG_FATAL,
 | 
			
		||||
 			  "Unable to reset hardware; reset status %d\n", r);
 | 
			
		||||
-	spin_unlock_bh(&sc->sc_resetlock);
 | 
			
		||||
 
 | 
			
		||||
 	if (ath_startrecv(sc) != 0)
 | 
			
		||||
 		ath_print(common, ATH_DBG_FATAL,
 | 
			
		||||
@@ -1004,6 +1014,7 @@ int ath_reset(struct ath_softc *sc, bool
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	ieee80211_wake_queues(hw);
 | 
			
		||||
+	spin_unlock_bh(&sc->sc_pcu_lock);
 | 
			
		||||
 
 | 
			
		||||
 	/* Start ANI */
 | 
			
		||||
 	ath_start_ani(common);
 | 
			
		||||
@@ -1142,17 +1153,16 @@ static int ath9k_start(struct ieee80211_
 | 
			
		||||
 	 * be followed by initialization of the appropriate bits
 | 
			
		||||
 	 * and then setup of the interrupt mask.
 | 
			
		||||
 	 */
 | 
			
		||||
-	spin_lock_bh(&sc->sc_resetlock);
 | 
			
		||||
+	spin_lock_bh(&sc->sc_pcu_lock);
 | 
			
		||||
 	r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
 | 
			
		||||
 	if (r) {
 | 
			
		||||
 		ath_print(common, ATH_DBG_FATAL,
 | 
			
		||||
 			  "Unable to reset hardware; reset status %d "
 | 
			
		||||
 			  "(freq %u MHz)\n", r,
 | 
			
		||||
 			  curchan->center_freq);
 | 
			
		||||
-		spin_unlock_bh(&sc->sc_resetlock);
 | 
			
		||||
+		spin_unlock_bh(&sc->sc_pcu_lock);
 | 
			
		||||
 		goto mutex_unlock;
 | 
			
		||||
 	}
 | 
			
		||||
-	spin_unlock_bh(&sc->sc_resetlock);
 | 
			
		||||
 
 | 
			
		||||
 	/*
 | 
			
		||||
 	 * This is needed only to setup initial state
 | 
			
		||||
@@ -1171,8 +1181,10 @@ static int ath9k_start(struct ieee80211_
 | 
			
		||||
 		ath_print(common, ATH_DBG_FATAL,
 | 
			
		||||
 			  "Unable to start recv logic\n");
 | 
			
		||||
 		r = -EIO;
 | 
			
		||||
+		spin_unlock_bh(&sc->sc_pcu_lock);
 | 
			
		||||
 		goto mutex_unlock;
 | 
			
		||||
 	}
 | 
			
		||||
+	spin_unlock_bh(&sc->sc_pcu_lock);
 | 
			
		||||
 
 | 
			
		||||
 	/* Setup our intr mask. */
 | 
			
		||||
 	ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
 | 
			
		||||
@@ -1367,6 +1379,8 @@ static void ath9k_stop(struct ieee80211_
 | 
			
		||||
 			ath9k_btcoex_timer_pause(sc);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	spin_lock_bh(&sc->sc_pcu_lock);
 | 
			
		||||
+
 | 
			
		||||
 	/* make sure h/w will not generate any interrupt
 | 
			
		||||
 	 * before setting the invalid flag. */
 | 
			
		||||
 	ath9k_hw_disable_interrupts(ah);
 | 
			
		||||
@@ -1381,6 +1395,9 @@ static void ath9k_stop(struct ieee80211_
 | 
			
		||||
 	/* disable HAL and put h/w to sleep */
 | 
			
		||||
 	ath9k_hw_disable(ah);
 | 
			
		||||
 	ath9k_hw_configpcipowersave(ah, 1, 1);
 | 
			
		||||
+
 | 
			
		||||
+	spin_unlock_bh(&sc->sc_pcu_lock);
 | 
			
		||||
+
 | 
			
		||||
 	ath9k_ps_restore(sc);
 | 
			
		||||
 
 | 
			
		||||
 	/* Finally, put the chip in FULL SLEEP mode */
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/recv.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/recv.c
 | 
			
		||||
@@ -297,19 +297,17 @@ static void ath_edma_start_recv(struct a
 | 
			
		||||
 	ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP,
 | 
			
		||||
 			      sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize);
 | 
			
		||||
 
 | 
			
		||||
-	spin_unlock_bh(&sc->rx.rxbuflock);
 | 
			
		||||
-
 | 
			
		||||
 	ath_opmode_init(sc);
 | 
			
		||||
 
 | 
			
		||||
 	ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
 | 
			
		||||
+
 | 
			
		||||
+	spin_unlock_bh(&sc->rx.rxbuflock);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void ath_edma_stop_recv(struct ath_softc *sc)
 | 
			
		||||
 {
 | 
			
		||||
-	spin_lock_bh(&sc->rx.rxbuflock);
 | 
			
		||||
 	ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);
 | 
			
		||||
 	ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);
 | 
			
		||||
-	spin_unlock_bh(&sc->rx.rxbuflock);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 int ath_rx_init(struct ath_softc *sc, int nbufs)
 | 
			
		||||
@@ -319,7 +317,7 @@ int ath_rx_init(struct ath_softc *sc, in
 | 
			
		||||
 	struct ath_buf *bf;
 | 
			
		||||
 	int error = 0;
 | 
			
		||||
 
 | 
			
		||||
-	spin_lock_init(&sc->rx.rxflushlock);
 | 
			
		||||
+	spin_lock_init(&sc->sc_pcu_lock);
 | 
			
		||||
 	sc->sc_flags &= ~SC_OP_RXFLUSH;
 | 
			
		||||
 	spin_lock_init(&sc->rx.rxbuflock);
 | 
			
		||||
 
 | 
			
		||||
@@ -506,9 +504,9 @@ int ath_startrecv(struct ath_softc *sc)
 | 
			
		||||
 	ath9k_hw_rxena(ah);
 | 
			
		||||
 
 | 
			
		||||
 start_recv:
 | 
			
		||||
-	spin_unlock_bh(&sc->rx.rxbuflock);
 | 
			
		||||
 	ath_opmode_init(sc);
 | 
			
		||||
 	ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
 | 
			
		||||
+	spin_unlock_bh(&sc->rx.rxbuflock);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -518,6 +516,7 @@ bool ath_stoprecv(struct ath_softc *sc)
 | 
			
		||||
 	struct ath_hw *ah = sc->sc_ah;
 | 
			
		||||
 	bool stopped;
 | 
			
		||||
 
 | 
			
		||||
+	spin_lock_bh(&sc->rx.rxbuflock);
 | 
			
		||||
 	ath9k_hw_stoppcurecv(ah);
 | 
			
		||||
 	ath9k_hw_setrxfilter(ah, 0);
 | 
			
		||||
 	stopped = ath9k_hw_stopdmarecv(ah);
 | 
			
		||||
@@ -526,19 +525,18 @@ bool ath_stoprecv(struct ath_softc *sc)
 | 
			
		||||
 		ath_edma_stop_recv(sc);
 | 
			
		||||
 	else
 | 
			
		||||
 		sc->rx.rxlink = NULL;
 | 
			
		||||
+	spin_unlock_bh(&sc->rx.rxbuflock);
 | 
			
		||||
 
 | 
			
		||||
 	return stopped;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 void ath_flushrecv(struct ath_softc *sc)
 | 
			
		||||
 {
 | 
			
		||||
-	spin_lock_bh(&sc->rx.rxflushlock);
 | 
			
		||||
 	sc->sc_flags |= SC_OP_RXFLUSH;
 | 
			
		||||
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
 | 
			
		||||
 		ath_rx_tasklet(sc, 1, true);
 | 
			
		||||
 	ath_rx_tasklet(sc, 1, false);
 | 
			
		||||
 	sc->sc_flags &= ~SC_OP_RXFLUSH;
 | 
			
		||||
-	spin_unlock_bh(&sc->rx.rxflushlock);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/init.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
 | 
			
		||||
@@ -592,7 +592,6 @@ static int ath9k_init_softc(u16 devid, s
 | 
			
		||||
 	spin_lock_init(&common->cc_lock);
 | 
			
		||||
 
 | 
			
		||||
 	spin_lock_init(&sc->wiphy_lock);
 | 
			
		||||
-	spin_lock_init(&sc->sc_resetlock);
 | 
			
		||||
 	spin_lock_init(&sc->sc_serial_rw);
 | 
			
		||||
 	spin_lock_init(&sc->sc_pm_lock);
 | 
			
		||||
 	mutex_init(&sc->mutex);
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
 | 
			
		||||
@@ -1142,13 +1142,11 @@ void ath_drain_all_txq(struct ath_softc 
 | 
			
		||||
 		ath_print(common, ATH_DBG_FATAL,
 | 
			
		||||
 			  "Failed to stop TX DMA. Resetting hardware!\n");
 | 
			
		||||
 
 | 
			
		||||
-		spin_lock_bh(&sc->sc_resetlock);
 | 
			
		||||
 		r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
 | 
			
		||||
 		if (r)
 | 
			
		||||
 			ath_print(common, ATH_DBG_FATAL,
 | 
			
		||||
 				  "Unable to reset hardware; reset status %d\n",
 | 
			
		||||
 				  r);
 | 
			
		||||
-		spin_unlock_bh(&sc->sc_resetlock);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
 | 
			
		||||
@ -1,12 +0,0 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/main.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
 | 
			
		||||
@@ -183,6 +183,9 @@ static void ath_update_survey_stats(stru
 | 
			
		||||
 	struct ath_cycle_counters *cc = &common->cc_survey;
 | 
			
		||||
 	unsigned int div = common->clockrate * 1000;
 | 
			
		||||
 
 | 
			
		||||
+	if (!ah->curchan)
 | 
			
		||||
+		return;
 | 
			
		||||
+
 | 
			
		||||
 	if (ah->power_mode == ATH9K_PM_AWAKE)
 | 
			
		||||
 		ath_hw_cycle_counters_update(common);
 | 
			
		||||
 
 | 
			
		||||
@ -1,25 +0,0 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
 | 
			
		||||
@@ -237,13 +237,15 @@ static int ar9002_hw_proc_txdesc(struct 
 | 
			
		||||
 	status = ACCESS_ONCE(ads->ds_txstatus1);
 | 
			
		||||
 	if (status & AR_FrmXmitOK)
 | 
			
		||||
 		ts->ts_status |= ATH9K_TX_ACKED;
 | 
			
		||||
-	if (status & AR_ExcessiveRetries)
 | 
			
		||||
-		ts->ts_status |= ATH9K_TXERR_XRETRY;
 | 
			
		||||
-	if (status & AR_Filtered)
 | 
			
		||||
-		ts->ts_status |= ATH9K_TXERR_FILT;
 | 
			
		||||
-	if (status & AR_FIFOUnderrun) {
 | 
			
		||||
-		ts->ts_status |= ATH9K_TXERR_FIFO;
 | 
			
		||||
-		ath9k_hw_updatetxtriglevel(ah, true);
 | 
			
		||||
+	else {
 | 
			
		||||
+		if (status & AR_ExcessiveRetries)
 | 
			
		||||
+			ts->ts_status |= ATH9K_TXERR_XRETRY;
 | 
			
		||||
+		if (status & AR_Filtered)
 | 
			
		||||
+			ts->ts_status |= ATH9K_TXERR_FILT;
 | 
			
		||||
+		if (status & AR_FIFOUnderrun) {
 | 
			
		||||
+			ts->ts_status |= ATH9K_TXERR_FIFO;
 | 
			
		||||
+			ath9k_hw_updatetxtriglevel(ah, true);
 | 
			
		||||
+		}
 | 
			
		||||
 	}
 | 
			
		||||
 	if (status & AR_TxTimerExpired)
 | 
			
		||||
 		ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
 | 
			
		||||
@ -1,22 +0,0 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
 | 
			
		||||
@@ -673,6 +673,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
 | 
			
		||||
 	u16 aggr_limit = 0, al = 0, bpad = 0,
 | 
			
		||||
 		al_delta, h_baw = tid->baw_size / 2;
 | 
			
		||||
 	enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
 | 
			
		||||
+	struct ieee80211_tx_info *tx_info;
 | 
			
		||||
 
 | 
			
		||||
 	bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list);
 | 
			
		||||
 
 | 
			
		||||
@@ -699,6 +700,11 @@ static enum ATH_AGGR_STATUS ath_tx_form_
 | 
			
		||||
 			break;
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
+		tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
 | 
			
		||||
+		if (nframes && ((tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) ||
 | 
			
		||||
+			!(tx_info->control.rates[0].flags & IEEE80211_TX_RC_MCS)))
 | 
			
		||||
+			break;
 | 
			
		||||
+
 | 
			
		||||
 		/* do not exceed subframe limit */
 | 
			
		||||
 		if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) {
 | 
			
		||||
 			status = ATH_AGGR_LIMITED;
 | 
			
		||||
@ -1,13 +0,0 @@
 | 
			
		||||
--- a/net/mac80211/rc80211_minstrel_ht.c
 | 
			
		||||
+++ b/net/mac80211/rc80211_minstrel_ht.c
 | 
			
		||||
@@ -506,7 +506,9 @@ minstrel_ht_set_rate(struct minstrel_pri
 | 
			
		||||
 	if (!mr->retry_updated)
 | 
			
		||||
 		minstrel_calc_retransmit(mp, mi, index);
 | 
			
		||||
 
 | 
			
		||||
-	if (mr->probability < MINSTREL_FRAC(20, 100))
 | 
			
		||||
+	if (sample)
 | 
			
		||||
+		rate->count = 1;
 | 
			
		||||
+	else if (mr->probability < MINSTREL_FRAC(20, 100))
 | 
			
		||||
 		rate->count = 2;
 | 
			
		||||
 	else if (rtscts)
 | 
			
		||||
 		rate->count = mr->retry_count_rtscts;
 | 
			
		||||
@ -1,52 +0,0 @@
 | 
			
		||||
--- a/net/mac80211/rc80211_minstrel_ht.c
 | 
			
		||||
+++ b/net/mac80211/rc80211_minstrel_ht.c
 | 
			
		||||
@@ -407,8 +407,8 @@ minstrel_ht_tx_status(void *priv, struct
 | 
			
		||||
 	mi->ampdu_len += info->status.ampdu_len;
 | 
			
		||||
 
 | 
			
		||||
 	if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) {
 | 
			
		||||
-		mi->sample_wait = 4 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len);
 | 
			
		||||
-		mi->sample_tries = 3;
 | 
			
		||||
+		mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len);
 | 
			
		||||
+		mi->sample_tries = 2;
 | 
			
		||||
 		mi->sample_count--;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
@@ -564,7 +564,7 @@ minstrel_get_sample_rate(struct minstrel
 | 
			
		||||
 	 */
 | 
			
		||||
 	if (minstrel_get_duration(sample_idx) >
 | 
			
		||||
 	    minstrel_get_duration(mi->max_tp_rate)) {
 | 
			
		||||
-		if (mr->sample_skipped < 10)
 | 
			
		||||
+		if (mr->sample_skipped < 20)
 | 
			
		||||
 			goto next;
 | 
			
		||||
 
 | 
			
		||||
 		if (mi->sample_slow++ > 2)
 | 
			
		||||
@@ -588,6 +588,7 @@ minstrel_ht_get_rate(void *priv, struct 
 | 
			
		||||
 	struct minstrel_ht_sta *mi = &msp->ht;
 | 
			
		||||
 	struct minstrel_priv *mp = priv;
 | 
			
		||||
 	int sample_idx;
 | 
			
		||||
+	bool sample = false;
 | 
			
		||||
 
 | 
			
		||||
 	if (rate_control_send_low(sta, priv_sta, txrc))
 | 
			
		||||
 		return;
 | 
			
		||||
@@ -598,10 +599,11 @@ minstrel_ht_get_rate(void *priv, struct 
 | 
			
		||||
 	info->flags |= mi->tx_flags;
 | 
			
		||||
 	sample_idx = minstrel_get_sample_rate(mp, mi);
 | 
			
		||||
 	if (sample_idx >= 0) {
 | 
			
		||||
+		sample = true;
 | 
			
		||||
 		minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
 | 
			
		||||
 			txrc, true, false);
 | 
			
		||||
 		minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
 | 
			
		||||
-			txrc, false, true);
 | 
			
		||||
+			txrc, false, false);
 | 
			
		||||
 		info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
 | 
			
		||||
 	} else {
 | 
			
		||||
 		minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate,
 | 
			
		||||
@@ -609,7 +611,7 @@ minstrel_ht_get_rate(void *priv, struct 
 | 
			
		||||
 		minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
 | 
			
		||||
 			txrc, false, true);
 | 
			
		||||
 	}
 | 
			
		||||
-	minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate, txrc, false, true);
 | 
			
		||||
+	minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate, txrc, false, !sample);
 | 
			
		||||
 
 | 
			
		||||
 	ar[3].count = 0;
 | 
			
		||||
 	ar[3].idx = -1;
 | 
			
		||||
@ -1,42 +0,0 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/main.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
 | 
			
		||||
@@ -581,7 +581,7 @@ void ath_hw_check(struct work_struct *wo
 | 
			
		||||
 
 | 
			
		||||
 		msleep(1);
 | 
			
		||||
 	}
 | 
			
		||||
-	ath_reset(sc, false);
 | 
			
		||||
+	ath_reset(sc, true);
 | 
			
		||||
 
 | 
			
		||||
 out:
 | 
			
		||||
 	ath9k_ps_restore(sc);
 | 
			
		||||
@@ -599,7 +599,7 @@ void ath9k_tasklet(unsigned long data)
 | 
			
		||||
 	ath9k_ps_wakeup(sc);
 | 
			
		||||
 
 | 
			
		||||
 	if (status & ATH9K_INT_FATAL) {
 | 
			
		||||
-		ath_reset(sc, false);
 | 
			
		||||
+		ath_reset(sc, true);
 | 
			
		||||
 		ath9k_ps_restore(sc);
 | 
			
		||||
 		return;
 | 
			
		||||
 	}
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
 | 
			
		||||
@@ -2161,7 +2161,7 @@ static void ath_tx_complete_poll_work(st
 | 
			
		||||
 		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
 | 
			
		||||
 			  "tx hung, resetting the chip\n");
 | 
			
		||||
 		ath9k_ps_wakeup(sc);
 | 
			
		||||
-		ath_reset(sc, false);
 | 
			
		||||
+		ath_reset(sc, true);
 | 
			
		||||
 		ath9k_ps_restore(sc);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/beacon.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
 | 
			
		||||
@@ -370,7 +370,7 @@ void ath_beacon_tasklet(unsigned long da
 | 
			
		||||
 			ath_print(common, ATH_DBG_BSTUCK,
 | 
			
		||||
 				  "beacon is officially stuck\n");
 | 
			
		||||
 			sc->sc_flags |= SC_OP_TSF_RESET;
 | 
			
		||||
-			ath_reset(sc, false);
 | 
			
		||||
+			ath_reset(sc, true);
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
 		return;
 | 
			
		||||
@ -1,34 +0,0 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
 | 
			
		||||
@@ -1089,15 +1089,6 @@ void ath_draintxq(struct ath_softc *sc, 
 | 
			
		||||
 	txq->axq_tx_inprogress = false;
 | 
			
		||||
 	spin_unlock_bh(&txq->axq_lock);
 | 
			
		||||
 
 | 
			
		||||
-	/* flush any pending frames if aggregation is enabled */
 | 
			
		||||
-	if (sc->sc_flags & SC_OP_TXAGGR) {
 | 
			
		||||
-		if (!retry_tx) {
 | 
			
		||||
-			spin_lock_bh(&txq->axq_lock);
 | 
			
		||||
-			ath_txq_drain_pending_buffers(sc, txq);
 | 
			
		||||
-			spin_unlock_bh(&txq->axq_lock);
 | 
			
		||||
-		}
 | 
			
		||||
-	}
 | 
			
		||||
-
 | 
			
		||||
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
 | 
			
		||||
 		spin_lock_bh(&txq->axq_lock);
 | 
			
		||||
 		while (!list_empty(&txq->txq_fifo_pending)) {
 | 
			
		||||
@@ -1118,6 +1109,15 @@ void ath_draintxq(struct ath_softc *sc, 
 | 
			
		||||
 		}
 | 
			
		||||
 		spin_unlock_bh(&txq->axq_lock);
 | 
			
		||||
 	}
 | 
			
		||||
+
 | 
			
		||||
+	/* flush any pending frames if aggregation is enabled */
 | 
			
		||||
+	if (sc->sc_flags & SC_OP_TXAGGR) {
 | 
			
		||||
+		if (!retry_tx) {
 | 
			
		||||
+			spin_lock_bh(&txq->axq_lock);
 | 
			
		||||
+			ath_txq_drain_pending_buffers(sc, txq);
 | 
			
		||||
+			spin_unlock_bh(&txq->axq_lock);
 | 
			
		||||
+		}
 | 
			
		||||
+	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
 | 
			
		||||
@ -1,714 +0,0 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
 | 
			
		||||
@@ -195,7 +195,6 @@ enum ATH_AGGR_STATUS {
 | 
			
		||||
 
 | 
			
		||||
 #define ATH_TXFIFO_DEPTH 8
 | 
			
		||||
 struct ath_txq {
 | 
			
		||||
-	int axq_class;
 | 
			
		||||
 	u32 axq_qnum;
 | 
			
		||||
 	u32 *axq_link;
 | 
			
		||||
 	struct list_head axq_q;
 | 
			
		||||
@@ -208,11 +207,12 @@ struct ath_txq {
 | 
			
		||||
 	struct list_head txq_fifo_pending;
 | 
			
		||||
 	u8 txq_headidx;
 | 
			
		||||
 	u8 txq_tailidx;
 | 
			
		||||
+	int pending_frames;
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
 struct ath_atx_ac {
 | 
			
		||||
+	struct ath_txq *txq;
 | 
			
		||||
 	int sched;
 | 
			
		||||
-	int qnum;
 | 
			
		||||
 	struct list_head list;
 | 
			
		||||
 	struct list_head tid_q;
 | 
			
		||||
 };
 | 
			
		||||
@@ -290,12 +290,11 @@ struct ath_tx_control {
 | 
			
		||||
 struct ath_tx {
 | 
			
		||||
 	u16 seq_no;
 | 
			
		||||
 	u32 txqsetup;
 | 
			
		||||
-	int hwq_map[WME_NUM_AC];
 | 
			
		||||
 	spinlock_t txbuflock;
 | 
			
		||||
 	struct list_head txbuf;
 | 
			
		||||
 	struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
 | 
			
		||||
 	struct ath_descdma txdma;
 | 
			
		||||
-	int pending_frames[WME_NUM_AC];
 | 
			
		||||
+	struct ath_txq *txq_map[WME_NUM_AC];
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
 struct ath_rx_edma {
 | 
			
		||||
@@ -325,7 +324,6 @@ void ath_rx_cleanup(struct ath_softc *sc
 | 
			
		||||
 int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
 | 
			
		||||
 struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
 | 
			
		||||
 void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
 | 
			
		||||
-int ath_tx_setup(struct ath_softc *sc, int haltype);
 | 
			
		||||
 void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
 | 
			
		||||
 void ath_draintxq(struct ath_softc *sc,
 | 
			
		||||
 		     struct ath_txq *txq, bool retry_tx);
 | 
			
		||||
@@ -665,7 +663,6 @@ struct ath_wiphy {
 | 
			
		||||
 
 | 
			
		||||
 void ath9k_tasklet(unsigned long data);
 | 
			
		||||
 int ath_reset(struct ath_softc *sc, bool retry_tx);
 | 
			
		||||
-int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
 | 
			
		||||
 int ath_cabq_update(struct ath_softc *);
 | 
			
		||||
 
 | 
			
		||||
 static inline void ath_read_cachesize(struct ath_common *common, int *csz)
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/beacon.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
 | 
			
		||||
@@ -28,7 +28,7 @@ int ath_beaconq_config(struct ath_softc 
 | 
			
		||||
 	struct ath_hw *ah = sc->sc_ah;
 | 
			
		||||
 	struct ath_common *common = ath9k_hw_common(ah);
 | 
			
		||||
 	struct ath9k_tx_queue_info qi, qi_be;
 | 
			
		||||
-	int qnum;
 | 
			
		||||
+	struct ath_txq *txq;
 | 
			
		||||
 
 | 
			
		||||
 	ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
 | 
			
		||||
 	if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
 | 
			
		||||
@@ -38,8 +38,8 @@ int ath_beaconq_config(struct ath_softc 
 | 
			
		||||
 		qi.tqi_cwmax = 0;
 | 
			
		||||
 	} else {
 | 
			
		||||
 		/* Adhoc mode; important thing is to use 2x cwmin. */
 | 
			
		||||
-		qnum = sc->tx.hwq_map[WME_AC_BE];
 | 
			
		||||
-		ath9k_hw_get_txq_props(ah, qnum, &qi_be);
 | 
			
		||||
+		txq = sc->tx.txq_map[WME_AC_BE];
 | 
			
		||||
+		ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
 | 
			
		||||
 		qi.tqi_aifs = qi_be.tqi_aifs;
 | 
			
		||||
 		qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
 | 
			
		||||
 		qi.tqi_cwmax = qi_be.tqi_cwmax;
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/common.h
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/common.h
 | 
			
		||||
@@ -31,10 +31,11 @@
 | 
			
		||||
 #define WME_MAX_BA              WME_BA_BMP_SIZE
 | 
			
		||||
 #define ATH_TID_MAX_BUFS        (2 * WME_MAX_BA)
 | 
			
		||||
 
 | 
			
		||||
-#define WME_AC_BE   0
 | 
			
		||||
-#define WME_AC_BK   1
 | 
			
		||||
-#define WME_AC_VI   2
 | 
			
		||||
-#define WME_AC_VO   3
 | 
			
		||||
+/* These must match mac80211 skb queue mapping numbers */
 | 
			
		||||
+#define WME_AC_VO   0
 | 
			
		||||
+#define WME_AC_VI   1
 | 
			
		||||
+#define WME_AC_BE   2
 | 
			
		||||
+#define WME_AC_BK   3
 | 
			
		||||
 #define WME_NUM_AC  4
 | 
			
		||||
 
 | 
			
		||||
 #define ATH_RSSI_DUMMY_MARKER   0x127
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/main.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
 | 
			
		||||
@@ -331,7 +331,7 @@ void ath_paprd_calibrate(struct work_str
 | 
			
		||||
 	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 ftype;
 | 
			
		||||
 	int chain_ok = 0;
 | 
			
		||||
 	int chain;
 | 
			
		||||
 	int len = 1800;
 | 
			
		||||
@@ -358,8 +358,7 @@ void ath_paprd_calibrate(struct work_str
 | 
			
		||||
 	memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
 | 
			
		||||
 
 | 
			
		||||
 	memset(&txctl, 0, sizeof(txctl));
 | 
			
		||||
-	qnum = sc->tx.hwq_map[WME_AC_BE];
 | 
			
		||||
-	txctl.txq = &sc->tx.txq[qnum];
 | 
			
		||||
+	txctl.txq = sc->tx.txq_map[WME_AC_BE];
 | 
			
		||||
 
 | 
			
		||||
 	ath9k_ps_wakeup(sc);
 | 
			
		||||
 	ar9003_paprd_init_table(ah);
 | 
			
		||||
@@ -1025,56 +1024,6 @@ int ath_reset(struct ath_softc *sc, bool
 | 
			
		||||
 	return r;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
 | 
			
		||||
-{
 | 
			
		||||
-	int qnum;
 | 
			
		||||
-
 | 
			
		||||
-	switch (queue) {
 | 
			
		||||
-	case 0:
 | 
			
		||||
-		qnum = sc->tx.hwq_map[WME_AC_VO];
 | 
			
		||||
-		break;
 | 
			
		||||
-	case 1:
 | 
			
		||||
-		qnum = sc->tx.hwq_map[WME_AC_VI];
 | 
			
		||||
-		break;
 | 
			
		||||
-	case 2:
 | 
			
		||||
-		qnum = sc->tx.hwq_map[WME_AC_BE];
 | 
			
		||||
-		break;
 | 
			
		||||
-	case 3:
 | 
			
		||||
-		qnum = sc->tx.hwq_map[WME_AC_BK];
 | 
			
		||||
-		break;
 | 
			
		||||
-	default:
 | 
			
		||||
-		qnum = sc->tx.hwq_map[WME_AC_BE];
 | 
			
		||||
-		break;
 | 
			
		||||
-	}
 | 
			
		||||
-
 | 
			
		||||
-	return qnum;
 | 
			
		||||
-}
 | 
			
		||||
-
 | 
			
		||||
-int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
 | 
			
		||||
-{
 | 
			
		||||
-	int qnum;
 | 
			
		||||
-
 | 
			
		||||
-	switch (queue) {
 | 
			
		||||
-	case WME_AC_VO:
 | 
			
		||||
-		qnum = 0;
 | 
			
		||||
-		break;
 | 
			
		||||
-	case WME_AC_VI:
 | 
			
		||||
-		qnum = 1;
 | 
			
		||||
-		break;
 | 
			
		||||
-	case WME_AC_BE:
 | 
			
		||||
-		qnum = 2;
 | 
			
		||||
-		break;
 | 
			
		||||
-	case WME_AC_BK:
 | 
			
		||||
-		qnum = 3;
 | 
			
		||||
-		break;
 | 
			
		||||
-	default:
 | 
			
		||||
-		qnum = -1;
 | 
			
		||||
-		break;
 | 
			
		||||
-	}
 | 
			
		||||
-
 | 
			
		||||
-	return qnum;
 | 
			
		||||
-}
 | 
			
		||||
-
 | 
			
		||||
 /* XXX: Remove me once we don't depend on ath9k_channel for all
 | 
			
		||||
  * this redundant data */
 | 
			
		||||
 void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
 | 
			
		||||
@@ -1244,7 +1193,6 @@ static int ath9k_tx(struct ieee80211_hw 
 | 
			
		||||
 	struct ath_tx_control txctl;
 | 
			
		||||
 	int padpos, padsize;
 | 
			
		||||
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 | 
			
		||||
-	int qnum;
 | 
			
		||||
 
 | 
			
		||||
 	if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
 | 
			
		||||
 		ath_print(common, ATH_DBG_XMIT,
 | 
			
		||||
@@ -1317,8 +1265,7 @@ static int ath9k_tx(struct ieee80211_hw 
 | 
			
		||||
 		memmove(skb->data, skb->data + padsize, padpos);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
 | 
			
		||||
-	txctl.txq = &sc->tx.txq[qnum];
 | 
			
		||||
+	txctl.txq = sc->tx.txq_map[skb_get_queue_mapping(skb)];
 | 
			
		||||
 
 | 
			
		||||
 	ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
 | 
			
		||||
 
 | 
			
		||||
@@ -1802,12 +1749,15 @@ static int ath9k_conf_tx(struct ieee8021
 | 
			
		||||
 	struct ath_wiphy *aphy = hw->priv;
 | 
			
		||||
 	struct ath_softc *sc = aphy->sc;
 | 
			
		||||
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 | 
			
		||||
+	struct ath_txq *txq;
 | 
			
		||||
 	struct ath9k_tx_queue_info qi;
 | 
			
		||||
-	int ret = 0, qnum;
 | 
			
		||||
+	int ret = 0;
 | 
			
		||||
 
 | 
			
		||||
 	if (queue >= WME_NUM_AC)
 | 
			
		||||
 		return 0;
 | 
			
		||||
 
 | 
			
		||||
+	txq = sc->tx.txq_map[queue];
 | 
			
		||||
+
 | 
			
		||||
 	mutex_lock(&sc->mutex);
 | 
			
		||||
 
 | 
			
		||||
 	memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
 | 
			
		||||
@@ -1816,20 +1766,19 @@ static int ath9k_conf_tx(struct ieee8021
 | 
			
		||||
 	qi.tqi_cwmin = params->cw_min;
 | 
			
		||||
 	qi.tqi_cwmax = params->cw_max;
 | 
			
		||||
 	qi.tqi_burstTime = params->txop;
 | 
			
		||||
-	qnum = ath_get_hal_qnum(queue, sc);
 | 
			
		||||
 
 | 
			
		||||
 	ath_print(common, ATH_DBG_CONFIG,
 | 
			
		||||
 		  "Configure tx [queue/halq] [%d/%d],  "
 | 
			
		||||
 		  "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
 | 
			
		||||
-		  queue, qnum, params->aifs, params->cw_min,
 | 
			
		||||
+		  queue, txq->axq_qnum, params->aifs, params->cw_min,
 | 
			
		||||
 		  params->cw_max, params->txop);
 | 
			
		||||
 
 | 
			
		||||
-	ret = ath_txq_update(sc, qnum, &qi);
 | 
			
		||||
+	ret = ath_txq_update(sc, txq->axq_qnum, &qi);
 | 
			
		||||
 	if (ret)
 | 
			
		||||
 		ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n");
 | 
			
		||||
 
 | 
			
		||||
 	if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)
 | 
			
		||||
-		if ((qnum == sc->tx.hwq_map[WME_AC_BE]) && !ret)
 | 
			
		||||
+		if (queue == WME_AC_BE && !ret)
 | 
			
		||||
 			ath_beaconq_config(sc);
 | 
			
		||||
 
 | 
			
		||||
 	mutex_unlock(&sc->mutex);
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
 | 
			
		||||
@@ -124,7 +124,7 @@ static void ath_tx_queue_tid(struct ath_
 | 
			
		||||
 
 | 
			
		||||
 static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
 | 
			
		||||
 {
 | 
			
		||||
-	struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
 | 
			
		||||
+	struct ath_txq *txq = tid->ac->txq;
 | 
			
		||||
 
 | 
			
		||||
 	WARN_ON(!tid->paused);
 | 
			
		||||
 
 | 
			
		||||
@@ -142,7 +142,7 @@ unlock:
 | 
			
		||||
 
 | 
			
		||||
 static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
 | 
			
		||||
 {
 | 
			
		||||
-	struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
 | 
			
		||||
+	struct ath_txq *txq = tid->ac->txq;
 | 
			
		||||
 	struct ath_buf *bf;
 | 
			
		||||
 	struct list_head bf_head;
 | 
			
		||||
 	struct ath_tx_status ts;
 | 
			
		||||
@@ -817,7 +817,7 @@ void ath_tx_aggr_stop(struct ath_softc *
 | 
			
		||||
 {
 | 
			
		||||
 	struct ath_node *an = (struct ath_node *)sta->drv_priv;
 | 
			
		||||
 	struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
 | 
			
		||||
-	struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
 | 
			
		||||
+	struct ath_txq *txq = txtid->ac->txq;
 | 
			
		||||
 
 | 
			
		||||
 	if (txtid->state & AGGR_CLEANUP)
 | 
			
		||||
 		return;
 | 
			
		||||
@@ -888,10 +888,16 @@ struct ath_txq *ath_txq_setup(struct ath
 | 
			
		||||
 	struct ath_hw *ah = sc->sc_ah;
 | 
			
		||||
 	struct ath_common *common = ath9k_hw_common(ah);
 | 
			
		||||
 	struct ath9k_tx_queue_info qi;
 | 
			
		||||
+	static const int subtype_txq_to_hwq[] = {
 | 
			
		||||
+		[WME_AC_BE] = ATH_TXQ_AC_BE,
 | 
			
		||||
+		[WME_AC_BK] = ATH_TXQ_AC_BK,
 | 
			
		||||
+		[WME_AC_VI] = ATH_TXQ_AC_VI,
 | 
			
		||||
+		[WME_AC_VO] = ATH_TXQ_AC_VO,
 | 
			
		||||
+	};
 | 
			
		||||
 	int qnum, i;
 | 
			
		||||
 
 | 
			
		||||
 	memset(&qi, 0, sizeof(qi));
 | 
			
		||||
-	qi.tqi_subtype = subtype;
 | 
			
		||||
+	qi.tqi_subtype = subtype_txq_to_hwq[subtype];
 | 
			
		||||
 	qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
 | 
			
		||||
 	qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
 | 
			
		||||
 	qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
 | 
			
		||||
@@ -940,7 +946,6 @@ struct ath_txq *ath_txq_setup(struct ath
 | 
			
		||||
 	if (!ATH_TXQ_SETUP(sc, qnum)) {
 | 
			
		||||
 		struct ath_txq *txq = &sc->tx.txq[qnum];
 | 
			
		||||
 
 | 
			
		||||
-		txq->axq_class = subtype;
 | 
			
		||||
 		txq->axq_qnum = qnum;
 | 
			
		||||
 		txq->axq_link = NULL;
 | 
			
		||||
 		INIT_LIST_HEAD(&txq->axq_q);
 | 
			
		||||
@@ -1210,24 +1215,6 @@ void ath_txq_schedule(struct ath_softc *
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-int ath_tx_setup(struct ath_softc *sc, int haltype)
 | 
			
		||||
-{
 | 
			
		||||
-	struct ath_txq *txq;
 | 
			
		||||
-
 | 
			
		||||
-	if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
 | 
			
		||||
-		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
 | 
			
		||||
-			  "HAL AC %u out of range, max %zu!\n",
 | 
			
		||||
-			 haltype, ARRAY_SIZE(sc->tx.hwq_map));
 | 
			
		||||
-		return 0;
 | 
			
		||||
-	}
 | 
			
		||||
-	txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype);
 | 
			
		||||
-	if (txq != NULL) {
 | 
			
		||||
-		sc->tx.hwq_map[haltype] = txq->axq_qnum;
 | 
			
		||||
-		return 1;
 | 
			
		||||
-	} else
 | 
			
		||||
-		return 0;
 | 
			
		||||
-}
 | 
			
		||||
-
 | 
			
		||||
 /***********/
 | 
			
		||||
 /* TX, DMA */
 | 
			
		||||
 /***********/
 | 
			
		||||
@@ -1708,6 +1695,7 @@ static void ath_tx_start_dma(struct ath_
 | 
			
		||||
 			goto tx_done;
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
+		WARN_ON(tid->ac->txq != txctl->txq);
 | 
			
		||||
 		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
 | 
			
		||||
 			/*
 | 
			
		||||
 			 * Try aggregation if it's a unicast data frame
 | 
			
		||||
@@ -1747,6 +1735,7 @@ int ath_tx_start(struct ieee80211_hw *hw
 | 
			
		||||
 		return -1;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	q = skb_get_queue_mapping(skb);
 | 
			
		||||
 	r = ath_tx_setup_buffer(hw, bf, skb, txctl);
 | 
			
		||||
 	if (unlikely(r)) {
 | 
			
		||||
 		ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n");
 | 
			
		||||
@@ -1756,8 +1745,9 @@ int ath_tx_start(struct ieee80211_hw *hw
 | 
			
		||||
 		 * we will at least have to run TX completionon one buffer
 | 
			
		||||
 		 * on the queue */
 | 
			
		||||
 		spin_lock_bh(&txq->axq_lock);
 | 
			
		||||
-		if (!txq->stopped && txq->axq_depth > 1) {
 | 
			
		||||
-			ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
 | 
			
		||||
+		if (txq == sc->tx.txq_map[q] && !txq->stopped &&
 | 
			
		||||
+		    txq->axq_depth > 1) {
 | 
			
		||||
+			ath_mac80211_stop_queue(sc, q);
 | 
			
		||||
 			txq->stopped = 1;
 | 
			
		||||
 		}
 | 
			
		||||
 		spin_unlock_bh(&txq->axq_lock);
 | 
			
		||||
@@ -1767,13 +1757,10 @@ int ath_tx_start(struct ieee80211_hw *hw
 | 
			
		||||
 		return r;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	q = skb_get_queue_mapping(skb);
 | 
			
		||||
-	if (q >= 4)
 | 
			
		||||
-		q = 0;
 | 
			
		||||
-
 | 
			
		||||
 	spin_lock_bh(&txq->axq_lock);
 | 
			
		||||
-	if (++sc->tx.pending_frames[q] > ATH_MAX_QDEPTH && !txq->stopped) {
 | 
			
		||||
-		ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
 | 
			
		||||
+	if (txq == sc->tx.txq_map[q] &&
 | 
			
		||||
+	    ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
 | 
			
		||||
+		ath_mac80211_stop_queue(sc, q);
 | 
			
		||||
 		txq->stopped = 1;
 | 
			
		||||
 	}
 | 
			
		||||
 	spin_unlock_bh(&txq->axq_lock);
 | 
			
		||||
@@ -1841,7 +1828,8 @@ exit:
 | 
			
		||||
 /*****************/
 | 
			
		||||
 
 | 
			
		||||
 static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
 | 
			
		||||
-			    struct ath_wiphy *aphy, int tx_flags)
 | 
			
		||||
+			    struct ath_wiphy *aphy, int tx_flags,
 | 
			
		||||
+			    struct ath_txq *txq)
 | 
			
		||||
 {
 | 
			
		||||
 	struct ieee80211_hw *hw = sc->hw;
 | 
			
		||||
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 | 
			
		||||
@@ -1888,11 +1876,12 @@ static void ath_tx_complete(struct ath_s
 | 
			
		||||
 		ath9k_tx_status(hw, skb);
 | 
			
		||||
 	else {
 | 
			
		||||
 		q = skb_get_queue_mapping(skb);
 | 
			
		||||
-		if (q >= 4)
 | 
			
		||||
-			q = 0;
 | 
			
		||||
-
 | 
			
		||||
-		if (--sc->tx.pending_frames[q] < 0)
 | 
			
		||||
-			sc->tx.pending_frames[q] = 0;
 | 
			
		||||
+		if (txq == sc->tx.txq_map[q]) {
 | 
			
		||||
+			spin_lock_bh(&txq->axq_lock);
 | 
			
		||||
+			if (WARN_ON(--txq->pending_frames < 0))
 | 
			
		||||
+				txq->pending_frames = 0;
 | 
			
		||||
+			spin_unlock_bh(&txq->axq_lock);
 | 
			
		||||
+		}
 | 
			
		||||
 
 | 
			
		||||
 		ieee80211_tx_status(hw, skb);
 | 
			
		||||
 	}
 | 
			
		||||
@@ -1927,8 +1916,8 @@ static void ath_tx_complete_buf(struct a
 | 
			
		||||
 		else
 | 
			
		||||
 			complete(&sc->paprd_complete);
 | 
			
		||||
 	} else {
 | 
			
		||||
-		ath_debug_stat_tx(sc, txq, bf, ts);
 | 
			
		||||
-		ath_tx_complete(sc, skb, bf->aphy, tx_flags);
 | 
			
		||||
+		ath_debug_stat_tx(sc, bf, ts);
 | 
			
		||||
+		ath_tx_complete(sc, skb, bf->aphy, tx_flags, txq);
 | 
			
		||||
 	}
 | 
			
		||||
 	/* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
 | 
			
		||||
 	 * accidentally reference it later.
 | 
			
		||||
@@ -2018,16 +2007,13 @@ static void ath_tx_rc_status(struct ath_
 | 
			
		||||
 	tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
 | 
			
		||||
+static void ath_wake_mac80211_queue(struct ath_softc *sc, int qnum)
 | 
			
		||||
 {
 | 
			
		||||
-	int qnum;
 | 
			
		||||
-
 | 
			
		||||
-	qnum = ath_get_mac80211_qnum(txq->axq_class, sc);
 | 
			
		||||
-	if (qnum == -1)
 | 
			
		||||
-		return;
 | 
			
		||||
+	struct ath_txq *txq;
 | 
			
		||||
 
 | 
			
		||||
+	txq = sc->tx.txq_map[qnum];
 | 
			
		||||
 	spin_lock_bh(&txq->axq_lock);
 | 
			
		||||
-	if (txq->stopped && sc->tx.pending_frames[qnum] < ATH_MAX_QDEPTH) {
 | 
			
		||||
+	if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
 | 
			
		||||
 		if (ath_mac80211_start_queue(sc, qnum))
 | 
			
		||||
 			txq->stopped = 0;
 | 
			
		||||
 	}
 | 
			
		||||
@@ -2044,6 +2030,7 @@ static void ath_tx_processq(struct ath_s
 | 
			
		||||
 	struct ath_tx_status ts;
 | 
			
		||||
 	int txok;
 | 
			
		||||
 	int status;
 | 
			
		||||
+	int qnum;
 | 
			
		||||
 
 | 
			
		||||
 	ath_print(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
 | 
			
		||||
 		  txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
 | 
			
		||||
@@ -2119,12 +2106,15 @@ static void ath_tx_processq(struct ath_s
 | 
			
		||||
 			ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true);
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
+		qnum = skb_get_queue_mapping(bf->bf_mpdu);
 | 
			
		||||
+
 | 
			
		||||
 		if (bf_isampdu(bf))
 | 
			
		||||
 			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok);
 | 
			
		||||
 		else
 | 
			
		||||
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
 | 
			
		||||
 
 | 
			
		||||
-		ath_wake_mac80211_queue(sc, txq);
 | 
			
		||||
+		if (txq == sc->tx.txq_map[qnum])
 | 
			
		||||
+			ath_wake_mac80211_queue(sc, qnum);
 | 
			
		||||
 
 | 
			
		||||
 		spin_lock_bh(&txq->axq_lock);
 | 
			
		||||
 		if (sc->sc_flags & SC_OP_TXAGGR)
 | 
			
		||||
@@ -2194,6 +2184,7 @@ void ath_tx_edma_tasklet(struct ath_soft
 | 
			
		||||
 	struct list_head bf_head;
 | 
			
		||||
 	int status;
 | 
			
		||||
 	int txok;
 | 
			
		||||
+	int qnum;
 | 
			
		||||
 
 | 
			
		||||
 	for (;;) {
 | 
			
		||||
 		status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
 | 
			
		||||
@@ -2237,13 +2228,16 @@ void ath_tx_edma_tasklet(struct ath_soft
 | 
			
		||||
 			ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true);
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
+		qnum = skb_get_queue_mapping(bf->bf_mpdu);
 | 
			
		||||
+
 | 
			
		||||
 		if (bf_isampdu(bf))
 | 
			
		||||
 			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, txok);
 | 
			
		||||
 		else
 | 
			
		||||
 			ath_tx_complete_buf(sc, bf, txq, &bf_head,
 | 
			
		||||
 					    &txs, txok, 0);
 | 
			
		||||
 
 | 
			
		||||
-		ath_wake_mac80211_queue(sc, txq);
 | 
			
		||||
+		if (txq == sc->tx.txq_map[qnum])
 | 
			
		||||
+			ath_wake_mac80211_queue(sc, qnum);
 | 
			
		||||
 
 | 
			
		||||
 		spin_lock_bh(&txq->axq_lock);
 | 
			
		||||
 		if (!list_empty(&txq->txq_fifo_pending)) {
 | 
			
		||||
@@ -2375,7 +2369,7 @@ void ath_tx_node_init(struct ath_softc *
 | 
			
		||||
 	for (acno = 0, ac = &an->ac[acno];
 | 
			
		||||
 	     acno < WME_NUM_AC; acno++, ac++) {
 | 
			
		||||
 		ac->sched    = false;
 | 
			
		||||
-		ac->qnum = sc->tx.hwq_map[acno];
 | 
			
		||||
+		ac->txq = sc->tx.txq_map[acno];
 | 
			
		||||
 		INIT_LIST_HEAD(&ac->tid_q);
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
@@ -2385,17 +2379,13 @@ void ath_tx_node_cleanup(struct ath_soft
 | 
			
		||||
 	struct ath_atx_ac *ac;
 | 
			
		||||
 	struct ath_atx_tid *tid;
 | 
			
		||||
 	struct ath_txq *txq;
 | 
			
		||||
-	int i, tidno;
 | 
			
		||||
+	int tidno;
 | 
			
		||||
 
 | 
			
		||||
 	for (tidno = 0, tid = &an->tid[tidno];
 | 
			
		||||
 	     tidno < WME_NUM_TID; tidno++, tid++) {
 | 
			
		||||
-		i = tid->ac->qnum;
 | 
			
		||||
-
 | 
			
		||||
-		if (!ATH_TXQ_SETUP(sc, i))
 | 
			
		||||
-			continue;
 | 
			
		||||
 
 | 
			
		||||
-		txq = &sc->tx.txq[i];
 | 
			
		||||
 		ac = tid->ac;
 | 
			
		||||
+		txq = ac->txq;
 | 
			
		||||
 
 | 
			
		||||
 		spin_lock_bh(&txq->axq_lock);
 | 
			
		||||
 
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
 | 
			
		||||
@@ -157,6 +157,13 @@
 | 
			
		||||
 #define PAPRD_GAIN_TABLE_ENTRIES    32
 | 
			
		||||
 #define PAPRD_TABLE_SZ              24
 | 
			
		||||
 
 | 
			
		||||
+enum ath_hw_txq_subtype {
 | 
			
		||||
+	ATH_TXQ_AC_BE = 0,
 | 
			
		||||
+	ATH_TXQ_AC_BK = 1,
 | 
			
		||||
+	ATH_TXQ_AC_VI = 2,
 | 
			
		||||
+	ATH_TXQ_AC_VO = 3,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
 enum ath_ini_subsys {
 | 
			
		||||
 	ATH_INI_PRE = 0,
 | 
			
		||||
 	ATH_INI_CORE,
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
 | 
			
		||||
@@ -20,8 +20,15 @@
 | 
			
		||||
 /* TX */
 | 
			
		||||
 /******/
 | 
			
		||||
 
 | 
			
		||||
+static const int subtype_txq_to_hwq[] = {
 | 
			
		||||
+	[WME_AC_BE] = ATH_TXQ_AC_BE,
 | 
			
		||||
+	[WME_AC_BK] = ATH_TXQ_AC_BK,
 | 
			
		||||
+	[WME_AC_VI] = ATH_TXQ_AC_VI,
 | 
			
		||||
+	[WME_AC_VO] = ATH_TXQ_AC_VO,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
 #define ATH9K_HTC_INIT_TXQ(subtype) do {			\
 | 
			
		||||
-		qi.tqi_subtype = subtype;			\
 | 
			
		||||
+		qi.tqi_subtype = subtype_txq_to_hwq[subtype];	\
 | 
			
		||||
 		qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;		\
 | 
			
		||||
 		qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;		\
 | 
			
		||||
 		qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;		\
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/init.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
 | 
			
		||||
@@ -396,7 +396,8 @@ static void ath9k_init_crypto(struct ath
 | 
			
		||||
 
 | 
			
		||||
 static int ath9k_init_btcoex(struct ath_softc *sc)
 | 
			
		||||
 {
 | 
			
		||||
-	int r, qnum;
 | 
			
		||||
+	struct ath_txq *txq;
 | 
			
		||||
+	int r;
 | 
			
		||||
 
 | 
			
		||||
 	switch (sc->sc_ah->btcoex_hw.scheme) {
 | 
			
		||||
 	case ATH_BTCOEX_CFG_NONE:
 | 
			
		||||
@@ -409,8 +410,8 @@ static int ath9k_init_btcoex(struct ath_
 | 
			
		||||
 		r = ath_init_btcoex_timer(sc);
 | 
			
		||||
 		if (r)
 | 
			
		||||
 			return -1;
 | 
			
		||||
-		qnum = sc->tx.hwq_map[WME_AC_BE];
 | 
			
		||||
-		ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum);
 | 
			
		||||
+		txq = sc->tx.txq_map[WME_AC_BE];
 | 
			
		||||
+		ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
 | 
			
		||||
 		sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
 | 
			
		||||
 		break;
 | 
			
		||||
 	default:
 | 
			
		||||
@@ -423,59 +424,18 @@ static int ath9k_init_btcoex(struct ath_
 | 
			
		||||
 
 | 
			
		||||
 static int ath9k_init_queues(struct ath_softc *sc)
 | 
			
		||||
 {
 | 
			
		||||
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 | 
			
		||||
 	int i = 0;
 | 
			
		||||
 
 | 
			
		||||
-	for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++)
 | 
			
		||||
-		sc->tx.hwq_map[i] = -1;
 | 
			
		||||
-
 | 
			
		||||
 	sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
 | 
			
		||||
-	if (sc->beacon.beaconq == -1) {
 | 
			
		||||
-		ath_print(common, ATH_DBG_FATAL,
 | 
			
		||||
-			  "Unable to setup a beacon xmit queue\n");
 | 
			
		||||
-		goto err;
 | 
			
		||||
-	}
 | 
			
		||||
-
 | 
			
		||||
 	sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
 | 
			
		||||
-	if (sc->beacon.cabq == NULL) {
 | 
			
		||||
-		ath_print(common, ATH_DBG_FATAL,
 | 
			
		||||
-			  "Unable to setup CAB xmit queue\n");
 | 
			
		||||
-		goto err;
 | 
			
		||||
-	}
 | 
			
		||||
 
 | 
			
		||||
 	sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
 | 
			
		||||
 	ath_cabq_update(sc);
 | 
			
		||||
 
 | 
			
		||||
-	if (!ath_tx_setup(sc, WME_AC_BK)) {
 | 
			
		||||
-		ath_print(common, ATH_DBG_FATAL,
 | 
			
		||||
-			  "Unable to setup xmit queue for BK traffic\n");
 | 
			
		||||
-		goto err;
 | 
			
		||||
-	}
 | 
			
		||||
-
 | 
			
		||||
-	if (!ath_tx_setup(sc, WME_AC_BE)) {
 | 
			
		||||
-		ath_print(common, ATH_DBG_FATAL,
 | 
			
		||||
-			  "Unable to setup xmit queue for BE traffic\n");
 | 
			
		||||
-		goto err;
 | 
			
		||||
-	}
 | 
			
		||||
-	if (!ath_tx_setup(sc, WME_AC_VI)) {
 | 
			
		||||
-		ath_print(common, ATH_DBG_FATAL,
 | 
			
		||||
-			  "Unable to setup xmit queue for VI traffic\n");
 | 
			
		||||
-		goto err;
 | 
			
		||||
-	}
 | 
			
		||||
-	if (!ath_tx_setup(sc, WME_AC_VO)) {
 | 
			
		||||
-		ath_print(common, ATH_DBG_FATAL,
 | 
			
		||||
-			  "Unable to setup xmit queue for VO traffic\n");
 | 
			
		||||
-		goto err;
 | 
			
		||||
-	}
 | 
			
		||||
+	for (i = 0; i < WME_NUM_AC; i++)
 | 
			
		||||
+		sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
-
 | 
			
		||||
-err:
 | 
			
		||||
-	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
 | 
			
		||||
-		if (ATH_TXQ_SETUP(sc, i))
 | 
			
		||||
-			ath_tx_cleanupq(sc, &sc->tx.txq[i]);
 | 
			
		||||
-
 | 
			
		||||
-	return -EIO;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static int ath9k_init_channels_rates(struct ath_softc *sc)
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/virtual.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/virtual.c
 | 
			
		||||
@@ -187,7 +187,7 @@ static int ath9k_send_nullfunc(struct at
 | 
			
		||||
 	info->control.rates[1].idx = -1;
 | 
			
		||||
 
 | 
			
		||||
 	memset(&txctl, 0, sizeof(struct ath_tx_control));
 | 
			
		||||
-	txctl.txq = &sc->tx.txq[sc->tx.hwq_map[WME_AC_VO]];
 | 
			
		||||
+	txctl.txq = sc->tx.txq_map[WME_AC_VO];
 | 
			
		||||
 	txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE;
 | 
			
		||||
 
 | 
			
		||||
 	if (ath_tx_start(aphy->hw, skb, &txctl) != 0)
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
 | 
			
		||||
@@ -579,10 +579,10 @@ static const struct file_operations fops
 | 
			
		||||
 	do {								\
 | 
			
		||||
 		len += snprintf(buf + len, size - len,			\
 | 
			
		||||
 				"%s%13u%11u%10u%10u\n", str,		\
 | 
			
		||||
-		sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BE]].elem, \
 | 
			
		||||
-		sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BK]].elem, \
 | 
			
		||||
-		sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VI]].elem, \
 | 
			
		||||
-		sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VO]].elem); \
 | 
			
		||||
+		sc->debug.stats.txstats[WME_AC_BE].elem, \
 | 
			
		||||
+		sc->debug.stats.txstats[WME_AC_BK].elem, \
 | 
			
		||||
+		sc->debug.stats.txstats[WME_AC_VI].elem, \
 | 
			
		||||
+		sc->debug.stats.txstats[WME_AC_VO].elem); \
 | 
			
		||||
 } while(0)
 | 
			
		||||
 
 | 
			
		||||
 static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
 | 
			
		||||
@@ -624,33 +624,35 @@ static ssize_t read_file_xmit(struct fil
 | 
			
		||||
 	return retval;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
 | 
			
		||||
-		       struct ath_buf *bf, struct ath_tx_status *ts)
 | 
			
		||||
+void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
 | 
			
		||||
+		       struct ath_tx_status *ts)
 | 
			
		||||
 {
 | 
			
		||||
-	TX_STAT_INC(txq->axq_qnum, tx_pkts_all);
 | 
			
		||||
-	sc->debug.stats.txstats[txq->axq_qnum].tx_bytes_all += bf->bf_mpdu->len;
 | 
			
		||||
+	int qnum = skb_get_queue_mapping(bf->bf_mpdu);
 | 
			
		||||
+
 | 
			
		||||
+	TX_STAT_INC(qnum, tx_pkts_all);
 | 
			
		||||
+	sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
 | 
			
		||||
 
 | 
			
		||||
 	if (bf_isampdu(bf)) {
 | 
			
		||||
 		if (bf_isxretried(bf))
 | 
			
		||||
-			TX_STAT_INC(txq->axq_qnum, a_xretries);
 | 
			
		||||
+			TX_STAT_INC(qnum, a_xretries);
 | 
			
		||||
 		else
 | 
			
		||||
-			TX_STAT_INC(txq->axq_qnum, a_completed);
 | 
			
		||||
+			TX_STAT_INC(qnum, a_completed);
 | 
			
		||||
 	} else {
 | 
			
		||||
-		TX_STAT_INC(txq->axq_qnum, completed);
 | 
			
		||||
+		TX_STAT_INC(qnum, completed);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	if (ts->ts_status & ATH9K_TXERR_FIFO)
 | 
			
		||||
-		TX_STAT_INC(txq->axq_qnum, fifo_underrun);
 | 
			
		||||
+		TX_STAT_INC(qnum, fifo_underrun);
 | 
			
		||||
 	if (ts->ts_status & ATH9K_TXERR_XTXOP)
 | 
			
		||||
-		TX_STAT_INC(txq->axq_qnum, xtxop);
 | 
			
		||||
+		TX_STAT_INC(qnum, xtxop);
 | 
			
		||||
 	if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED)
 | 
			
		||||
-		TX_STAT_INC(txq->axq_qnum, timer_exp);
 | 
			
		||||
+		TX_STAT_INC(qnum, timer_exp);
 | 
			
		||||
 	if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR)
 | 
			
		||||
-		TX_STAT_INC(txq->axq_qnum, desc_cfg_err);
 | 
			
		||||
+		TX_STAT_INC(qnum, desc_cfg_err);
 | 
			
		||||
 	if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN)
 | 
			
		||||
-		TX_STAT_INC(txq->axq_qnum, data_underrun);
 | 
			
		||||
+		TX_STAT_INC(qnum, data_underrun);
 | 
			
		||||
 	if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
 | 
			
		||||
-		TX_STAT_INC(txq->axq_qnum, delim_underrun);
 | 
			
		||||
+		TX_STAT_INC(qnum, delim_underrun);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static const struct file_operations fops_xmit = {
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/debug.h
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/debug.h
 | 
			
		||||
@@ -169,8 +169,8 @@ void ath9k_exit_debug(struct ath_hw *ah)
 | 
			
		||||
 int ath9k_debug_create_root(void);
 | 
			
		||||
 void ath9k_debug_remove_root(void);
 | 
			
		||||
 void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
 | 
			
		||||
-void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
 | 
			
		||||
-		       struct ath_buf *bf, struct ath_tx_status *ts);
 | 
			
		||||
+void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
 | 
			
		||||
+		       struct ath_tx_status *ts);
 | 
			
		||||
 void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
 | 
			
		||||
 
 | 
			
		||||
 #else
 | 
			
		||||
@@ -199,7 +199,6 @@ static inline void ath_debug_stat_interr
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static inline void ath_debug_stat_tx(struct ath_softc *sc,
 | 
			
		||||
-				     struct ath_txq *txq,
 | 
			
		||||
 				     struct ath_buf *bf,
 | 
			
		||||
 				     struct ath_tx_status *ts)
 | 
			
		||||
 {
 | 
			
		||||
@ -1,58 +0,0 @@
 | 
			
		||||
--- a/include/linux/nl80211.h
 | 
			
		||||
+++ b/include/linux/nl80211.h
 | 
			
		||||
@@ -804,6 +804,8 @@ enum nl80211_commands {
 | 
			
		||||
  * @NL80211_ATTR_SUPPORT_IBSS_RSN: The device supports IBSS RSN, which mostly
 | 
			
		||||
  *	means support for per-station GTKs.
 | 
			
		||||
  *
 | 
			
		||||
+ * @NL80211_ATTR_MCAST_RATE: Multicast tx rate (in 100 kbps) for IBSS
 | 
			
		||||
+ *
 | 
			
		||||
  * @NL80211_ATTR_MAX: highest attribute number currently defined
 | 
			
		||||
  * @__NL80211_ATTR_AFTER_LAST: internal use
 | 
			
		||||
  */
 | 
			
		||||
@@ -973,6 +975,8 @@ enum nl80211_attrs {
 | 
			
		||||
 
 | 
			
		||||
 	NL80211_ATTR_SUPPORT_IBSS_RSN,
 | 
			
		||||
 
 | 
			
		||||
+	NL80211_ATTR_MCAST_RATE,
 | 
			
		||||
+
 | 
			
		||||
 	/* add attributes here, update the policy in nl80211.c */
 | 
			
		||||
 
 | 
			
		||||
 	__NL80211_ATTR_AFTER_LAST,
 | 
			
		||||
--- a/include/net/cfg80211.h
 | 
			
		||||
+++ b/include/net/cfg80211.h
 | 
			
		||||
@@ -924,6 +924,7 @@ struct cfg80211_disassoc_request {
 | 
			
		||||
  * @privacy: this is a protected network, keys will be configured
 | 
			
		||||
  *	after joining
 | 
			
		||||
  * @basic_rates: bitmap of basic rates to use when creating the IBSS
 | 
			
		||||
+ * @mcast_rate: multicast tx rate (in 100 kbps)
 | 
			
		||||
  */
 | 
			
		||||
 struct cfg80211_ibss_params {
 | 
			
		||||
 	u8 *ssid;
 | 
			
		||||
@@ -935,6 +936,7 @@ struct cfg80211_ibss_params {
 | 
			
		||||
 	u32 basic_rates;
 | 
			
		||||
 	bool channel_fixed;
 | 
			
		||||
 	bool privacy;
 | 
			
		||||
+	int mcast_rate;
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
--- a/net/wireless/nl80211.c
 | 
			
		||||
+++ b/net/wireless/nl80211.c
 | 
			
		||||
@@ -167,6 +167,7 @@ static const struct nla_policy nl80211_p
 | 
			
		||||
 	[NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
 | 
			
		||||
 	[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
 | 
			
		||||
 	[NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
 | 
			
		||||
+	[NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
 /* policy for the key attributes */
 | 
			
		||||
@@ -3652,6 +3653,9 @@ static int nl80211_join_ibss(struct sk_b
 | 
			
		||||
 				return -EINVAL;
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
+	if (info->attrs[NL80211_ATTR_MCAST_RATE])
 | 
			
		||||
+		ibss.mcast_rate =
 | 
			
		||||
+			nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]);
 | 
			
		||||
 
 | 
			
		||||
 	if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
 | 
			
		||||
 		connkeys = nl80211_parse_connkeys(rdev,
 | 
			
		||||
@ -1,106 +0,0 @@
 | 
			
		||||
--- a/net/mac80211/ibss.c
 | 
			
		||||
+++ b/net/mac80211/ibss.c
 | 
			
		||||
@@ -914,6 +914,7 @@ int ieee80211_ibss_join(struct ieee80211
 | 
			
		||||
 
 | 
			
		||||
 	sdata->u.ibss.privacy = params->privacy;
 | 
			
		||||
 	sdata->u.ibss.basic_rates = params->basic_rates;
 | 
			
		||||
+	sdata->vif.bss_conf.mcast_rate = params->mcast_rate;
 | 
			
		||||
 
 | 
			
		||||
 	sdata->vif.bss_conf.beacon_int = params->beacon_interval;
 | 
			
		||||
 
 | 
			
		||||
--- a/include/net/mac80211.h
 | 
			
		||||
+++ b/include/net/mac80211.h
 | 
			
		||||
@@ -244,6 +244,7 @@ struct ieee80211_bss_conf {
 | 
			
		||||
 	u16 assoc_capability;
 | 
			
		||||
 	u64 timestamp;
 | 
			
		||||
 	u32 basic_rates;
 | 
			
		||||
+	u32 mcast_rate;
 | 
			
		||||
 	u16 ht_operation_mode;
 | 
			
		||||
 	s32 cqm_rssi_thold;
 | 
			
		||||
 	u32 cqm_rssi_hyst;
 | 
			
		||||
@@ -2644,7 +2645,7 @@ enum rate_control_changed {
 | 
			
		||||
  * @rate_idx_mask: user-requested rate mask (not MCS for now)
 | 
			
		||||
  * @skb: the skb that will be transmitted, the control information in it needs
 | 
			
		||||
  *	to be filled in
 | 
			
		||||
- * @ap: whether this frame is sent out in AP mode
 | 
			
		||||
+ * @bss: whether this frame is sent out in AP or IBSS mode
 | 
			
		||||
  */
 | 
			
		||||
 struct ieee80211_tx_rate_control {
 | 
			
		||||
 	struct ieee80211_hw *hw;
 | 
			
		||||
@@ -2655,7 +2656,7 @@ struct ieee80211_tx_rate_control {
 | 
			
		||||
 	bool rts, short_preamble;
 | 
			
		||||
 	u8 max_rate_idx;
 | 
			
		||||
 	u32 rate_idx_mask;
 | 
			
		||||
-	bool ap;
 | 
			
		||||
+	bool bss;
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
 struct rate_control_ops {
 | 
			
		||||
--- a/net/mac80211/rate.c
 | 
			
		||||
+++ b/net/mac80211/rate.c
 | 
			
		||||
@@ -210,10 +210,20 @@ static bool rc_no_data_or_no_ack(struct 
 | 
			
		||||
 	return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc));
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, u8 max_rate_idx)
 | 
			
		||||
+static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, u32 mcast_rate,
 | 
			
		||||
+				  struct ieee80211_supported_band *sband)
 | 
			
		||||
 {
 | 
			
		||||
 	u8 i;
 | 
			
		||||
 
 | 
			
		||||
+	if (mcast_rate) {
 | 
			
		||||
+		for (i = 0; i < sband->n_bitrates; i++) {
 | 
			
		||||
+			if (sband->bitrates[i].bitrate == mcast_rate) {
 | 
			
		||||
+				*idx = i;
 | 
			
		||||
+				return;
 | 
			
		||||
+			}
 | 
			
		||||
+		}
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
 	if (basic_rates == 0)
 | 
			
		||||
 		return; /* assume basic rates unknown and accept rate */
 | 
			
		||||
 	if (*idx < 0)
 | 
			
		||||
@@ -221,7 +231,7 @@ static void rc_send_low_broadcast(s8 *id
 | 
			
		||||
 	if (basic_rates & (1 << *idx))
 | 
			
		||||
 		return; /* selected rate is a basic rate */
 | 
			
		||||
 
 | 
			
		||||
-	for (i = *idx + 1; i <= max_rate_idx; i++) {
 | 
			
		||||
+	for (i = *idx + 1; i <= sband->n_bitrates; i++) {
 | 
			
		||||
 		if (basic_rates & (1 << i)) {
 | 
			
		||||
 			*idx = i;
 | 
			
		||||
 			return;
 | 
			
		||||
@@ -242,10 +252,11 @@ bool rate_control_send_low(struct ieee80
 | 
			
		||||
 		info->control.rates[0].count =
 | 
			
		||||
 			(info->flags & IEEE80211_TX_CTL_NO_ACK) ?
 | 
			
		||||
 			1 : txrc->hw->max_rate_tries;
 | 
			
		||||
-		if (!sta && txrc->ap)
 | 
			
		||||
+		if (!sta && txrc->bss)
 | 
			
		||||
 			rc_send_low_broadcast(&info->control.rates[0].idx,
 | 
			
		||||
 					      txrc->bss_conf->basic_rates,
 | 
			
		||||
-					      txrc->sband->n_bitrates);
 | 
			
		||||
+					      txrc->bss_conf->mcast_rate,
 | 
			
		||||
+					      txrc->sband);
 | 
			
		||||
 		return true;
 | 
			
		||||
 	}
 | 
			
		||||
 	return false;
 | 
			
		||||
--- a/net/mac80211/tx.c
 | 
			
		||||
+++ b/net/mac80211/tx.c
 | 
			
		||||
@@ -622,7 +622,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021
 | 
			
		||||
 		txrc.max_rate_idx = -1;
 | 
			
		||||
 	else
 | 
			
		||||
 		txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
 | 
			
		||||
-	txrc.ap = tx->sdata->vif.type == NL80211_IFTYPE_AP;
 | 
			
		||||
+	txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
 | 
			
		||||
+			   tx->sdata->vif.type == NL80211_IFTYPE_ADHOC);
 | 
			
		||||
 
 | 
			
		||||
 	/* set up RTS protection if desired */
 | 
			
		||||
 	if (len > tx->local->hw.wiphy->rts_threshold) {
 | 
			
		||||
@@ -2312,7 +2313,7 @@ struct sk_buff *ieee80211_beacon_get_tim
 | 
			
		||||
 		txrc.max_rate_idx = -1;
 | 
			
		||||
 	else
 | 
			
		||||
 		txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
 | 
			
		||||
-	txrc.ap = true;
 | 
			
		||||
+	txrc.bss = true;
 | 
			
		||||
 	rate_control_get_rate(sdata, NULL, &txrc);
 | 
			
		||||
 
 | 
			
		||||
 	info->control.vif = vif;
 | 
			
		||||
@ -1,33 +0,0 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/main.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
 | 
			
		||||
@@ -94,11 +94,13 @@ void ath9k_ps_wakeup(struct ath_softc *s
 | 
			
		||||
 {
 | 
			
		||||
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 | 
			
		||||
 	unsigned long flags;
 | 
			
		||||
+	enum ath9k_power_mode power_mode;
 | 
			
		||||
 
 | 
			
		||||
 	spin_lock_irqsave(&sc->sc_pm_lock, flags);
 | 
			
		||||
 	if (++sc->ps_usecount != 1)
 | 
			
		||||
 		goto unlock;
 | 
			
		||||
 
 | 
			
		||||
+	power_mode = sc->sc_ah->power_mode;
 | 
			
		||||
 	ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
 | 
			
		||||
 
 | 
			
		||||
 	/*
 | 
			
		||||
@@ -106,10 +108,12 @@ void ath9k_ps_wakeup(struct ath_softc *s
 | 
			
		||||
 	 * useful data. Better clear them now so that they don't mess up
 | 
			
		||||
 	 * survey data results.
 | 
			
		||||
 	 */
 | 
			
		||||
-	spin_lock(&common->cc_lock);
 | 
			
		||||
-	ath_hw_cycle_counters_update(common);
 | 
			
		||||
-	memset(&common->cc_survey, 0, sizeof(common->cc_survey));
 | 
			
		||||
-	spin_unlock(&common->cc_lock);
 | 
			
		||||
+	if (power_mode != ATH9K_PM_AWAKE) {
 | 
			
		||||
+		spin_lock(&common->cc_lock);
 | 
			
		||||
+		ath_hw_cycle_counters_update(common);
 | 
			
		||||
+		memset(&common->cc_survey, 0, sizeof(common->cc_survey));
 | 
			
		||||
+		spin_unlock(&common->cc_lock);
 | 
			
		||||
+	}
 | 
			
		||||
 
 | 
			
		||||
  unlock:
 | 
			
		||||
 	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 | 
			
		||||
@ -1,20 +0,0 @@
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/beacon.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
 | 
			
		||||
@@ -506,7 +506,7 @@ static void ath_beacon_config_ap(struct 
 | 
			
		||||
 	ath9k_hw_disable_interrupts(ah);
 | 
			
		||||
 	ath9k_beacon_init(sc, nexttbtt, intval);
 | 
			
		||||
 	sc->beacon.bmisscnt = 0;
 | 
			
		||||
-	ath9k_hw_enable_interrupts(ah);
 | 
			
		||||
+	ath9k_hw_set_interrupts(ah, ah->imask);
 | 
			
		||||
 
 | 
			
		||||
 	/* Clear the reset TSF flag, so that subsequent beacon updation
 | 
			
		||||
 	   will not reset the HW TSF. */
 | 
			
		||||
@@ -689,7 +689,7 @@ static void ath_beacon_config_adhoc(stru
 | 
			
		||||
 	ath9k_hw_disable_interrupts(ah);
 | 
			
		||||
 	ath9k_beacon_init(sc, nexttbtt, intval);
 | 
			
		||||
 	sc->beacon.bmisscnt = 0;
 | 
			
		||||
-	ath9k_hw_enable_interrupts(ah);
 | 
			
		||||
+	ath9k_hw_set_interrupts(ah, ah->imask);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
 | 
			
		||||
@ -16,7 +16,7 @@ Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
 | 
			
		||||
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
 | 
			
		||||
@@ -593,6 +593,10 @@ static void rt2800pci_kill_tx_queue(stru
 | 
			
		||||
@@ -590,6 +590,10 @@ static void rt2800pci_kill_tx_queue(stru
 | 
			
		||||
 		return;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
--- a/drivers/net/wireless/mwl8k.c
 | 
			
		||||
+++ b/drivers/net/wireless/mwl8k.c
 | 
			
		||||
@@ -3897,6 +3897,7 @@ MODULE_FIRMWARE("mwl8k/helper_8366.fw");
 | 
			
		||||
@@ -3902,6 +3902,7 @@ MODULE_FIRMWARE("mwl8k/helper_8366.fw");
 | 
			
		||||
 MODULE_FIRMWARE("mwl8k/fmimage_8366.fw");
 | 
			
		||||
 
 | 
			
		||||
 static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
--- a/drivers/net/wireless/b43/b43.h
 | 
			
		||||
+++ b/drivers/net/wireless/b43/b43.h
 | 
			
		||||
@@ -705,6 +705,7 @@ struct b43_wldev {
 | 
			
		||||
@@ -718,6 +718,7 @@ struct b43_wldev {
 | 
			
		||||
 	bool qos_enabled;		/* TRUE, if QoS is used. */
 | 
			
		||||
 	bool hwcrypto_enabled;		/* TRUE, if HW crypto acceleration is enabled. */
 | 
			
		||||
 	bool use_pio;			/* TRUE if next init should use PIO */
 | 
			
		||||
 | 
			
		||||
@ -21,54 +21,6 @@
 | 
			
		||||
 # 
 | 
			
		||||
 # Copyright 2007, 2008, 2010	Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
 | 
			
		||||
 #
 | 
			
		||||
--- a/scripts/athenable
 | 
			
		||||
+++ b/scripts/athenable
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
-#!/bin/bash
 | 
			
		||||
+#!/usr/bin/env bash
 | 
			
		||||
 #
 | 
			
		||||
 # Copyright 2007	Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
 | 
			
		||||
 #
 | 
			
		||||
--- a/scripts/athload
 | 
			
		||||
+++ b/scripts/athload
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
-#!/bin/bash
 | 
			
		||||
+#!/usr/bin/env bash
 | 
			
		||||
 # Copyright 2007	Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
 | 
			
		||||
 #
 | 
			
		||||
 # Loads ath5k or madwifi
 | 
			
		||||
--- a/scripts/b43enable
 | 
			
		||||
+++ b/scripts/b43enable
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
-#!/bin/bash
 | 
			
		||||
+#!/usr/bin/env bash
 | 
			
		||||
 #
 | 
			
		||||
 # Copyright 2007	Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
 | 
			
		||||
 #
 | 
			
		||||
--- a/scripts/b43load
 | 
			
		||||
+++ b/scripts/b43load
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
-#!/bin/bash
 | 
			
		||||
+#!/usr/bin/env bash
 | 
			
		||||
 # Copyright 2007	Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
 | 
			
		||||
 #
 | 
			
		||||
 # Loads new broadcom drivers (b43 and b43legacy) or the old ones (bcm43xx)
 | 
			
		||||
--- a/scripts/btload.sh
 | 
			
		||||
+++ b/scripts/btload.sh
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
-#!/bin/bash
 | 
			
		||||
+#!/usr/bin/env bash
 | 
			
		||||
 MODULES="bluetooth btusb l2cap sco hidp rfcomm bnep"
 | 
			
		||||
 for i in $MODULES; do
 | 
			
		||||
 	echo Loading $i...
 | 
			
		||||
--- a/scripts/btunload.sh
 | 
			
		||||
+++ b/scripts/btunload.sh
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
-#!/bin/bash
 | 
			
		||||
+#!/usr/bin/env bash
 | 
			
		||||
 MODULES="hidp rfcomm bnep l2cap sco btusb bluetooth"
 | 
			
		||||
 echo Stoping bluetooth service..
 | 
			
		||||
 /etc/init.d/bluetooth stop
 | 
			
		||||
--- a/scripts/check_config.sh
 | 
			
		||||
+++ b/scripts/check_config.sh
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
@ -77,22 +29,6 @@
 | 
			
		||||
 # This script checks the compat-wireless configuration file and if changes were made
 | 
			
		||||
 # regenerates the compat_autoconf header.
 | 
			
		||||
 
 | 
			
		||||
--- a/scripts/check_depmod
 | 
			
		||||
+++ b/scripts/check_depmod
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
-#!/bin/bash
 | 
			
		||||
+#!/usr/bin/env bash
 | 
			
		||||
 # Copyright 2009	Luis R. Rodriguez <mcgrof@gmail.com>
 | 
			
		||||
 # 
 | 
			
		||||
 # Ensures your distribution likes to prefer updates/ over the kernel/
 | 
			
		||||
--- a/scripts/compress_modules
 | 
			
		||||
+++ b/scripts/compress_modules
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
-#!/bin/bash
 | 
			
		||||
+#!/usr/bin/env bash
 | 
			
		||||
 # To be used by distributions using compressed modules
 | 
			
		||||
 
 | 
			
		||||
 COMPRESSION_FOUND="n"
 | 
			
		||||
--- a/scripts/driver-select
 | 
			
		||||
+++ b/scripts/driver-select
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
@ -117,73 +53,9 @@
 | 
			
		||||
 # Copyright 2009  Luis R. Rodriguez <mcgrof@gmail.com>
 | 
			
		||||
 #
 | 
			
		||||
 # You can use this to make stable compat-wireless releases
 | 
			
		||||
--- a/scripts/iwl-enable
 | 
			
		||||
+++ b/scripts/iwl-enable
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
-#!/bin/bash
 | 
			
		||||
+#!/usr/bin/env bash
 | 
			
		||||
 #
 | 
			
		||||
 # Copyright 2007	Luis R. Rodriguez <lrodriguez@atheros.com>
 | 
			
		||||
 #
 | 
			
		||||
--- a/scripts/iwl-load
 | 
			
		||||
+++ b/scripts/iwl-load
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
-#!/bin/bash
 | 
			
		||||
+#!/usr/bin/env bash
 | 
			
		||||
 # Copyright 2008	Luis R. Rodriguez <lrodriguez@atheros.com>
 | 
			
		||||
 #
 | 
			
		||||
 # Loads new Intel iwl (iwlagn) or the old ones (iwl4965)
 | 
			
		||||
--- a/scripts/load.sh
 | 
			
		||||
+++ b/scripts/load.sh
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
-#!/bin/bash
 | 
			
		||||
+#!/usr/bin/env bash
 | 
			
		||||
 MODULES="ipw2100 ipw2200 libertas_cs usb8xxx"
 | 
			
		||||
 MODULES="$MODULES p54pci p54usb"
 | 
			
		||||
 MODULES="$MODULES adm8211 zd1211rw"
 | 
			
		||||
--- a/scripts/modlib.sh
 | 
			
		||||
+++ b/scripts/modlib.sh
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
-#!/bin/bash
 | 
			
		||||
+#!/usr/bin/env bash
 | 
			
		||||
 #
 | 
			
		||||
 # Copyright 2007	Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
 | 
			
		||||
 #
 | 
			
		||||
--- a/scripts/skip-colors
 | 
			
		||||
+++ b/scripts/skip-colors
 | 
			
		||||
@@ -1,2 +1,2 @@
 | 
			
		||||
-#!/bin/bash
 | 
			
		||||
+#!/usr/bin/env bash
 | 
			
		||||
 perl -pe 's|(\e)\[(\d+)(;*)(\d*)(\w)||g'
 | 
			
		||||
--- a/scripts/unload.sh
 | 
			
		||||
+++ b/scripts/unload.sh
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
-#!/bin/bash
 | 
			
		||||
+#!/usr/bin/env bash
 | 
			
		||||
 
 | 
			
		||||
 # The old stack drivers and the mac80211 rc80211_simple modules 
 | 
			
		||||
 # which is no longer on recent kernels (its internal)
 | 
			
		||||
--- a/scripts/update-initramfs
 | 
			
		||||
+++ b/scripts/update-initramfs
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
-#!/bin/bash
 | 
			
		||||
+#!/usr/bin/env bash
 | 
			
		||||
 # Copyright 2009        Luis R. Rodriguez <mcgrof@gmail.com>
 | 
			
		||||
 #
 | 
			
		||||
 # Since we provide ssb, the Ethernet module b44 some people may
 | 
			
		||||
--- a/scripts/wlload.sh
 | 
			
		||||
+++ b/scripts/wlload.sh
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
-#!/bin/bash
 | 
			
		||||
+#!/usr/bin/env bash
 | 
			
		||||
 MODULES="ipw2100 ipw2200 libertas_cs usb8xxx"
 | 
			
		||||
 MODULES="$MODULES p54pci p54usb"
 | 
			
		||||
 MODULES="$MODULES adm8211 zd1211rw"
 | 
			
		||||
--- a/scripts/wlunload.sh
 | 
			
		||||
+++ b/scripts/wlunload.sh
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
-#!/bin/bash
 | 
			
		||||
+#!/usr/bin/env bash
 | 
			
		||||
 
 | 
			
		||||
 # The old stack drivers and the mac80211 rc80211_simple modules
 | 
			
		||||
 # which is no longer on recent kernels (its internal)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user