mac80211: update to wireless-testing 2011-09-14

SVN-Revision: 28245
master
Felix Fietkau 13 years ago
parent 98372a8eb5
commit 22be36418e
  1. 4
      package/mac80211/Makefile
  2. 2
      package/mac80211/patches/018-revert_printk_va_format.patch
  3. 10
      package/mac80211/patches/120-pr_fmt_warnings.patch
  4. 22
      package/mac80211/patches/130-fix_sublevel_check.patch
  5. 2658
      package/mac80211/patches/300-pending_work.patch
  6. 32
      package/mac80211/patches/310-ibss_ht.patch
  7. 2
      package/mac80211/patches/400-ath_move_debug_code.patch
  8. 4
      package/mac80211/patches/406-regd_no_assoc_hints.patch
  9. 4
      package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
  10. 10
      package/mac80211/patches/500-ath9k_eeprom_debugfs.patch
  11. 2
      package/mac80211/patches/511-ath9k_increase_bcbuf.patch
  12. 2
      package/mac80211/patches/512-ath9k_reduce_rxbuf.patch
  13. 18
      package/mac80211/patches/513-ath9k_channelbw_debugfs.patch
  14. 8
      package/mac80211/patches/520-mac80211_minstrel_ht_aggr_delay.patch
  15. 4
      package/mac80211/patches/530-mac80211_cur_txpower.patch
  16. 4
      package/mac80211/patches/531-ath9k_cur_txpower.patch
  17. 34
      package/mac80211/patches/540-ath9k_limit_qlen.patch
  18. 56
      package/mac80211/patches/540-ath9k_txkeyidx_u8.patch
  19. 281
      package/mac80211/patches/541-ath9k_aggr_queue_cleanup.patch
  20. 10
      package/mac80211/patches/541-ath9k_sw_retry_reduce.patch
  21. 207
      package/mac80211/patches/542-ath9k_move_seqno.patch
  22. 119
      package/mac80211/patches/543-ath9k_move_seqno_alloc.patch
  23. 264
      package/mac80211/patches/544-ath9k_defer_buffer_setup.patch
  24. 24
      package/mac80211/patches/545-ath9k_aggr_padding_fix.patch
  25. 19
      package/mac80211/patches/546-ath9k_retry_cache_sync.patch
  26. 0
      package/mac80211/patches/550-ath9k_ar9280_cold_reset.patch
  27. 103
      package/mac80211/patches/560-mac80211_defer_bar_tx.patch
  28. 167
      package/mac80211/patches/560-minstrel_ht_optimize.patch
  29. 96
      package/mac80211/patches/561-mac80211_tx_status.patch
  30. 121
      package/mac80211/patches/562-ath9k_tx_status.patch
  31. 28
      package/mac80211/patches/570-ath9k_fix_ack_cts_timeout.patch
  32. 27
      package/mac80211/patches/570-ath9k_tx_stop_failure_debug.patch
  33. 122
      package/mac80211/patches/571-ath9k_reset_debug.patch
  34. 273
      package/mac80211/patches/580-ath9k_remove_common_chainmask.patch
  35. 298
      package/mac80211/patches/581-ath9k_use_reset_work.patch
  36. 448
      package/mac80211/patches/582-ath9k_merge_reset_functions.patch
  37. 178
      package/mac80211/patches/583-ath9k_antenna_control.patch
  38. 30
      package/mac80211/patches/584-ath9k_fix_reset.patch
  39. 10
      package/mac80211/patches/585-ath9k_fix_beacon_timer.patch
  40. 34
      package/mac80211/patches/586-ath9k_fix_rx_flush.patch
  41. 12
      package/mac80211/patches/590-ath9k_fix_5ghz_adc_cal.patch
  42. 24
      package/mac80211/patches/591-ath9k_cleanup_rx_status_rate.patch
  43. 4104
      package/mac80211/patches/592-ath9k_strip_initvals.patch
  44. 12
      package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
  45. 6
      package/mac80211/patches/800-b43-gpio-mask-module-option.patch
  46. 2
      package/mac80211/patches/810-b43_no_pio.patch

@ -10,10 +10,10 @@ include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=mac80211
PKG_VERSION:=2011-08-26
PKG_VERSION:=2011-09-14
PKG_RELEASE:=1
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
PKG_MD5SUM:=37218b56e8a30b351662087d68948825
PKG_MD5SUM:=a5627e6079e8d0f0baf7045141503a3d
PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -337,83 +337,59 @@ static int b43_ratelimit(struct b43_wl *
@@ -339,83 +339,59 @@ static int b43_ratelimit(struct b43_wl *
void b43info(struct b43_wl *wl, const char *fmt, ...)
{

@ -165,3 +165,13 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/etherdevice.h>
--- a/compat/crc8.c
+++ b/compat/crc8.c
@@ -14,6 +14,7 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#undef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>

@ -0,0 +1,22 @@
--- a/config.mk
+++ b/config.mk
@@ -20,16 +20,16 @@ COMPAT_LATEST_VERSION = 1
KERNEL_VERSION := $(shell $(MAKE) -C $(KLIB_BUILD) kernelversion | sed -n 's/^\([0-9]\)\..*/\1/p')
ifneq ($(KERNEL_VERSION),2)
-KERNEL_SUBLEVEL := $(shell $(MAKE) -C $(KLIB_BUILD) kernelversion | sed -n 's/^3\.\([0-9]\+\).*/\1/p')
+COMPAT_KERNEL_SUBLEVEL := $(shell $(MAKE) -C $(KLIB_BUILD) kernelversion | sed -n 's/^3\.\([0-9]\+\).*/\1/p')
else
COMPAT_26LATEST_VERSION = 39
KERNEL_26SUBLEVEL := $(shell $(MAKE) -C $(KLIB_BUILD) kernelversion | sed -n 's/^2\.6\.\([0-9]\+\).*/\1/p')
COMPAT_26VERSIONS := $(shell I=$(COMPAT_26LATEST_VERSION); while [ "$$I" -gt $(KERNEL_26SUBLEVEL) ]; do echo $$I; I=$$(($$I - 1)); done)
$(foreach ver,$(COMPAT_26VERSIONS),$(eval CONFIG_COMPAT_KERNEL_2_6_$(ver)=y))
-KERNEL_SUBLEVEL := -1
+COMPAT_KERNEL_SUBLEVEL := -1
endif
-COMPAT_VERSIONS := $(shell I=$(COMPAT_LATEST_VERSION); while [ "$$I" -gt $(KERNEL_SUBLEVEL) ]; do echo $$I; I=$$(($$I - 1)); done)
+COMPAT_VERSIONS := $(shell I=$(COMPAT_LATEST_VERSION); while [ "$$I" -gt $(COMPAT_KERNEL_SUBLEVEL) ]; do echo $$I; I=$$(($$I - 1)); done)
$(foreach ver,$(COMPAT_VERSIONS),$(eval CONFIG_COMPAT_KERNEL_3_$(ver)=y))
ifdef CONFIG_COMPAT_KERNEL_2_6_24

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1085,6 +1085,7 @@ struct cfg80211_ibss_params {
@@ -1101,6 +1101,7 @@ struct cfg80211_ibss_params {
u8 *ssid;
u8 *bssid;
struct ieee80211_channel *channel;
@ -8,7 +8,7 @@
u8 *ie;
u8 ssid_len, ie_len;
u16 beacon_interval;
@@ -2584,6 +2585,12 @@ struct cfg80211_bss *cfg80211_get_bss(st
@@ -2612,6 +2613,12 @@ struct cfg80211_bss *cfg80211_get_bss(st
const u8 *bssid,
const u8 *ssid, size_t ssid_len,
u16 capa_mask, u16 capa_val);
@ -23,7 +23,7 @@
struct ieee80211_channel *channel,
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4470,13 +4470,41 @@ static int nl80211_join_ibss(struct sk_b
@@ -4539,13 +4539,41 @@ static int nl80211_join_ibss(struct sk_b
ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
}
@ -89,7 +89,7 @@
struct wireless_dev *wdev, int freq,
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -441,6 +441,9 @@ cfg80211_can_add_interface(struct cfg802
@@ -439,6 +439,9 @@ cfg80211_can_add_interface(struct cfg802
struct ieee80211_channel *
rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
int freq, enum nl80211_channel_type channel_type);
@ -161,7 +161,7 @@
struct ieee80211_channel *channel,
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -464,6 +464,7 @@ struct ieee80211_if_ibss {
@@ -465,6 +465,7 @@ struct ieee80211_if_ibss {
u8 ssid_len, ie_len;
u8 *ie;
struct ieee80211_channel *channel;
@ -169,7 +169,7 @@
unsigned long ibss_join_req;
/* probe response/beacon for IBSS */
@@ -1089,6 +1090,7 @@ void ieee80211_ibss_notify_scan_complete
@@ -1091,6 +1092,7 @@ void ieee80211_ibss_notify_scan_complete
void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata);
struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
u8 *bssid, u8 *addr, u32 supp_rates,
@ -177,7 +177,7 @@
gfp_t gfp);
int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
struct cfg80211_ibss_params *params);
@@ -1343,6 +1345,12 @@ void ieee80211_recalc_smps(struct ieee80
@@ -1344,6 +1346,12 @@ void ieee80211_recalc_smps(struct ieee80
size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
const u8 *ids, int n_ids, size_t offset);
size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
@ -190,7 +190,7 @@
/* internal work items */
void ieee80211_work_init(struct ieee80211_local *local);
@@ -1371,6 +1379,8 @@ ieee80211_get_channel_mode(struct ieee80
@@ -1372,6 +1380,8 @@ ieee80211_get_channel_mode(struct ieee80
bool ieee80211_set_channel_type(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
enum nl80211_channel_type chantype);
@ -201,7 +201,7 @@
#define debug_noinline noinline
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -841,23 +841,8 @@ int ieee80211_build_preq_ies(struct ieee
@@ -839,23 +839,8 @@ int ieee80211_build_preq_ies(struct ieee
offset = noffset;
}
@ -227,7 +227,7 @@
/*
* If adding more here, adjust code in main.c
@@ -1381,3 +1366,100 @@ void ieee80211_disable_rssi_reports(stru
@@ -1378,3 +1363,100 @@ void ieee80211_disable_rssi_reports(stru
_ieee80211_enable_rssi_reports(sdata, 0, 0);
}
EXPORT_SYMBOL(ieee80211_disable_rssi_reports);
@ -376,7 +376,7 @@
static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -84,6 +84,8 @@ static void ieee80211_send_addba_request
@@ -82,6 +82,8 @@ static void ieee80211_send_addba_request
memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
else if (sdata->vif.type == NL80211_IFTYPE_STATION)
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
@ -385,7 +385,7 @@
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
@@ -400,7 +402,8 @@ int ieee80211_start_tx_ba_session(struct
@@ -399,7 +401,8 @@ int ieee80211_start_tx_ba_session(struct
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
sdata->vif.type != NL80211_IFTYPE_AP &&
@ -397,7 +397,7 @@
if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -203,6 +203,8 @@ void ieee80211_send_delba(struct ieee802
@@ -199,6 +199,8 @@ void ieee80211_send_delba(struct ieee802
memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
else if (sdata->vif.type == NL80211_IFTYPE_STATION)
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
@ -687,7 +687,7 @@
if (params->ie) {
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2161,7 +2161,8 @@ ieee80211_rx_h_action(struct ieee80211_r
@@ -2164,7 +2164,8 @@ ieee80211_rx_h_action(struct ieee80211_r
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
sdata->vif.type != NL80211_IFTYPE_AP &&
@ -697,7 +697,7 @@
break;
/* verify action_code is present */
@@ -2696,7 +2697,8 @@ static int prepare_for_handlers(struct i
@@ -2699,7 +2700,8 @@ static int prepare_for_handlers(struct i
else
rate_idx = status->rate_idx;
rx->sta = ieee80211_ibss_add_sta(sdata, bssid,
@ -709,7 +709,7 @@
case NL80211_IFTYPE_MESH_POINT:
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -186,6 +186,8 @@ static void ieee80211_send_addba_resp(st
@@ -182,6 +182,8 @@ static void ieee80211_send_addba_resp(st
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
else if (sdata->vif.type == NL80211_IFTYPE_WDS)
memcpy(mgmt->bssid, da, ETH_ALEN);

@ -11,7 +11,7 @@
+ debug.o
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -277,13 +277,6 @@ ath_dbg(struct ath_common *common, enum
@@ -274,13 +274,6 @@ void ath_dbg(struct ath_common *common,
#endif /* CONFIG_ATH_DEBUG */
/** Returns string describing opmode, or NULL if unknown mode. */

@ -1,6 +1,6 @@
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1642,6 +1642,8 @@ void regulatory_hint_11d(struct wiphy *w
@@ -1653,6 +1653,8 @@ void regulatory_hint_11d(struct wiphy *w
enum environment_cap env = ENVIRON_ANY;
struct regulatory_request *request;
@ -9,7 +9,7 @@
mutex_lock(&reg_mutex);
if (unlikely(!last_request))
@@ -1848,6 +1850,8 @@ static void restore_regulatory_settings(
@@ -1859,6 +1861,8 @@ static void restore_regulatory_settings(
void regulatory_hint_disconnect(void)
{

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1491,15 +1491,6 @@ static int ath9k_add_interface(struct ie
@@ -1473,15 +1473,6 @@ static int ath9k_add_interface(struct ie
}
}
@ -16,7 +16,7 @@
ath_dbg(common, ATH_DBG_CONFIG,
"Attach a VIF of type: %d\n", vif->type);
@@ -1525,15 +1516,6 @@ static int ath9k_change_interface(struct
@@ -1507,15 +1498,6 @@ static int ath9k_change_interface(struct
mutex_lock(&sc->mutex);
ath9k_ps_wakeup(sc);

@ -1,9 +1,9 @@
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1272,6 +1272,53 @@ static const struct file_operations fops
.llseek = default_llseek,
@@ -1585,6 +1585,53 @@ static const struct file_operations fops
};
+static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
@ -54,7 +54,7 @@
int ath9k_init_debug(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
@@ -1328,6 +1375,9 @@ int ath9k_init_debug(struct ath_hw *ah)
@@ -1643,6 +1690,9 @@ 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);
@ -62,5 +62,5 @@
+ &fops_eeprom);
+
sc->debug.regidx = 0;
return 0;
}
memset(&sc->debug.bb_mac_samp, 0, sizeof(sc->debug.bb_mac_samp));
sc->debug.sampidx = 0;

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -366,7 +366,7 @@ struct ath_vif {
@@ -363,7 +363,7 @@ struct ath_vif {
* number of beacon intervals, the game's up.
*/
#define BSTUCK_THRESH 9

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -123,7 +123,7 @@ void ath_descdma_cleanup(struct ath_soft
@@ -120,7 +120,7 @@ void ath_descdma_cleanup(struct ath_soft
/* RX / TX */
/***********/

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -587,6 +587,7 @@ struct ath_softc {
@@ -585,6 +585,7 @@ struct ath_softc {
struct ieee80211_hw *hw;
struct device *dev;
@ -10,7 +10,7 @@
struct survey_info *cur_survey;
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1378,6 +1378,9 @@ int ath9k_init_debug(struct ath_hw *ah)
@@ -1693,6 +1693,9 @@ int ath9k_init_debug(struct ath_hw *ah)
debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_eeprom);
@ -18,11 +18,11 @@
+ &sc->chan_bw);
+
sc->debug.regidx = 0;
return 0;
}
memset(&sc->debug.bb_mac_samp, 0, sizeof(sc->debug.bb_mac_samp));
sc->debug.sampidx = 0;
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1654,9 +1654,10 @@ static int ath9k_config(struct ieee80211
@@ -1636,9 +1636,10 @@ static int ath9k_config(struct ieee80211
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
struct ieee80211_channel *curchan = hw->conf.channel;
@ -34,7 +34,7 @@
unsigned long flags;
if (ah->curchan)
@@ -1709,7 +1710,23 @@ static int ath9k_config(struct ieee80211
@@ -1691,7 +1692,23 @@ static int ath9k_config(struct ieee80211
memset(&sc->survey[pos], 0, sizeof(struct survey_info));
}
@ -61,9 +61,9 @@
return -EINVAL;
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1507,6 +1507,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st
}
ah->noise = ath9k_hw_getchan_noise(ah, chan);
@@ -1509,6 +1509,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st
(AR_SREV_9300_20_OR_LATER(ah) && IS_CHAN_5GHZ(chan)))
bChannelChange = false;
+ if (!ah->curchan || ((ah->curchan->channelFlags ^ chan->channelFlags) &
+ (CHANNEL_HALF | CHANNEL_QUARTER)))

@ -27,12 +27,12 @@
ieee80211_start_tx_ba_session(pubsta, tid, 5000);
}
@@ -452,7 +460,7 @@ minstrel_ht_tx_status(void *priv, struct
@@ -453,7 +461,7 @@ minstrel_ht_tx_status(void *priv, struct
if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
minstrel_ht_update_stats(mp, mi);
- minstrel_aggr_check(mp, sta, skb);
+ minstrel_aggr_check(mp, mi, sta, skb);
if (!(info->flags & IEEE80211_TX_CTL_AMPDU))
- minstrel_aggr_check(mp, sta, skb);
+ minstrel_aggr_check(mp, mi, sta, skb);
}
}

@ -1,6 +1,6 @@
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -790,7 +790,7 @@ enum ieee80211_smps_mode {
@@ -798,7 +798,7 @@ enum ieee80211_smps_mode {
*/
struct ieee80211_conf {
u32 flags;
@ -11,7 +11,7 @@
u16 listen_interval;
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1551,7 +1551,7 @@ static int ieee80211_get_tx_power(struct
@@ -1568,7 +1568,7 @@ static int ieee80211_get_tx_power(struct
{
struct ieee80211_local *local = wiphy_priv(wiphy);

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1732,6 +1732,8 @@ static int ath9k_config(struct ieee80211
@@ -1714,6 +1714,8 @@ static int ath9k_config(struct ieee80211
return -EINVAL;
}
@ -9,7 +9,7 @@
/*
* The most recent snapshot of channel->noisefloor for the old
* channel is only available after the hardware reset. Copy it to
@@ -1749,6 +1751,7 @@ static int ath9k_config(struct ieee80211
@@ -1731,6 +1733,7 @@ static int ath9k_config(struct ieee80211
ath9k_cmn_update_txpow(ah, sc->curtxpow,
sc->config.txpowlimit, &sc->curtxpow);
ath9k_ps_restore(sc);

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -240,6 +240,7 @@ struct ath_atx_tid {
@@ -237,6 +237,7 @@ struct ath_atx_tid {
struct ath_node *an;
struct ath_atx_ac *ac;
unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
@ -8,7 +8,7 @@
u16 seq_start;
u16 seq_next;
u16 baw_size;
@@ -286,6 +287,9 @@ struct ath_tx_control {
@@ -282,6 +283,9 @@ struct ath_tx_control {
* (axq_qnum).
*/
struct ath_tx {
@ -20,7 +20,7 @@
spinlock_t txbuflock;
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1341,6 +1341,10 @@ int ath9k_init_debug(struct ath_hw *ah)
@@ -1654,6 +1654,10 @@ int ath9k_init_debug(struct ath_hw *ah)
sc, &fops_wiphy);
debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_xmit);
@ -33,7 +33,7 @@
debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, sc,
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -351,6 +351,14 @@ static void ath_tx_count_frames(struct a
@@ -350,6 +350,14 @@ static void ath_tx_count_frames(struct a
}
}
@ -48,7 +48,7 @@
static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf, struct list_head *bf_q,
@@ -441,6 +449,8 @@ static void ath_tx_complete_aggr(struct
@@ -438,6 +446,8 @@ static void ath_tx_complete_aggr(struct
__skb_queue_head_init(&bf_pending);
ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
@ -57,15 +57,15 @@
while (bf) {
u16 seqno = bf->bf_state.seqno;
@@ -839,6 +849,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
@@ -816,6 +826,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
ath_tx_addto_baw(sc, tid, seqno);
ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
bf->bf_state.ndelim = ndelim;
+ tid->buf_pending++;
__skb_unlink(skb, &tid->buf_q);
list_add_tail(&bf->list, bf_q);
if (bf_prev) {
@@ -1494,6 +1505,8 @@ static void ath_tx_send_ampdu(struct ath
if (bf_prev)
@@ -1693,6 +1704,8 @@ static void ath_tx_send_ampdu(struct ath
/* Add sub-frame to BAW */
ath_tx_addto_baw(sc, tid, bf->bf_state.seqno);
@ -74,7 +74,7 @@
/* Queue to h/w without aggregation */
TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
bf->bf_lastbf = bf;
@@ -1822,23 +1835,13 @@ error:
@@ -1821,23 +1834,13 @@ error:
/* FIXME: tx power */
static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
@ -100,7 +100,7 @@
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
/*
@@ -1880,6 +1883,7 @@ int ath_tx_start(struct ieee80211_hw *hw
@@ -1872,6 +1875,7 @@ int ath_tx_start(struct ieee80211_hw *hw
struct ieee80211_vif *vif = info->control.vif;
struct ath_softc *sc = hw->priv;
struct ath_txq *txq = txctl->txq;
@ -108,15 +108,7 @@
int padpos, padsize;
int frmlen = skb->len + FCS_LEN;
int q;
@@ -1912,6 +1916,7 @@ int ath_tx_start(struct ieee80211_hw *hw
skb_push(skb, padsize);
memmove(skb->data, skb->data + padsize, padpos);
+ hdr = (struct ieee80211_hdr *) skb->data;
}
if ((vif && vif->type != NL80211_IFTYPE_AP &&
@@ -1921,6 +1926,24 @@ int ath_tx_start(struct ieee80211_hw *hw
@@ -1916,6 +1920,24 @@ int ath_tx_start(struct ieee80211_hw *hw
setup_frame_info(hw, skb, frmlen);
@ -141,7 +133,7 @@
/*
* At this point, the vif, hw_key and sta pointers in the tx control
* info are no longer valid (overwritten by the ath_frame_info data.
@@ -1935,7 +1958,7 @@ int ath_tx_start(struct ieee80211_hw *hw
@@ -1930,7 +1952,7 @@ int ath_tx_start(struct ieee80211_hw *hw
}
spin_unlock_bh(&txq->axq_lock);

@ -1,56 +0,0 @@
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -273,7 +273,7 @@ static int ar9002_hw_proc_txdesc(struct
static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
u32 pktLen, enum ath9k_pkt_type type,
- u32 txPower, u32 keyIx,
+ u32 txPower, u8 keyIx,
enum ath9k_key_type keyType, u32 flags)
{
struct ar5416_desc *ads = AR5416DESC(ds);
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -207,8 +207,8 @@ struct ath_atx_ac {
struct ath_frame_info {
int framelen;
- u32 keyix;
enum ath9k_key_type keytype;
+ u8 keyix;
u8 retries;
u16 seqno;
};
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -623,7 +623,7 @@ struct ath_hw_ops {
struct ath_tx_status *ts);
void (*set11n_txdesc)(struct ath_hw *ah, void *ds,
u32 pktLen, enum ath9k_pkt_type type,
- u32 txPower, u32 keyIx,
+ u32 txPower, u8 keyIx,
enum ath9k_key_type keyType,
u32 flags);
void (*set11n_ratescenario)(struct ath_hw *ah, void *ds,
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -194,7 +194,7 @@ struct ath_htc_rx_status {
#define ATH9K_RX_DECRYPT_BUSY 0x40
#define ATH9K_RXKEYIX_INVALID ((u8)-1)
-#define ATH9K_TXKEYIX_INVALID ((u32)-1)
+#define ATH9K_TXKEYIX_INVALID ((u8)-1)
enum ath9k_phyerr {
ATH9K_PHYERR_UNDERRUN = 0, /* Transmit underrun */
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -312,7 +312,7 @@ static int ar9003_hw_proc_txdesc(struct
static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
u32 pktlen, enum ath9k_pkt_type type, u32 txpower,
- u32 keyIx, enum ath9k_key_type keyType, u32 flags)
+ u8 keyIx, enum ath9k_key_type keyType, u32 flags)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;

@ -1,281 +0,0 @@
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -206,6 +206,7 @@ struct ath_atx_ac {
};
struct ath_frame_info {
+ struct ath_buf *bf;
int framelen;
enum ath9k_key_type keytype;
u8 keyix;
@@ -235,7 +236,7 @@ struct ath_buf {
struct ath_atx_tid {
struct list_head list;
- struct list_head buf_q;
+ struct sk_buff_head buf_q;
struct ath_node *an;
struct ath_atx_ac *ac;
unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -711,7 +711,7 @@ static ssize_t read_file_stations(struct
" tid: %p %s %s %i %p %p\n",
tid, tid->sched ? "sched" : "idle",
tid->paused ? "paused" : "running",
- list_empty(&tid->buf_q),
+ skb_queue_empty(&tid->buf_q),
tid->an, tid->ac);
if (len >= size)
goto done;
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -129,7 +129,7 @@ static void ath_tx_resume_tid(struct ath
spin_lock_bh(&txq->axq_lock);
tid->paused = false;
- if (list_empty(&tid->buf_q))
+ if (skb_queue_empty(&tid->buf_q))
goto unlock;
ath_tx_queue_tid(txq, tid);
@@ -149,6 +149,7 @@ static struct ath_frame_info *get_frame_
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{
struct ath_txq *txq = tid->ac->txq;
+ struct sk_buff *skb;
struct ath_buf *bf;
struct list_head bf_head;
struct ath_tx_status ts;
@@ -159,12 +160,13 @@ static void ath_tx_flush_tid(struct ath_
memset(&ts, 0, sizeof(ts));
spin_lock_bh(&txq->axq_lock);
- while (!list_empty(&tid->buf_q)) {
- bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
- list_move_tail(&bf->list, &bf_head);
+ while ((skb = __skb_dequeue(&tid->buf_q))) {
+ fi = get_frame_info(skb);
+ bf = fi->bf;
+
+ list_add_tail(&bf->list, &bf_head);
spin_unlock_bh(&txq->axq_lock);
- fi = get_frame_info(bf->bf_mpdu);
if (fi->retries) {
ath_tx_update_baw(sc, tid, fi->seqno);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
@@ -219,6 +221,7 @@ static void ath_tid_drain(struct ath_sof
struct ath_atx_tid *tid)
{
+ struct sk_buff *skb;
struct ath_buf *bf;
struct list_head bf_head;
struct ath_tx_status ts;
@@ -227,14 +230,12 @@ static void ath_tid_drain(struct ath_sof
memset(&ts, 0, sizeof(ts));
INIT_LIST_HEAD(&bf_head);
- for (;;) {
- if (list_empty(&tid->buf_q))
- break;
+ while ((skb = __skb_dequeue(&tid->buf_q))) {
+ fi = get_frame_info(skb);
+ bf = fi->bf;
- bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
- list_move_tail(&bf->list, &bf_head);
+ list_add_tail(&bf->list, &bf_head);
- fi = get_frame_info(bf->bf_mpdu);
if (fi->retries)
ath_tx_update_baw(sc, tid, fi->seqno);
@@ -349,7 +350,8 @@ static void ath_tx_complete_aggr(struct
struct ieee80211_tx_info *tx_info;
struct ath_atx_tid *tid = NULL;
struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
- struct list_head bf_head, bf_pending;
+ struct list_head bf_head;
+ struct sk_buff_head bf_pending;
u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0;
u32 ba[WME_BA_BMP_SIZE >> 5];
int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
@@ -422,8 +424,7 @@ static void ath_tx_complete_aggr(struct
}
}
- INIT_LIST_HEAD(&bf_pending);
- INIT_LIST_HEAD(&bf_head);
+ __skb_queue_head_init(&bf_pending);
ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
while (bf) {
@@ -467,10 +468,10 @@ static void ath_tx_complete_aggr(struct
* Make sure the last desc is reclaimed if it
* not a holding desc.
*/
- if (!bf_last->bf_stale || bf_next != NULL)
+ INIT_LIST_HEAD(&bf_head);
+ if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
+ bf_next != NULL || !bf_last->bf_stale)
list_move_tail(&bf->list, &bf_head);
- else
- INIT_LIST_HEAD(&bf_head);
if (!txpending || (tid->state & AGGR_CLEANUP)) {
/*
@@ -521,7 +522,7 @@ static void ath_tx_complete_aggr(struct
ath9k_hw_cleartxdesc(sc->sc_ah,
tbf->bf_desc);
- list_add_tail(&tbf->list, &bf_head);
+ fi->bf = tbf;
} else {
/*
* Clear descriptor status words for
@@ -536,21 +537,21 @@ static void ath_tx_complete_aggr(struct
* Put this buffer to the temporary pending
* queue to retain ordering
*/
- list_splice_tail_init(&bf_head, &bf_pending);
+ __skb_queue_tail(&bf_pending, skb);
}
bf = bf_next;
}
/* prepend un-acked frames to the beginning of the pending frame queue */
- if (!list_empty(&bf_pending)) {
+ if (!skb_queue_empty(&bf_pending)) {
if (an->sleeping)
ieee80211_sta_set_tim(sta);
spin_lock_bh(&txq->axq_lock);
if (clear_filter)
tid->ac->clear_ps_filter = true;
- list_splice(&bf_pending, &tid->buf_q);
+ skb_queue_splice(&bf_pending, &tid->buf_q);
if (!an->sleeping)
ath_tx_queue_tid(txq, tid);
spin_unlock_bh(&txq->axq_lock);
@@ -743,19 +744,22 @@ static enum ATH_AGGR_STATUS ath_tx_form_
int *aggr_len)
{
#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
- struct ath_buf *bf, *bf_first, *bf_prev = NULL;
+ struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
int rl = 0, nframes = 0, ndelim, prev_al = 0;
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;
struct ath_frame_info *fi;
-
- bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list);
+ struct sk_buff *skb;
do {
- bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
- fi = get_frame_info(bf->bf_mpdu);
+ skb = skb_peek(&tid->buf_q);
+ fi = get_frame_info(skb);
+ bf = fi->bf;
+
+ if (!bf_first)
+ bf_first = bf;
/* do not step over block-ack window */
if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) {
@@ -808,7 +812,9 @@ static enum ATH_AGGR_STATUS ath_tx_form_
if (!fi->retries)
ath_tx_addto_baw(sc, tid, fi->seqno);
ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
- list_move_tail(&bf->list, bf_q);
+
+ __skb_unlink(skb, &tid->buf_q);
+ list_add_tail(&bf->list, bf_q);
if (bf_prev) {
bf_prev->bf_next = bf;
ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc,
@@ -816,7 +822,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
}
bf_prev = bf;
- } while (!list_empty(&tid->buf_q));
+ } while (!skb_queue_empty(&tid->buf_q));
*aggr_len = al;
@@ -834,7 +840,7 @@ static void ath_tx_sched_aggr(struct ath
int aggr_len;
do {
- if (list_empty(&tid->buf_q))
+ if (skb_queue_empty(&tid->buf_q))
return;
INIT_LIST_HEAD(&bf_q);
@@ -955,7 +961,7 @@ bool ath_tx_aggr_sleep(struct ath_softc
spin_lock_bh(&txq->axq_lock);
- if (!list_empty(&tid->buf_q))
+ if (!skb_queue_empty(&tid->buf_q))
buffered = true;
tid->sched = false;
@@ -988,7 +994,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
spin_lock_bh(&txq->axq_lock);
ac->clear_ps_filter = true;
- if (!list_empty(&tid->buf_q) && !tid->paused) {
+ if (!skb_queue_empty(&tid->buf_q) && !tid->paused) {
ath_tx_queue_tid(txq, tid);
ath_txq_schedule(sc, txq);
}
@@ -1332,7 +1338,7 @@ void ath_txq_schedule(struct ath_softc *
* add tid to round-robin queue if more frames
* are pending for the tid
*/
- if (!list_empty(&tid->buf_q))
+ if (!skb_queue_empty(&tid->buf_q))
ath_tx_queue_tid(txq, tid);
if (tid == last_tid ||
@@ -1438,7 +1444,7 @@ static void ath_tx_send_ampdu(struct ath
* - seqno is not within block-ack window
* - h/w queue depth exceeds low water mark
*/
- if (!list_empty(&tid->buf_q) || tid->paused ||
+ if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) ||
txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
/*
@@ -1446,7 +1452,7 @@ static void ath_tx_send_ampdu(struct ath
* for aggregation.
*/
TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
- list_add_tail(&bf->list, &tid->buf_q);
+ __skb_queue_tail(&tid->buf_q, bf->bf_mpdu);
if (!txctl->an || !txctl->an->sleeping)
ath_tx_queue_tid(txctl->txq, tid);
return;
@@ -1777,6 +1783,7 @@ static struct ath_buf *ath_tx_setup_buff
bf->bf_buf_addr,
txq->axq_qnum);
+ fi->bf = bf;
return bf;
}
@@ -2394,7 +2401,7 @@ void ath_tx_node_init(struct ath_softc *
tid->sched = false;
tid->paused = false;
tid->state &= ~AGGR_CLEANUP;
- INIT_LIST_HEAD(&tid->buf_q);
+ __skb_queue_head_init(&tid->buf_q);
acno = TID_TO_WME_AC(tidno);
tid->ac = &an->ac[acno];
tid->state &= ~AGGR_ADDBA_COMPLETE;

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -260,14 +260,17 @@ static void ath_tid_drain(struct ath_sof
@@ -259,14 +259,17 @@ static void ath_tid_drain(struct ath_sof
}
static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
@ -20,7 +20,7 @@
return;
hdr = (struct ieee80211_hdr *)skb->data;
@@ -383,6 +386,7 @@ static void ath_tx_complete_aggr(struct
@@ -382,6 +385,7 @@ static void ath_tx_complete_aggr(struct
int nframes;
u8 tidno;
bool clear_filter;
@ -28,7 +28,7 @@
skb = bf->bf_mpdu;
hdr = (struct ieee80211_hdr *)skb->data;
@@ -391,6 +395,10 @@ static void ath_tx_complete_aggr(struct
@@ -390,6 +394,10 @@ static void ath_tx_complete_aggr(struct
memcpy(rates, tx_info->control.rates, sizeof(rates));
@ -39,7 +39,7 @@
rcu_read_lock();
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
@@ -478,7 +486,8 @@ static void ath_tx_complete_aggr(struct
@@ -475,7 +483,8 @@ static void ath_tx_complete_aggr(struct
} else if (fi->retries < ATH_MAX_SW_RETRIES) {
if (!(ts->ts_status & ATH9K_TXERR_FILT) ||
!an->sleeping)
@ -51,7 +51,7 @@
txpending = 1;
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -543,7 +543,7 @@ struct ath_ant_comb {
@@ -540,7 +540,7 @@ struct ath_ant_comb {
#define DEFAULT_CACHELINE 32
#define ATH_REGCLASSIDS_MAX 10
#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */

@ -1,207 +0,0 @@
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -211,12 +211,12 @@ struct ath_frame_info {
enum ath9k_key_type keytype;
u8 keyix;
u8 retries;
- u16 seqno;
};
struct ath_buf_state {
u8 bf_type;
u8 bfs_paprd;
+ u16 seqno;
unsigned long bfs_paprd_timestamp;
};
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -168,7 +168,7 @@ static void ath_tx_flush_tid(struct ath_
spin_unlock_bh(&txq->axq_lock);
if (fi->retries) {
- ath_tx_update_baw(sc, tid, fi->seqno);
+ ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
} else {
ath_tx_send_normal(sc, txq, NULL, &bf_head);
@@ -237,7 +237,7 @@ static void ath_tid_drain(struct ath_sof
list_add_tail(&bf->list, &bf_head);
if (fi->retries)
- ath_tx_update_baw(sc, tid, fi->seqno);
+ ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
spin_unlock(&txq->axq_lock);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
@@ -327,7 +327,7 @@ static void ath_tx_count_frames(struct a
while (bf) {
fi = get_frame_info(bf->bf_mpdu);
- ba_index = ATH_BA_INDEX(seq_st, fi->seqno);
+ ba_index = ATH_BA_INDEX(seq_st, bf->bf_state.seqno);
(*nframes)++;
if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
@@ -428,6 +428,8 @@ static void ath_tx_complete_aggr(struct
ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
while (bf) {
+ u16 seqno = bf->bf_state.seqno;
+
txfail = txpending = sendbar = 0;
bf_next = bf->bf_next;
@@ -435,7 +437,7 @@ static void ath_tx_complete_aggr(struct
tx_info = IEEE80211_SKB_CB(skb);
fi = get_frame_info(skb);
- if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, fi->seqno))) {
+ if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) {
/* transmit completion, subframe is
* acked by block ack */
acked_cnt++;
@@ -479,7 +481,7 @@ static void ath_tx_complete_aggr(struct
* block-ack window
*/
spin_lock_bh(&txq->axq_lock);
- ath_tx_update_baw(sc, tid, fi->seqno);
+ ath_tx_update_baw(sc, tid, seqno);
spin_unlock_bh(&txq->axq_lock);
if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
@@ -507,7 +509,7 @@ static void ath_tx_complete_aggr(struct
*/
if (!tbf) {
spin_lock_bh(&txq->axq_lock);
- ath_tx_update_baw(sc, tid, fi->seqno);
+ ath_tx_update_baw(sc, tid, seqno);
spin_unlock_bh(&txq->axq_lock);
bf->bf_state.bf_type |=
@@ -752,17 +754,19 @@ static enum ATH_AGGR_STATUS ath_tx_form_
struct ieee80211_tx_info *tx_info;
struct ath_frame_info *fi;
struct sk_buff *skb;
+ u16 seqno;
do {
skb = skb_peek(&tid->buf_q);
fi = get_frame_info(skb);
bf = fi->bf;
+ seqno = bf->bf_state.seqno;
if (!bf_first)
bf_first = bf;
/* do not step over block-ack window */
- if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) {
+ if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
status = ATH_AGGR_BAW_CLOSED;
break;
}
@@ -810,7 +814,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
/* link buffers of this frame to the aggregate */
if (!fi->retries)
- ath_tx_addto_baw(sc, tid, fi->seqno);
+ ath_tx_addto_baw(sc, tid, seqno);
ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
__skb_unlink(skb, &tid->buf_q);
@@ -1434,6 +1438,7 @@ static void ath_tx_send_ampdu(struct ath
{
struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
struct list_head bf_head;
+ u16 seqno = bf->bf_state.seqno;
bf->bf_state.bf_type |= BUF_AMPDU;
@@ -1445,7 +1450,7 @@ static void ath_tx_send_ampdu(struct ath
* - h/w queue depth exceeds low water mark
*/
if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
- !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) ||
+ !BAW_WITHIN(tid->seq_start, tid->baw_size, seqno) ||
txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
/*
* Add this frame to software queue for scheduling later
@@ -1463,7 +1468,7 @@ static void ath_tx_send_ampdu(struct ath
/* Add sub-frame to BAW */
if (!fi->retries)
- ath_tx_addto_baw(sc, tid, fi->seqno);
+ ath_tx_addto_baw(sc, tid, seqno);
/* Queue to h/w without aggregation */
TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
@@ -1519,39 +1524,19 @@ static enum ath9k_pkt_type get_hw_packet
static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
int framelen)
{
- struct ath_softc *sc = hw->priv;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_sta *sta = tx_info->control.sta;
struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ath_frame_info *fi = get_frame_info(skb);
struct ath_node *an = NULL;
- struct ath_atx_tid *tid;
enum ath9k_key_type keytype;
- u16 seqno = 0;
- u8 tidno;
keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
if (sta)
an = (struct ath_node *) sta->drv_priv;
- hdr = (struct ieee80211_hdr *)skb->data;
- if (an && ieee80211_is_data_qos(hdr->frame_control) &&
- conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) {
-
- tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
-
- /*
- * Override seqno set by upper layer with the one
- * in tx aggregation state.
- */
- tid = ATH_AN_2_TID(an, tidno);
- seqno = tid->seq_next;
- hdr->seq_ctrl = cpu_to_le16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
- INCR(tid->seq_next, IEEE80211_SEQ_MAX);
- }
-
memset(fi, 0, sizeof(*fi));
if (hw_key)
fi->keyix = hw_key->hw_key_idx;
@@ -1561,7 +1546,6 @@ static void setup_frame_info(struct ieee
fi->keyix = ATH9K_TXKEYIX_INVALID;
fi->keytype = keytype;
fi->framelen = framelen;
- fi->seqno = seqno;
}
static int setup_tx_flags(struct sk_buff *skb)
@@ -1797,6 +1781,7 @@ static void ath_tx_start_dma(struct ath_
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct list_head bf_head;
struct ath_atx_tid *tid = NULL;
+ u16 seqno;
u8 tidno;
spin_lock_bh(&txctl->txq->axq_lock);
@@ -1806,6 +1791,12 @@ static void ath_tx_start_dma(struct ath_
IEEE80211_QOS_CTL_TID_MASK;
tid = ATH_AN_2_TID(txctl->an, tidno);
+ seqno = tid->seq_next;
+ hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
+ INCR(tid->seq_next, IEEE80211_SEQ_MAX);
+
+ bf->bf_state.seqno = seqno;
+
WARN_ON(tid->ac->txq != txctl->txq);
}

@ -1,119 +0,0 @@
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1717,17 +1717,19 @@ static void ath_buf_set_rate(struct ath_
}
-static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw,
+static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
struct ath_txq *txq,
+ struct ath_atx_tid *tid,
struct sk_buff *skb)
{
- struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_frame_info *fi = get_frame_info(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ath_buf *bf;
struct ath_desc *ds;
int frm_type;
+ u16 seqno;
bf = ath_tx_get_buffer(sc);
if (!bf) {
@@ -1737,6 +1739,13 @@ static struct ath_buf *ath_tx_setup_buff
ATH_TXBUF_RESET(bf);
+ if (tid) {
+ seqno = tid->seq_next;
+ hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
+ INCR(tid->seq_next, IEEE80211_SEQ_MAX);
+ bf->bf_state.seqno = seqno;
+ }
+
bf->bf_flags = setup_tx_flags(skb);
bf->bf_mpdu = skb;
@@ -1773,15 +1782,15 @@ static struct ath_buf *ath_tx_setup_buff
}
/* FIXME: tx power */
-static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
+static int ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
struct ath_tx_control *txctl)
{
- struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct list_head bf_head;
struct ath_atx_tid *tid = NULL;
- u16 seqno;
+ struct ath_buf *bf;
+ int ret = 0;
u8 tidno;
spin_lock_bh(&txctl->txq->axq_lock);
@@ -1791,15 +1800,15 @@ static void ath_tx_start_dma(struct ath_
IEEE80211_QOS_CTL_TID_MASK;
tid = ATH_AN_2_TID(txctl->an, tidno);
- seqno = tid->seq_next;
- hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
- INCR(tid->seq_next, IEEE80211_SEQ_MAX);
-
- bf->bf_state.seqno = seqno;
-
WARN_ON(tid->ac->txq != txctl->txq);
}
+ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
+ if (unlikely(!bf)) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
/*
* Try aggregation if it's a unicast data frame
@@ -1825,7 +1834,9 @@ static void ath_tx_start_dma(struct ath_
ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);
}
+out:
spin_unlock_bh(&txctl->txq->axq_lock);
+ return ret;
}
/* Upon failure caller should free skb */
@@ -1838,7 +1849,6 @@ int ath_tx_start(struct ieee80211_hw *hw
struct ieee80211_vif *vif = info->control.vif;
struct ath_softc *sc = hw->priv;
struct ath_txq *txq = txctl->txq;
- struct ath_buf *bf;
int padpos, padsize;
int frmlen = skb->len + FCS_LEN;
int q;
@@ -1885,10 +1895,6 @@ int ath_tx_start(struct ieee80211_hw *hw
* info are no longer valid (overwritten by the ath_frame_info data.
*/
- bf = ath_tx_setup_buffer(hw, txctl->txq, skb);
- if (unlikely(!bf))
- return -ENOMEM;
-
q = skb_get_queue_mapping(skb);
spin_lock_bh(&txq->axq_lock);
if (txq == sc->tx.txq_map[q] &&
@@ -1898,9 +1904,7 @@ int ath_tx_start(struct ieee80211_hw *hw
}
spin_unlock_bh(&txq->axq_lock);
- ath_tx_start_dma(sc, bf, txctl);
-
- return 0;
+ return ath_tx_start_dma(sc, skb, txctl);
}
/*****************/

@ -1,264 +0,0 @@
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -48,8 +48,9 @@ static u16 bits_per_symbol[][2] = {
#define IS_HT_RATE(_rate) ((_rate) & 0x80)
static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_atx_tid *tid,
- struct list_head *bf_head);
+ struct ath_atx_tid *tid, struct sk_buff *skb);
+static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
+ int tx_flags, struct ath_txq *txq);
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
struct ath_txq *txq, struct list_head *bf_q,
struct ath_tx_status *ts, int txok, int sendbar);
@@ -61,6 +62,10 @@ static void ath_tx_rc_status(struct ath_
int txok, bool update_rc);
static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
int seqno);
+static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
+ struct ath_txq *txq,
+ struct ath_atx_tid *tid,
+ struct sk_buff *skb);
enum {
MCS_HT20,
@@ -164,14 +169,13 @@ static void ath_tx_flush_tid(struct ath_
fi = get_frame_info(skb);
bf = fi->bf;
- list_add_tail(&bf->list, &bf_head);
-
spin_unlock_bh(&txq->axq_lock);
- if (fi->retries) {
+ if (bf && fi->retries) {
+ list_add_tail(&bf->list, &bf_head);
ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
} else {
- ath_tx_send_normal(sc, txq, NULL, &bf_head);
+ ath_tx_send_normal(sc, txq, NULL, skb);
}
spin_lock_bh(&txq->axq_lock);
}
@@ -234,6 +238,13 @@ static void ath_tid_drain(struct ath_sof
fi = get_frame_info(skb);
bf = fi->bf;
+ if (!bf) {
+ spin_unlock(&txq->axq_lock);
+ ath_tx_complete(sc, skb, ATH_TX_ERROR, txq);
+ spin_lock(&txq->axq_lock);
+ continue;
+ }
+
list_add_tail(&bf->list, &bf_head);
if (fi->retries)
@@ -760,8 +771,14 @@ static enum ATH_AGGR_STATUS ath_tx_form_
skb = skb_peek(&tid->buf_q);
fi = get_frame_info(skb);
bf = fi->bf;
- seqno = bf->bf_state.seqno;
+ if (!fi->bf)
+ bf = ath_tx_setup_buffer(sc, txq, tid, skb);
+ if (!bf)
+ continue;
+
+ bf->bf_state.bf_type |= BUF_AMPDU;
+ seqno = bf->bf_state.seqno;
if (!bf_first)
bf_first = bf;
@@ -1434,13 +1451,11 @@ static void ath_tx_txqaddbuf(struct ath_
}
static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
- struct ath_buf *bf, struct ath_tx_control *txctl)
+ struct sk_buff *skb, struct ath_tx_control *txctl)
{
- struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
+ struct ath_frame_info *fi = get_frame_info(skb);
struct list_head bf_head;
- u16 seqno = bf->bf_state.seqno;
-
- bf->bf_state.bf_type |= BUF_AMPDU;
+ struct ath_buf *bf;
/*
* Do not queue to h/w when any of the following conditions is true:
@@ -1450,25 +1465,29 @@ static void ath_tx_send_ampdu(struct ath
* - h/w queue depth exceeds low water mark
*/
if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
- !BAW_WITHIN(tid->seq_start, tid->baw_size, seqno) ||
+ !BAW_WITHIN(tid->seq_start, tid->baw_size, tid->seq_next) ||
txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
/*
* Add this frame to software queue for scheduling later
* for aggregation.
*/
TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
- __skb_queue_tail(&tid->buf_q, bf->bf_mpdu);
+ __skb_queue_tail(&tid->buf_q, skb);
if (!txctl->an || !txctl->an->sleeping)
ath_tx_queue_tid(txctl->txq, tid);
return;
}
+ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
+ if (!bf)
+ return;
+
+ bf->bf_state.bf_type |= BUF_AMPDU;
INIT_LIST_HEAD(&bf_head);
list_add(&bf->list, &bf_head);
/* Add sub-frame to BAW */
- if (!fi->retries)
- ath_tx_addto_baw(sc, tid, seqno);
+ ath_tx_addto_baw(sc, tid, bf->bf_state.seqno);
/* Queue to h/w without aggregation */
TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
@@ -1478,13 +1497,21 @@ static void ath_tx_send_ampdu(struct ath
}
static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_atx_tid *tid,
- struct list_head *bf_head)
+ struct ath_atx_tid *tid, struct sk_buff *skb)
{
- struct ath_frame_info *fi;
+ struct ath_frame_info *fi = get_frame_info(skb);
+ struct list_head bf_head;
struct ath_buf *bf;
- bf = list_first_entry(bf_head, struct ath_buf, list);
+ bf = fi->bf;
+ if (!bf)
+ bf = ath_tx_setup_buffer(sc, txq, tid, skb);
+
+ if (!bf)
+ return;
+
+ INIT_LIST_HEAD(&bf_head);
+ list_add_tail(&bf->list, &bf_head);
bf->bf_state.bf_type &= ~BUF_AMPDU;
/* update starting sequence number for subsequent ADDBA request */
@@ -1492,9 +1519,8 @@ static void ath_tx_send_normal(struct at
INCR(tid->seq_start, IEEE80211_SEQ_MAX);
bf->bf_lastbf = bf;
- fi = get_frame_info(bf->bf_mpdu);
ath_buf_set_rate(sc, bf, fi->framelen);
- ath_tx_txqaddbuf(sc, txq, bf_head, false);
+ ath_tx_txqaddbuf(sc, txq, &bf_head, false);
TX_STAT_INC(txq->axq_qnum, queued);
}
@@ -1717,6 +1743,10 @@ static void ath_buf_set_rate(struct ath_
}
+/*
+ * Assign a descriptor (and sequence number if necessary,
+ * and map buffer for DMA. Frees skb on error
+ */
static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
struct ath_txq *txq,
struct ath_atx_tid *tid,
@@ -1734,7 +1764,7 @@ static struct ath_buf *ath_tx_setup_buff
bf = ath_tx_get_buffer(sc);
if (!bf) {
ath_dbg(common, ATH_DBG_XMIT, "TX buffers are full\n");
- return NULL;
+ goto error;
}
ATH_TXBUF_RESET(bf);
@@ -1757,7 +1787,7 @@ static struct ath_buf *ath_tx_setup_buff
ath_err(ath9k_hw_common(sc->sc_ah),
"dma_mapping_error() on TX\n");
ath_tx_return_buffer(sc, bf);
- return NULL;
+ goto error;
}
frm_type = get_hw_packet_type(skb);
@@ -1779,18 +1809,20 @@ static struct ath_buf *ath_tx_setup_buff
fi->bf = bf;
return bf;
+
+error:
+ dev_kfree_skb_any(skb);
+ return NULL;
}
/* FIXME: tx power */
-static int ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
+static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
struct ath_tx_control *txctl)
{
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct list_head bf_head;
struct ath_atx_tid *tid = NULL;
struct ath_buf *bf;
- int ret = 0;
u8 tidno;
spin_lock_bh(&txctl->txq->axq_lock);
@@ -1803,21 +1835,16 @@ static int ath_tx_start_dma(struct ath_s
WARN_ON(tid->ac->txq != txctl->txq);
}
- bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
- if (unlikely(!bf)) {
- ret = -ENOMEM;
- goto out;
- }
-
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
/*
* Try aggregation if it's a unicast data frame
* and the destination is HT capable.
*/
- ath_tx_send_ampdu(sc, tid, bf, txctl);
+ ath_tx_send_ampdu(sc, tid, skb, txctl);
} else {
- INIT_LIST_HEAD(&bf_head);
- list_add_tail(&bf->list, &bf_head);
+ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
+ if (!bf)
+ goto out;
bf->bf_state.bfs_paprd = txctl->paprd;
@@ -1831,12 +1858,11 @@ static int ath_tx_start_dma(struct ath_s
if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
- ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);
+ ath_tx_send_normal(sc, txctl->txq, tid, skb);
}
out:
spin_unlock_bh(&txctl->txq->axq_lock);
- return ret;
}
/* Upon failure caller should free skb */
@@ -1904,7 +1930,8 @@ int ath_tx_start(struct ieee80211_hw *hw
}
spin_unlock_bh(&txq->axq_lock);
- return ath_tx_start_dma(sc, skb, txctl);
+ ath_tx_start_dma(sc, skb, txctl);
+ return 0;
}
/*****************/

@ -1,24 +0,0 @@
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -709,7 +709,9 @@ static int ath_compute_num_delims(struct
* Add delimiter when using RTS/CTS with aggregation
* and non enterprise AR9003 card
*/
- if (first_subfrm)
+ if (first_subfrm && (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
+ !AR_SREV_9580_10_OR_LATER(sc->sc_ah) &&
+ (sc->sc_ah->ent_mode & AR_ENT_OTP_MIN_PKT_SIZE_DISABLE))
ndelim = max(ndelim, FIRST_DESC_NDELIMS);
/*
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -1132,7 +1132,7 @@ enum {
#define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4)
#define AR_ENT_OTP 0x40d8
#define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000
-#define AR_ENT_OTP_MPSD 0x00800000
+#define AR_ENT_OTP_MIN_PKT_SIZE_DISABLE 0x00800000
#define AR_CH0_BB_DPLL1 0x16180
#define AR_CH0_BB_DPLL1_REFDIV 0xF8000000

@ -1,19 +0,0 @@
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -263,6 +263,7 @@ static void ath_tx_set_retry(struct ath_
struct sk_buff *skb)
{
struct ath_frame_info *fi = get_frame_info(skb);
+ struct ath_buf *bf = fi->bf;
struct ieee80211_hdr *hdr;
TX_STAT_INC(txq->axq_qnum, a_retries);
@@ -271,6 +272,8 @@ static void ath_tx_set_retry(struct ath_
hdr = (struct ieee80211_hdr *)skb->data;
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
+ dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
+ sizeof(*hdr), DMA_TO_DEVICE);
}
static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)

@ -1,103 +0,0 @@
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -84,6 +84,8 @@ enum ieee80211_sta_info_flags {
* @stop_initiator: initiator of a session stop
* @tx_stop: TX DelBA frame when stopping
* @buf_size: reorder buffer size at receiver
+ * @failed_bar_ssn: ssn of the last failed BAR tx attempt
+ * @bar_pending: BAR needs to be re-sent
*
* This structure's lifetime is managed by RCU, assignments to
* the array holding it must hold the aggregation mutex.
@@ -104,6 +106,9 @@ struct tid_ampdu_tx {
u8 stop_initiator;
bool tx_stop;
u8 buf_size;
+
+ u16 failed_bar_ssn;
+ bool bar_pending;
};
/**
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -127,12 +127,32 @@ static void ieee80211_handle_filtered_fr
dev_kfree_skb(skb);
}
+static void ieee80211_check_pending_bar(struct sta_info *sta, u8 *addr, u8 tid)
+{
+ struct tid_ampdu_tx *tid_tx;
+
+ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
+ if (!tid_tx || !tid_tx->bar_pending)
+ return;
+
+ tid_tx->bar_pending = false;
+ ieee80211_send_bar(sta->sdata, addr, tid, tid_tx->failed_bar_ssn);
+}
+
static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
{
struct ieee80211_mgmt *mgmt = (void *) skb->data;
struct ieee80211_local *local = sta->local;
struct ieee80211_sub_if_data *sdata = sta->sdata;
+ if (ieee80211_is_data_qos(mgmt->frame_control)) {
+ struct ieee80211_hdr *hdr = (void *) skb->data;
+ u8 *qc = ieee80211_get_qos_ctl(hdr);
+ u16 tid = qc[0] & 0xf;
+
+ ieee80211_check_pending_bar(sta, hdr->addr1, tid);
+ }
+
if (ieee80211_is_action(mgmt->frame_control) &&
sdata->vif.type == NL80211_IFTYPE_STATION &&
mgmt->u.action.category == WLAN_CATEGORY_HT &&
@@ -161,6 +181,18 @@ static void ieee80211_frame_acked(struct
}
}
+static void ieee80211_set_bar_pending(struct sta_info *sta, u8 tid, u16 ssn)
+{
+ struct tid_ampdu_tx *tid_tx;
+
+ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
+ if (!tid_tx)
+ return;
+
+ tid_tx->failed_bar_ssn = ssn;
+ tid_tx->bar_pending = true;
+}
+
/*
* Use a static threshold for now, best value to be determined
* by testing ...
@@ -246,6 +278,8 @@ void ieee80211_tx_status(struct ieee8021
}
if (!acked && ieee80211_is_back_req(fc)) {
+ u16 control;
+
/*
* BAR failed, let's tear down the BA session as a
* last resort as some STAs (Intel 5100 on Windows)
@@ -253,11 +287,15 @@ void ieee80211_tx_status(struct ieee8021
* correctly.
*/
bar = (struct ieee80211_bar *) skb->data;
- if (!(bar->control & IEEE80211_BAR_CTRL_MULTI_TID)) {
- tid = (bar->control &
+ control = le16_to_cpu(bar->control);
+ if (!(control & IEEE80211_BAR_CTRL_MULTI_TID)) {
+ u16 ssn = le16_to_cpu(bar->start_seq_num);
+
+ tid = (control &
IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
- ieee80211_stop_tx_ba_session(&sta->sta, tid);
+
+ ieee80211_set_bar_pending(sta, tid, ssn);
}
}

@ -0,0 +1,167 @@
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -70,6 +70,8 @@ struct minstrel_mcs_group_data {
};
struct minstrel_ht_sta {
+ struct ieee80211_tx_rate tx_rates[3];
+
/* ampdu length (average, per sampling interval) */
unsigned int ampdu_len;
unsigned int ampdu_packets;
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -87,6 +87,10 @@ const struct mcs_group minstrel_mcs_grou
static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES];
+static void
+minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
+ struct ieee80211_tx_rate *rate, int index,
+ bool sample, bool rtscts);
/*
* Perform EWMA (Exponentially Weighted Moving Average) calculation
*/
@@ -174,6 +178,17 @@ minstrel_ht_calc_tp(struct minstrel_priv
mr->cur_tp = MINSTREL_TRUNC((1000000 / usecs) * mr->probability);
}
+static void
+minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
+{
+ minstrel_ht_set_rate(mp, mi, &mi->tx_rates[0], mi->max_tp_rate,
+ false, false);
+ minstrel_ht_set_rate(mp, mi, &mi->tx_rates[1], mi->max_tp_rate2,
+ false, true);
+ minstrel_ht_set_rate(mp, mi, &mi->tx_rates[2], mi->max_prob_rate,
+ false, true);
+}
+
/*
* Update rate statistics and select new primary rates
*
@@ -292,6 +307,7 @@ minstrel_ht_update_stats(struct minstrel
}
}
+ minstrel_ht_update_rates(mp, mi);
mi->stats_update = jiffies;
}
@@ -330,8 +346,8 @@ minstrel_next_sample_idx(struct minstrel
}
static void
-minstrel_downgrade_rate(struct minstrel_ht_sta *mi, unsigned int *idx,
- bool primary)
+minstrel_downgrade_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
+ unsigned int *idx, bool primary)
{
int group, orig_group;
@@ -350,6 +366,7 @@ minstrel_downgrade_rate(struct minstrel_
*idx = mi->groups[group].max_tp_rate;
else
*idx = mi->groups[group].max_tp_rate2;
+ minstrel_ht_update_rates(mp, mi);
break;
}
}
@@ -450,13 +467,13 @@ minstrel_ht_tx_status(void *priv, struct
if (rate->attempts > 30 &&
MINSTREL_FRAC(rate->success, rate->attempts) <
MINSTREL_FRAC(20, 100))
- minstrel_downgrade_rate(mi, &mi->max_tp_rate, true);
+ minstrel_downgrade_rate(mp, mi, &mi->max_tp_rate, true);
rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate2);
if (rate2->attempts > 30 &&
MINSTREL_FRAC(rate2->success, rate2->attempts) <
MINSTREL_FRAC(20, 100))
- minstrel_downgrade_rate(mi, &mi->max_tp_rate2, false);
+ minstrel_downgrade_rate(mp, mi, &mi->max_tp_rate2, false);
if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
minstrel_ht_update_stats(mp, mi);
@@ -521,7 +538,6 @@ minstrel_calc_retransmit(struct minstrel
static void
minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
struct ieee80211_tx_rate *rate, int index,
- struct ieee80211_tx_rate_control *txrc,
bool sample, bool rtscts)
{
const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
@@ -609,6 +625,7 @@ minstrel_ht_get_rate(void *priv, struct
struct minstrel_priv *mp = priv;
int sample_idx;
bool sample = false;
+ int last = 0;
if (rate_control_send_low(sta, priv_sta, txrc))
return;
@@ -634,11 +651,10 @@ minstrel_ht_get_rate(void *priv, struct
if (sample_idx >= 0) {
sample = true;
minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
- txrc, true, false);
+ true, false);
info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
} else {
- minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate,
- txrc, false, false);
+ ar[0] = mi->tx_rates[0];
}
if (mp->hw->max_rates >= 3) {
@@ -648,33 +664,27 @@ minstrel_ht_get_rate(void *priv, struct
* max_tp_rate -> max_tp_rate2 -> max_prob_rate by default.
*/
if (sample_idx >= 0)
- minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
- txrc, false, false);
+ ar[1] = mi->tx_rates[0];
else
- 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, !sample);
+ ar[1] = mi->tx_rates[1];
- ar[3].count = 0;
- ar[3].idx = -1;
+ ar[2] = mi->tx_rates[2];
+ last = 3;
} else if (mp->hw->max_rates == 2) {
/*
* Only 2 tx rates supported, use
* sample_rate -> max_prob_rate for sampling and
* max_tp_rate -> max_prob_rate by default.
*/
- minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_prob_rate,
- txrc, false, !sample);
-
- ar[2].count = 0;
- ar[2].idx = -1;
+ ar[1] = mi->tx_rates[2];
+ last = 2;
} else {
/* Not using MRR, only use the first rate */
- ar[1].count = 0;
- ar[1].idx = -1;
+ last = 1;
+
}
+ ar[last].count = 0;
+ ar[last].idx = -1;
mi->total_packets++;
@@ -766,6 +776,7 @@ minstrel_ht_update_caps(void *priv, stru
if (!n_supported)
goto use_legacy;
+ minstrel_ht_update_rates(mp, mi);
return;
use_legacy:

@ -0,0 +1,96 @@
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2370,6 +2370,25 @@ static inline int ieee80211_sta_ps_trans
void ieee80211_sta_set_tim(struct ieee80211_sta *sta);
/**
+ * ieee80211_tx_status_sta - transmit status callback
+ *
+ * Call this function for all transmitted frames after they have been
+ * transmitted. It is permissible to not call this function for
+ * multicast frames but this can affect statistics.
+ *
+ * This function may not be called in IRQ context. Calls to this function
+ * for a single hardware must be synchronized against each other. Calls
+ * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe()
+ * may not be mixed for a single hardware.
+ *
+ * @hw: the hardware the frame was transmitted by
+ * @skb: the frame that was transmitted, owned by mac80211 after this call
+ * @sta: station for which the tx status is provided
+ */
+void ieee80211_tx_status_sta(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ieee80211_sta *sta);
+
+/**
* ieee80211_tx_status - transmit status callback
*
* Call this function for all transmitted frames after they have been
@@ -2384,8 +2403,11 @@ void ieee80211_sta_set_tim(struct ieee80
* @hw: the hardware the frame was transmitted by
* @skb: the frame that was transmitted, owned by mac80211 after this call
*/
-void ieee80211_tx_status(struct ieee80211_hw *hw,
- struct sk_buff *skb);
+static inline void ieee80211_tx_status(struct ieee80211_hw *hw,
+ struct sk_buff *skb)
+{
+ ieee80211_tx_status_sta(hw, skb, NULL);
+}
/**
* ieee80211_tx_status_ni - transmit status callback (in process context)
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -202,7 +202,8 @@ static void ieee80211_set_bar_pending(st
*/
#define STA_LOST_PKT_THRESHOLD 50
-void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
+void ieee80211_tx_status_sta(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ieee80211_sta *pubsta)
{
struct sk_buff *skb2;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -214,7 +215,7 @@ void ieee80211_tx_status(struct ieee8021
struct ieee80211_tx_status_rtap_hdr *rthdr;
struct ieee80211_sub_if_data *sdata;
struct net_device *prev_dev = NULL;
- struct sta_info *sta, *tmp;
+ struct sta_info *sta = NULL, *tmp, *tmp2;
int retry_count = -1, i;
int rates_idx = -1;
bool send_to_cooked;
@@ -244,11 +245,19 @@ void ieee80211_tx_status(struct ieee8021
sband = local->hw.wiphy->bands[info->band];
fc = hdr->frame_control;
- for_each_sta_info(local, hdr->addr1, sta, tmp) {
- /* skip wrong virtual interface */
- if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN))
- continue;
+ if (!pubsta) {
+ for_each_sta_info(local, hdr->addr1, tmp, tmp2) {
+ /* skip wrong virtual interface */
+ if (memcmp(hdr->addr2, tmp->sdata->vif.addr, ETH_ALEN))
+ continue;
+
+ sta = tmp;
+ }
+ } else {
+ sta = container_of(pubsta, struct sta_info, sta);
+ }
+ if (sta) {
acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) {
/*
@@ -497,7 +506,7 @@ void ieee80211_tx_status(struct ieee8021
rcu_read_unlock();
dev_kfree_skb(skb);
}
-EXPORT_SYMBOL(ieee80211_tx_status);
+EXPORT_SYMBOL(ieee80211_tx_status_sta);
void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)
{

@ -0,0 +1,121 @@
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -50,10 +50,12 @@ static u16 bits_per_symbol[][2] = {
static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
struct ath_atx_tid *tid, struct sk_buff *skb);
static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
- int tx_flags, struct ath_txq *txq);
+ int tx_flags, struct ath_txq *txq,
+ struct ieee80211_sta *sta);
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
struct ath_txq *txq, struct list_head *bf_q,
- struct ath_tx_status *ts, int txok, int sendbar);
+ struct ath_tx_status *ts, int txok, int sendbar,
+ struct ieee80211_sta *sta);
static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
struct list_head *head, bool internal);
static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
@@ -172,7 +174,8 @@ static void ath_tx_flush_tid(struct ath_
if (bf && fi->retries) {
list_add_tail(&bf->list, &bf_head);
ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0,
+ 1, NULL);
} else {
ath_tx_send_normal(sc, txq, NULL, skb);
}
@@ -239,7 +242,7 @@ static void ath_tid_drain(struct ath_sof
if (!bf) {
spin_unlock(&txq->axq_lock);
- ath_tx_complete(sc, skb, ATH_TX_ERROR, txq);
+ ath_tx_complete(sc, skb, ATH_TX_ERROR, txq, NULL);
spin_lock(&txq->axq_lock);
continue;
}
@@ -250,7 +253,7 @@ static void ath_tid_drain(struct ath_sof
ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
spin_unlock(&txq->axq_lock);
- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0, NULL);
spin_lock(&txq->axq_lock);
}
@@ -412,7 +415,7 @@ static void ath_tx_complete_aggr(struct
list_move_tail(&bf->list, &bf_head);
ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
- 0, 0);
+ 0, 0, NULL);
bf = bf_next;
}
@@ -520,7 +523,7 @@ static void ath_tx_complete_aggr(struct
}
ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
- !txfail, sendbar);
+ !txfail, sendbar, sta);
} else {
/* retry the un-acked ones */
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
@@ -540,7 +543,8 @@ static void ath_tx_complete_aggr(struct
ath_tx_complete_buf(sc, bf, txq,
&bf_head,
- ts, 0, 1);
+ ts, 0, 1,
+ sta);
break;
}
@@ -1465,7 +1469,8 @@ static void ath_drain_txq_list(struct at
ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
retry_tx);
else
- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0,
+ NULL);
spin_lock_bh(&txq->axq_lock);
}
}
@@ -1970,7 +1975,8 @@ int ath_tx_start(struct ieee80211_hw *hw
/*****************/
static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
- int tx_flags, struct ath_txq *txq)
+ int tx_flags, struct ath_txq *txq,
+ struct ieee80211_sta *sta)
{
struct ieee80211_hw *hw = sc->hw;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -2028,7 +2034,8 @@ static void ath_tx_complete(struct ath_s
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
struct ath_txq *txq, struct list_head *bf_q,
- struct ath_tx_status *ts, int txok, int sendbar)
+ struct ath_tx_status *ts, int txok, int sendbar,
+ struct ieee80211_sta *sta)
{
struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -2056,7 +2063,7 @@ static void ath_tx_complete_buf(struct a
complete(&sc->paprd_complete);
} else {
ath_debug_stat_tx(sc, bf, ts, txq, tx_flags);
- ath_tx_complete(sc, skb, tx_flags, txq);
+ ath_tx_complete(sc, skb, tx_flags, txq, sta);
}
/* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
* accidentally reference it later.
@@ -2145,7 +2152,7 @@ static void ath_tx_process_buffer(struct
if (!bf_isampdu(bf)) {
ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
- ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
+ ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0, NULL);
} else
ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);

@ -1,28 +0,0 @@
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -969,7 +969,7 @@ void ath9k_hw_init_global_settings(struc
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &common->hw->conf;
const struct ath9k_channel *chan = ah->curchan;
- int acktimeout;
+ int acktimeout, ctstimeout;
int slottime;
int sifstime;
int rx_lat = 0, tx_lat = 0, eifs = 0;
@@ -1029,6 +1029,7 @@ void ath9k_hw_init_global_settings(struc
/* As defined by IEEE 802.11-2007 17.3.8.6 */
acktimeout = slottime + sifstime + 3 * ah->coverage_class;
+ ctstimeout = acktimeout;
/*
* Workaround for early ACK timeouts, add an offset to match the
@@ -1043,7 +1044,7 @@ void ath9k_hw_init_global_settings(struc
ath9k_hw_set_sifs_time(ah, sifstime);
ath9k_hw_setslottime(ah, slottime);
ath9k_hw_set_ack_timeout(ah, acktimeout);
- ath9k_hw_set_cts_timeout(ah, acktimeout);
+ ath9k_hw_set_cts_timeout(ah, ctstimeout);
if (ah->globaltxtimeout != (u32) -1)
ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);

@ -0,0 +1,27 @@
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1512,7 +1512,8 @@ bool ath_drain_all_txq(struct ath_softc
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_txq *txq;
- int i, npend = 0;
+ int i;
+ u32 npend = 0;
if (sc->sc_flags & SC_OP_INVALID)
return true;
@@ -1524,11 +1525,12 @@ bool ath_drain_all_txq(struct ath_softc
if (!ATH_TXQ_SETUP(sc, i))
continue;
- npend += ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum);
+ if (ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum))
+ npend |= BIT(i);
}
if (npend)
- ath_err(common, "Failed to stop TX DMA!\n");
+ ath_err(common, "Failed to stop TX DMA, queues=%08x!\n", npend);
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (!ATH_TXQ_SETUP(sc, i))

@ -0,0 +1,122 @@
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -25,8 +25,10 @@ struct ath_buf;
#ifdef CONFIG_ATH9K_DEBUGFS
#define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++
+#define RESET_STAT_INC(sc, type) sc->debug.stats.reset[type]++
#else
#define TX_STAT_INC(q, c) do { } while (0)
+#define RESET_STAT_INC(sc, type) do { } while (0)
#endif
#ifdef CONFIG_ATH9K_DEBUGFS
@@ -171,10 +173,21 @@ struct ath_rx_stats {
u8 rs_antenna;
};
+enum ath_reset_type {
+ RESET_TYPE_BB_HANG,
+ RESET_TYPE_BB_WATCHDOG,
+ RESET_TYPE_FATAL_INT,
+ RESET_TYPE_TX_ERROR,
+ RESET_TYPE_TX_HANG,
+ RESET_TYPE_PLL_HANG,
+ __RESET_TYPE_MAX
+};
+
struct ath_stats {
struct ath_interrupt_stats istats;
struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
struct ath_rx_stats rxstats;
+ u32 reset[__RESET_TYPE_MAX];
};
#define ATH_DBG_MAX_SAMPLES 10
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -679,6 +679,14 @@ void ath9k_tasklet(unsigned long data)
if ((status & ATH9K_INT_FATAL) ||
(status & ATH9K_INT_BB_WATCHDOG)) {
+ enum ath_reset_type type;
+
+ if (status & ATH9K_INT_FATAL)
+ type = RESET_TYPE_FATAL_INT;
+ else
+ type = RESET_TYPE_BB_WATCHDOG;
+
+ RESET_STAT_INC(sc, type);
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
goto out;
}
@@ -995,8 +1003,10 @@ void ath_hw_check(struct work_struct *wo
ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
"busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
if (busy >= 99) {
- if (++sc->hw_busy_count >= 3)
+ if (++sc->hw_busy_count >= 3) {
+ RESET_STAT_INC(sc, RESET_TYPE_BB_HANG);
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+ }
} else if (busy >= 0)
sc->hw_busy_count = 0;
@@ -1016,6 +1026,7 @@ static void ath_hw_pll_rx_hang_check(str
/* Rx is hung for more than 500ms. Reset it */
ath_dbg(common, ATH_DBG_RESET,
"Possible RX hang, resetting");
+ RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG);
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
count = 0;
}
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -587,8 +587,10 @@ static void ath_tx_complete_aggr(struct
rcu_read_unlock();
- if (needreset)
+ if (needreset) {
+ RESET_STAT_INC(sc, RESET_TYPE_TX_ERROR);
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+ }
}
static bool ath_lookup_legacy(struct ath_buf *bf)
@@ -2270,6 +2272,7 @@ static void ath_tx_complete_poll_work(st
if (needreset) {
ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
"tx hung, resetting the chip\n");
+ RESET_STAT_INC(sc, RESET_TYPE_TX_HANG);
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
}
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -523,9 +523,22 @@ static ssize_t read_file_wiphy(struct fi
if (tmp & ATH9K_RX_FILTER_PHYRADAR)
len += snprintf(buf + len, sizeof(buf) - len, " PHYRADAR");
if (tmp & ATH9K_RX_FILTER_MCAST_BCAST_ALL)
- len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL\n");
- else
- len += snprintf(buf + len, sizeof(buf) - len, "\n");
+ len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL");
+
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "\n\nReset causes:\n"
+ " baseband hang: %d\n"
+ " baseband watchdog: %d\n"
+ " fatal hardware error interrupt: %d\n"
+ " tx hardware error: %d\n"
+ " tx path hang: %d\n"
+ " pll rx hang: %d\n",
+ sc->debug.stats.reset[RESET_TYPE_BB_HANG],
+ sc->debug.stats.reset[RESET_TYPE_BB_WATCHDOG],
+ sc->debug.stats.reset[RESET_TYPE_FATAL_INT],
+ sc->debug.stats.reset[RESET_TYPE_TX_ERROR],
+ sc->debug.stats.reset[RESET_TYPE_TX_HANG],
+ sc->debug.stats.reset[RESET_TYPE_PLL_HANG]);
if (len > sizeof(buf))
len = sizeof(buf);

@ -1,273 +0,0 @@
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -140,9 +140,6 @@ struct ath_common {
u8 curbssid[ETH_ALEN];
u8 bssidmask[ETH_ALEN];
- u8 tx_chainmask;
- u8 rx_chainmask;
-
u32 rx_bufsize;
u32 keymax;
--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
@@ -113,7 +113,7 @@ static int ar9003_get_training_power_5g(
if (delta > scale)
return -1;
- switch (get_streams(common->tx_chainmask)) {
+ switch (get_streams(ah->txchainmask)) {
case 1:
delta = 6;
break;
@@ -126,7 +126,7 @@ static int ar9003_get_training_power_5g(
default:
delta = 0;
ath_dbg(common, ATH_DBG_CALIBRATE,
- "Invalid tx-chainmask: %u\n", common->tx_chainmask);
+ "Invalid tx-chainmask: %u\n", ah->txchainmask);
}
power += delta;
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -318,7 +318,6 @@ static void ath_paprd_activate(struct at
{
struct ath_hw *ah = sc->sc_ah;
struct ath9k_hw_cal_data *caldata = ah->caldata;
- struct ath_common *common = ath9k_hw_common(ah);
int chain;
if (!caldata || !caldata->paprd_done)
@@ -327,7 +326,7 @@ static void ath_paprd_activate(struct at
ath9k_ps_wakeup(sc);
ar9003_paprd_enable(ah, false);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
- if (!(common->tx_chainmask & BIT(chain)))
+ if (!(ah->txchainmask & BIT(chain)))
continue;
ar9003_paprd_populate_single_table(ah, caldata, chain);
@@ -414,7 +413,7 @@ void ath_paprd_calibrate(struct work_str
memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
- if (!(common->tx_chainmask & BIT(chain)))
+ if (!(ah->txchainmask & BIT(chain)))
continue;
chain_ok = 0;
@@ -535,7 +534,7 @@ void ath_ani_calibrate(unsigned long dat
if (longcal || shortcal) {
common->ani.caldone =
ath9k_hw_calibrate(ah, ah->curchan,
- common->rx_chainmask, longcal);
+ ah->rxchainmask, longcal);
}
ath9k_ps_restore(sc);
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1488,9 +1488,6 @@ int ath9k_hw_reset(struct ath_hw *ah, st
u64 tsf = 0;
int i, r;
- ah->txchainmask = common->tx_chainmask;
- ah->rxchainmask = common->rx_chainmask;
-
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
return -EIO;
@@ -2108,6 +2105,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw
pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask);
pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask);
+ ah->txchainmask = pCap->tx_chainmask;
+ ah->rxchainmask = pCap->rx_chainmask;
ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1660,7 +1660,7 @@ u8 ath_txchainmask_reduction(struct ath_
static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len)
{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
struct ath9k_11n_rate_series series[4];
struct sk_buff *skb;
struct ieee80211_tx_info *tx_info;
@@ -1720,7 +1720,7 @@ static void ath_buf_set_rate(struct ath_
/* MCS rates */
series[i].Rate = rix | 0x80;
series[i].ChSel = ath_txchainmask_reduction(sc,
- common->tx_chainmask, series[i].Rate);
+ ah->txchainmask, series[i].Rate);
series[i].PktDuration = ath_pkt_duration(sc, rix, len,
is_40, is_sgi, is_sp);
if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
@@ -1745,10 +1745,10 @@ static void ath_buf_set_rate(struct ath_
}
if (bf->bf_state.bfs_paprd)
- series[i].ChSel = common->tx_chainmask;
+ series[i].ChSel = ah->txchainmask;
else
series[i].ChSel = ath_txchainmask_reduction(sc,
- common->tx_chainmask, series[i].Rate);
+ ah->txchainmask, series[i].Rate);
series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
phy, rate->bitrate * 100, len, rix, is_sp);
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -107,7 +107,7 @@ static void ath_beacon_setup(struct ath_
series[0].Tries = 1;
series[0].Rate = rate;
series[0].ChSel = ath_txchainmask_reduction(sc,
- common->tx_chainmask, series[0].Rate);
+ ah->txchainmask, series[0].Rate);
series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration,
series, 4, 0);
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -95,11 +95,11 @@ static ssize_t read_file_tx_chainmask(st
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
char buf[32];
unsigned int len;
- len = sprintf(buf, "0x%08x\n", common->tx_chainmask);
+ len = sprintf(buf, "0x%08x\n", ah->txchainmask);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -107,7 +107,7 @@ static ssize_t write_file_tx_chainmask(s
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
unsigned long mask;
char buf[32];
ssize_t len;
@@ -120,8 +120,8 @@ static ssize_t write_file_tx_chainmask(s
if (strict_strtoul(buf, 0, &mask))
return -EINVAL;
- common->tx_chainmask = mask;
- sc->sc_ah->caps.tx_chainmask = mask;
+ ah->txchainmask = mask;
+ ah->caps.tx_chainmask = mask;
return count;
}
@@ -138,11 +138,11 @@ static ssize_t read_file_rx_chainmask(st
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
char buf[32];
unsigned int len;
- len = sprintf(buf, "0x%08x\n", common->rx_chainmask);
+ len = sprintf(buf, "0x%08x\n", ah->rxchainmask);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -150,7 +150,7 @@ static ssize_t write_file_rx_chainmask(s
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
unsigned long mask;
char buf[32];
ssize_t len;
@@ -163,8 +163,8 @@ static ssize_t write_file_rx_chainmask(s
if (strict_strtoul(buf, 0, &mask))
return -EINVAL;
- common->rx_chainmask = mask;
- sc->sc_ah->caps.rx_chainmask = mask;
+ ah->rxchainmask = mask;
+ ah->caps.rx_chainmask = mask;
return count;
}
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -509,8 +509,8 @@ static void setup_ht_cap(struct ath9k_ht
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
/* ath9k_htc supports only 1 or 2 stream devices */
- tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2);
- rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2);
+ tx_streams = ath9k_cmn_count_streams(priv->ah->txchainmask, 2);
+ rx_streams = ath9k_cmn_count_streams(priv->ah->rxchainmask, 2);
ath_dbg(common, ATH_DBG_CONFIG,
"TX streams %d, RX streams: %d\n",
@@ -601,9 +601,6 @@ static void ath9k_init_misc(struct ath9k
{
struct ath_common *common = ath9k_hw_common(priv->ah);
- common->tx_chainmask = priv->ah->caps.tx_chainmask;
- common->rx_chainmask = priv->ah->caps.rx_chainmask;
-
memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
priv->ah->opmode = NL80211_IFTYPE_STATION;
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -826,8 +826,7 @@ void ath9k_htc_ani_work(struct work_stru
if (longcal || shortcal)
common->ani.caldone =
ath9k_hw_calibrate(ah, ah->curchan,
- common->rx_chainmask,
- longcal);
+ ah->rxchainmask, longcal);
ath9k_htc_ps_restore(priv);
}
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -270,8 +270,8 @@ static void setup_ht_cap(struct ath_soft
/* set up supported mcs set */
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
- tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams);
- rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams);
+ tx_streams = ath9k_cmn_count_streams(ah->txchainmask, max_streams);
+ rx_streams = ath9k_cmn_count_streams(ah->rxchainmask, max_streams);
ath_dbg(common, ATH_DBG_CONFIG,
"TX streams %d, RX streams: %d\n",
@@ -506,9 +506,6 @@ static void ath9k_init_misc(struct ath_s
sc->sc_flags |= SC_OP_RXAGGR;
}
- common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
- common->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
-
ath9k_hw_set_diversity(sc->sc_ah, true);
sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
@@ -645,10 +642,8 @@ static void ath9k_init_band_txpower(stru
static void ath9k_init_txpower_limits(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath9k_channel *curchan = ah->curchan;
- ah->txchainmask = common->tx_chainmask;
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)

@ -1,298 +0,0 @@
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -429,6 +429,7 @@ void ath9k_set_beaconing_status(struct a
#define ATH_PAPRD_TIMEOUT 100 /* msecs */
+void ath_reset_work(struct work_struct *work);
void ath_hw_check(struct work_struct *work);
void ath_hw_pll_work(struct work_struct *work);
void ath_paprd_calibrate(struct work_struct *work);
@@ -609,6 +610,7 @@ struct ath_softc {
struct mutex mutex;
struct work_struct paprd_work;
struct work_struct hw_check_work;
+ struct work_struct hw_reset_work;
struct completion paprd_complete;
unsigned int hw_busy_count;
@@ -655,7 +657,6 @@ struct ath_softc {
};
void ath9k_tasklet(unsigned long data);
-int ath_reset(struct ath_softc *sc, bool retry_tx);
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
@@ -386,9 +386,7 @@ void ath_beacon_tasklet(unsigned long da
ath_dbg(common, ATH_DBG_BSTUCK,
"beacon is officially stuck\n");
sc->sc_flags |= SC_OP_TSF_RESET;
- spin_lock(&sc->sc_pcu_lock);
- ath_reset(sc, true);
- spin_unlock(&sc->sc_pcu_lock);
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
}
return;
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -776,6 +776,7 @@ int ath9k_init_device(u16 devid, struct
goto error_world;
}
+ INIT_WORK(&sc->hw_reset_work, ath_reset_work);
INIT_WORK(&sc->hw_check_work, ath_hw_check);
INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -236,6 +236,7 @@ static int ath_set_channel(struct ath_so
del_timer_sync(&common->ani.timer);
cancel_work_sync(&sc->paprd_work);
cancel_work_sync(&sc->hw_check_work);
+ cancel_work_sync(&sc->hw_reset_work);
cancel_delayed_work_sync(&sc->tx_complete_work);
cancel_delayed_work_sync(&sc->hw_pll_work);
@@ -595,74 +596,6 @@ static void ath_node_detach(struct ath_s
ath_tx_node_cleanup(sc, an);
}
-void ath_hw_check(struct work_struct *work)
-{
- struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- unsigned long flags;
- int busy;
-
- ath9k_ps_wakeup(sc);
- if (ath9k_hw_check_alive(sc->sc_ah))
- goto out;
-
- spin_lock_irqsave(&common->cc_lock, flags);
- busy = ath_update_survey_stats(sc);
- spin_unlock_irqrestore(&common->cc_lock, flags);
-
- ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
- "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
- if (busy >= 99) {
- if (++sc->hw_busy_count >= 3) {
- spin_lock_bh(&sc->sc_pcu_lock);
- ath_reset(sc, true);
- spin_unlock_bh(&sc->sc_pcu_lock);
- }
- } else if (busy >= 0)
- sc->hw_busy_count = 0;
-
-out:
- ath9k_ps_restore(sc);
-}
-
-static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
-{
- static int count;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-
- if (pll_sqsum >= 0x40000) {
- count++;
- if (count == 3) {
- /* Rx is hung for more than 500ms. Reset it */
- ath_dbg(common, ATH_DBG_RESET,
- "Possible RX hang, resetting");
- spin_lock_bh(&sc->sc_pcu_lock);
- ath_reset(sc, true);
- spin_unlock_bh(&sc->sc_pcu_lock);
- count = 0;
- }
- } else
- count = 0;
-}
-
-void ath_hw_pll_work(struct work_struct *work)
-{
- struct ath_softc *sc = container_of(work, struct ath_softc,
- hw_pll_work.work);
- u32 pll_sqsum;
-
- if (AR_SREV_9485(sc->sc_ah)) {
-
- ath9k_ps_wakeup(sc);
- pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
- ath9k_ps_restore(sc);
-
- ath_hw_pll_rx_hang_check(sc, pll_sqsum);
-
- ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
- }
-}
-
void ath9k_tasklet(unsigned long data)
{
@@ -675,9 +608,7 @@ void ath9k_tasklet(unsigned long data)
if ((status & ATH9K_INT_FATAL) ||
(status & ATH9K_INT_BB_WATCHDOG)) {
- spin_lock(&sc->sc_pcu_lock);
- ath_reset(sc, true);
- spin_unlock(&sc->sc_pcu_lock);
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
return;
}
@@ -968,7 +899,7 @@ void ath_radio_disable(struct ath_softc
ath9k_ps_restore(sc);
}
-int ath_reset(struct ath_softc *sc, bool retry_tx)
+static int ath_reset(struct ath_softc *sc, bool retry_tx)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
@@ -1035,6 +966,84 @@ int ath_reset(struct ath_softc *sc, bool
return r;
}
+void ath_reset_work(struct work_struct *work)
+{
+ struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
+
+ spin_lock_bh(&sc->sc_pcu_lock);
+ ath_reset(sc, true);
+ spin_unlock_bh(&sc->sc_pcu_lock);
+}
+
+void ath_hw_check(struct work_struct *work)
+{
+ struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ unsigned long flags;
+ int busy;
+
+ ath9k_ps_wakeup(sc);
+ if (ath9k_hw_check_alive(sc->sc_ah))
+ goto out;
+
+ spin_lock_irqsave(&common->cc_lock, flags);
+ busy = ath_update_survey_stats(sc);
+ spin_unlock_irqrestore(&common->cc_lock, flags);
+
+ ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
+ "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
+ if (busy >= 99) {
+ if (++sc->hw_busy_count >= 3) {
+ spin_lock_bh(&sc->sc_pcu_lock);
+ ath_reset(sc, true);
+ spin_unlock_bh(&sc->sc_pcu_lock);
+ }
+
+ } else if (busy >= 0)
+ sc->hw_busy_count = 0;
+
+out:
+ ath9k_ps_restore(sc);
+}
+
+static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
+{
+ static int count;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+ if (pll_sqsum >= 0x40000) {
+ count++;
+ if (count == 3) {
+ /* Rx is hung for more than 500ms. Reset it */
+ ath_dbg(common, ATH_DBG_RESET,
+ "Possible RX hang, resetting");
+ spin_lock_bh(&sc->sc_pcu_lock);
+ ath_reset(sc, true);
+ spin_unlock_bh(&sc->sc_pcu_lock);
+ count = 0;
+ }
+ } else
+ count = 0;
+}
+
+void ath_hw_pll_work(struct work_struct *work)
+{
+ struct ath_softc *sc = container_of(work, struct ath_softc,
+ hw_pll_work.work);
+ u32 pll_sqsum;
+
+ if (AR_SREV_9485(sc->sc_ah)) {
+
+ ath9k_ps_wakeup(sc);
+ pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
+ ath9k_ps_restore(sc);
+
+ ath_hw_pll_rx_hang_check(sc, pll_sqsum);
+
+ ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
+ }
+}
+
/**********************/
/* mac80211 callbacks */
/**********************/
@@ -1227,6 +1236,7 @@ static void ath9k_stop(struct ieee80211_
cancel_delayed_work_sync(&sc->hw_pll_work);
cancel_work_sync(&sc->paprd_work);
cancel_work_sync(&sc->hw_check_work);
+ cancel_work_sync(&sc->hw_reset_work);
if (sc->sc_flags & SC_OP_INVALID) {
ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -604,7 +604,7 @@ static void ath_tx_complete_aggr(struct
rcu_read_unlock();
if (needreset)
- ath_reset(sc, false);
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
}
static bool ath_lookup_legacy(struct ath_buf *bf)
@@ -1357,7 +1357,7 @@ void ath_txq_schedule(struct ath_softc *
struct ath_atx_ac *ac, *ac_tmp, *last_ac;
struct ath_atx_tid *tid, *last_tid;
- if (list_empty(&txq->axq_acq) ||
+ if (work_pending(&sc->hw_reset_work) || list_empty(&txq->axq_acq) ||
txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
return;
@@ -2184,6 +2184,9 @@ static void ath_tx_processq(struct ath_s
spin_lock_bh(&txq->axq_lock);
for (;;) {
+ if (work_pending(&sc->hw_reset_work))
+ break;
+
if (list_empty(&txq->axq_q)) {
txq->axq_link = NULL;
if (sc->sc_flags & SC_OP_TXAGGR)
@@ -2271,9 +2274,7 @@ static void ath_tx_complete_poll_work(st
if (needreset) {
ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
"tx hung, resetting the chip\n");
- spin_lock_bh(&sc->sc_pcu_lock);
- ath_reset(sc, true);
- spin_unlock_bh(&sc->sc_pcu_lock);
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
}
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
@@ -2306,6 +2307,9 @@ void ath_tx_edma_tasklet(struct ath_soft
int status;
for (;;) {
+ if (work_pending(&sc->hw_reset_work))
+ break;
+
status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
if (status == -EINPROGRESS)
break;

@ -1,448 +0,0 @@
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -212,84 +212,57 @@ static int ath_update_survey_stats(struc
return ret;
}
-/*
- * Set/change channels. If the channel is really being changed, it's done
- * by reseting the chip. To accomplish this we must first cleanup any pending
- * DMA, then restart stuff.
-*/
-static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
- struct ath9k_channel *hchan)
+static void __ath_cancel_work(struct ath_softc *sc)
{
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_conf *conf = &common->hw->conf;
- bool fastcc = true, stopped;
- struct ieee80211_channel *channel = hw->conf.channel;
- struct ath9k_hw_cal_data *caldata = NULL;
- int r;
-
- if (sc->sc_flags & SC_OP_INVALID)
- return -EIO;
-
- sc->hw_busy_count = 0;
-
- del_timer_sync(&common->ani.timer);
cancel_work_sync(&sc->paprd_work);
cancel_work_sync(&sc->hw_check_work);
- cancel_work_sync(&sc->hw_reset_work);
cancel_delayed_work_sync(&sc->tx_complete_work);
cancel_delayed_work_sync(&sc->hw_pll_work);
+}
- ath9k_ps_wakeup(sc);
+static void ath_cancel_work(struct ath_softc *sc)
+{
+ __ath_cancel_work(sc);
+ cancel_work_sync(&sc->hw_reset_work);
+}
- spin_lock_bh(&sc->sc_pcu_lock);
+static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ bool ret;
- /*
- * This is only performed if the channel settings have
- * actually changed.
- *
- * To switch channels clear any pending DMA operations;
- * wait long enough for the RX fifo to drain, reset the
- * hardware at the new frequency, and then re-enable
- * the relevant bits of the h/w.
- */
- ath9k_hw_disable_interrupts(ah);
- stopped = ath_drain_all_txq(sc, false);
+ ieee80211_stop_queues(sc->hw);
- if (!ath_stoprecv(sc))
- stopped = false;
+ sc->hw_busy_count = 0;
+ del_timer_sync(&common->ani.timer);
- if (!ath9k_hw_check_alive(ah))
- stopped = false;
+ ath9k_hw_disable_interrupts(ah);
- /* XXX: do not flush receive queue here. We don't want
- * to flush data frames already in queue because of
- * changing channel. */
+ ret = ath_drain_all_txq(sc, retry_tx);
- if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL))
- fastcc = false;
+ if (!ath_stoprecv(sc))
+ ret = false;
- if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
- caldata = &sc->caldata;
+ if (!flush) {
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+ ath_rx_tasklet(sc, 0, true);
+ ath_rx_tasklet(sc, 0, false);
+ } else {
+ ath_flushrecv(sc);
+ }
- ath_dbg(common, ATH_DBG_CONFIG,
- "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n",
- sc->sc_ah->curchan->channel,
- channel->center_freq, conf_is_ht40(conf),
- fastcc);
+ return ret;
+}
- r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
- if (r) {
- ath_err(common,
- "Unable to reset channel (%u MHz), reset status %d\n",
- channel->center_freq, r);
- goto ps_restore;
- }
+static bool ath_complete_reset(struct ath_softc *sc, bool start)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
if (ath_startrecv(sc) != 0) {
ath_err(common, "Unable to restart recv logic\n");
- r = -EIO;
- goto ps_restore;
+ return false;
}
ath9k_cmn_update_txpow(ah, sc->curtxpow,
@@ -297,21 +270,93 @@ static int ath_set_channel(struct ath_so
ath9k_hw_set_interrupts(ah, ah->imask);
ath9k_hw_enable_interrupts(ah);
- if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
+ if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) {
if (sc->sc_flags & SC_OP_BEACONS)
ath_set_beacon(sc);
+
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
if (!common->disable_ani)
ath_start_ani(common);
}
- ps_restore:
- ieee80211_wake_queues(hw);
+ ieee80211_wake_queues(sc->hw);
+
+ return true;
+}
+
+static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
+ bool retry_tx)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_hw_cal_data *caldata = NULL;
+ bool fastcc = true;
+ bool flush = false;
+ int r;
+
+ __ath_cancel_work(sc);
+
+ spin_lock_bh(&sc->sc_pcu_lock);
+ if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) {
+ fastcc = false;
+ caldata = &sc->caldata;
+ }
+
+ if (!hchan) {
+ fastcc = false;
+ flush = true;
+ hchan = ah->curchan;
+ }
+
+ if (fastcc && !ath9k_hw_check_alive(ah))
+ fastcc = false;
+
+ if (!ath_prepare_reset(sc, retry_tx, flush))
+ fastcc = false;
+
+ ath_dbg(common, ATH_DBG_CONFIG,
+ "Reset to %u MHz, HT40: %d fastcc: %d\n",
+ hchan->channel, !!(hchan->channelFlags & (CHANNEL_HT40MINUS |
+ CHANNEL_HT40PLUS)),
+ fastcc);
+
+ r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
+ if (r) {
+ ath_err(common,
+ "Unable to reset channel, reset status %d\n", r);
+ goto out;
+ }
+
+ if (!ath_complete_reset(sc, true))
+ r = -EIO;
+
+out:
spin_unlock_bh(&sc->sc_pcu_lock);
+ return r;
+}
+
+
+/*
+ * Set/change channels. If the channel is really being changed, it's done
+ * by reseting the chip. To accomplish this we must first cleanup any pending
+ * DMA, then restart stuff.
+*/
+static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
+ struct ath9k_channel *hchan)
+{
+ int r;
+
+ if (sc->sc_flags & SC_OP_INVALID)
+ return -EIO;
+
+ ath9k_ps_wakeup(sc);
+
+ r = ath_reset_internal(sc, hchan, false);
ath9k_ps_restore(sc);
+
return r;
}
@@ -824,28 +869,13 @@ static void ath_radio_enable(struct ath_
channel->center_freq, r);
}
- ath9k_cmn_update_txpow(ah, sc->curtxpow,
- sc->config.txpowlimit, &sc->curtxpow);
- if (ath_startrecv(sc) != 0) {
- ath_err(common, "Unable to restart recv logic\n");
- goto out;
- }
- if (sc->sc_flags & SC_OP_BEACONS)
- ath_set_beacon(sc); /* restart beacons */
-
- /* Re-Enable interrupts */
- ath9k_hw_set_interrupts(ah, ah->imask);
- ath9k_hw_enable_interrupts(ah);
+ ath_complete_reset(sc, true);
/* Enable LED */
ath9k_hw_cfg_output(ah, ah->led_pin,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
ath9k_hw_set_gpio(ah, ah->led_pin, 0);
- ieee80211_wake_queues(hw);
- ieee80211_queue_delayed_work(hw, &sc->hw_pll_work, HZ/2);
-
-out:
spin_unlock_bh(&sc->sc_pcu_lock);
ath9k_ps_restore(sc);
@@ -858,11 +888,10 @@ void ath_radio_disable(struct ath_softc
int r;
ath9k_ps_wakeup(sc);
- cancel_delayed_work_sync(&sc->hw_pll_work);
- spin_lock_bh(&sc->sc_pcu_lock);
+ ath_cancel_work(sc);
- ieee80211_stop_queues(hw);
+ spin_lock_bh(&sc->sc_pcu_lock);
/*
* Keep the LED on when the radio is disabled
@@ -873,13 +902,7 @@ void ath_radio_disable(struct ath_softc
ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
}
- /* Disable interrupts */
- 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 */
+ ath_prepare_reset(sc, false, true);
if (!ah->curchan)
ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
@@ -901,48 +924,11 @@ void ath_radio_disable(struct ath_softc
static int ath_reset(struct ath_softc *sc, bool retry_tx)
{
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_hw *hw = sc->hw;
int r;
- sc->hw_busy_count = 0;
-
- /* Stop ANI */
-
- del_timer_sync(&common->ani.timer);
-
ath9k_ps_wakeup(sc);
- ieee80211_stop_queues(hw);
-
- ath9k_hw_disable_interrupts(ah);
- ath_drain_all_txq(sc, retry_tx);
-
- ath_stoprecv(sc);
- ath_flushrecv(sc);
-
- r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
- if (r)
- ath_err(common,
- "Unable to reset hardware; reset status %d\n", r);
-
- if (ath_startrecv(sc) != 0)
- ath_err(common, "Unable to start recv logic\n");
-
- /*
- * We may be doing a reset in response to a request
- * that changes the channel so update any state that
- * might change as a result.
- */
- ath9k_cmn_update_txpow(ah, sc->curtxpow,
- sc->config.txpowlimit, &sc->curtxpow);
-
- if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
- ath_set_beacon(sc); /* restart beacons */
-
- ath9k_hw_set_interrupts(ah, ah->imask);
- ath9k_hw_enable_interrupts(ah);
+ r = ath_reset_internal(sc, NULL, retry_tx);
if (retry_tx) {
int i;
@@ -955,12 +941,6 @@ static int ath_reset(struct ath_softc *s
}
}
- ieee80211_wake_queues(hw);
-
- /* Start ANI */
- if (!common->disable_ani)
- ath_start_ani(common);
-
ath9k_ps_restore(sc);
return r;
@@ -970,9 +950,7 @@ void ath_reset_work(struct work_struct *
{
struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
- spin_lock_bh(&sc->sc_pcu_lock);
ath_reset(sc, true);
- spin_unlock_bh(&sc->sc_pcu_lock);
}
void ath_hw_check(struct work_struct *work)
@@ -993,11 +971,8 @@ void ath_hw_check(struct work_struct *wo
ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
"busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
if (busy >= 99) {
- if (++sc->hw_busy_count >= 3) {
- spin_lock_bh(&sc->sc_pcu_lock);
- ath_reset(sc, true);
- spin_unlock_bh(&sc->sc_pcu_lock);
- }
+ if (++sc->hw_busy_count >= 3)
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
} else if (busy >= 0)
sc->hw_busy_count = 0;
@@ -1017,9 +992,7 @@ static void ath_hw_pll_rx_hang_check(str
/* Rx is hung for more than 500ms. Reset it */
ath_dbg(common, ATH_DBG_RESET,
"Possible RX hang, resetting");
- spin_lock_bh(&sc->sc_pcu_lock);
- ath_reset(sc, true);
- spin_unlock_bh(&sc->sc_pcu_lock);
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
count = 0;
}
} else
@@ -1090,28 +1063,6 @@ static int ath9k_start(struct ieee80211_
goto mutex_unlock;
}
- /*
- * This is needed only to setup initial state
- * but it's best done after a reset.
- */
- ath9k_cmn_update_txpow(ah, sc->curtxpow,
- sc->config.txpowlimit, &sc->curtxpow);
-
- /*
- * Setup the hardware after reset:
- * The receive engine is set going.
- * Frame transmit is handled entirely
- * in the frame output path; there's nothing to do
- * here except setup the interrupt mask.
- */
- if (ath_startrecv(sc) != 0) {
- ath_err(common, "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 |
ATH9K_INT_RXORN | ATH9K_INT_FATAL |
@@ -1134,12 +1085,14 @@ static int ath9k_start(struct ieee80211_
/* Disable BMISS interrupt when we're not associated */
ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
- ath9k_hw_set_interrupts(ah, ah->imask);
- ath9k_hw_enable_interrupts(ah);
- ieee80211_wake_queues(hw);
+ if (!ath_complete_reset(sc, false)) {
+ r = -EIO;
+ spin_unlock_bh(&sc->sc_pcu_lock);
+ goto mutex_unlock;
+ }
- ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+ spin_unlock_bh(&sc->sc_pcu_lock);
if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
!ah->btcoex_hw.enabled) {
@@ -1232,11 +1185,7 @@ static void ath9k_stop(struct ieee80211_
mutex_lock(&sc->mutex);
- cancel_delayed_work_sync(&sc->tx_complete_work);
- cancel_delayed_work_sync(&sc->hw_pll_work);
- cancel_work_sync(&sc->paprd_work);
- cancel_work_sync(&sc->hw_check_work);
- cancel_work_sync(&sc->hw_reset_work);
+ ath_cancel_work(sc);
if (sc->sc_flags & SC_OP_INVALID) {
ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
@@ -2353,9 +2302,11 @@ static void ath9k_flush(struct ieee80211
ath9k_ps_wakeup(sc);
spin_lock_bh(&sc->sc_pcu_lock);
drain_txq = ath_drain_all_txq(sc, false);
+ spin_unlock_bh(&sc->sc_pcu_lock);
+
if (!drain_txq)
ath_reset(sc, false);
- spin_unlock_bh(&sc->sc_pcu_lock);
+
ath9k_ps_restore(sc);
ieee80211_wake_queues(hw);

@ -1,178 +0,0 @@
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -652,9 +652,22 @@ static void ath9k_init_txpower_limits(st
ah->curchan = curchan;
}
+void ath9k_reload_chainmask_settings(struct ath_softc *sc)
+{
+ if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT))
+ return;
+
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+ setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+ setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
+}
+
+
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
@@ -692,6 +705,16 @@ void ath9k_set_hw_capab(struct ath_softc
hw->sta_data_size = sizeof(struct ath_node);
hw->vif_data_size = sizeof(struct ath_vif);
+ hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
+ hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1;
+
+ /* single chain devices with rx diversity */
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
+ hw->wiphy->available_antennas_rx = BIT(0) | BIT(1);
+
+ sc->ant_rx = hw->wiphy->available_antennas_rx;
+ sc->ant_tx = hw->wiphy->available_antennas_tx;
+
#ifdef CONFIG_ATH9K_RATE_CONTROL
hw->rate_control_algorithm = "ath9k_rate_control";
#endif
@@ -703,12 +726,7 @@ void ath9k_set_hw_capab(struct ath_softc
hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
&sc->sbands[IEEE80211_BAND_5GHZ];
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
- setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
- setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
- }
+ ath9k_reload_chainmask_settings(sc);
SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
}
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -654,6 +654,7 @@ struct ath_softc {
struct ath_descdma txsdma;
struct ath_ant_comb ant_comb;
+ u8 ant_tx, ant_rx;
};
void ath9k_tasklet(unsigned long data);
@@ -674,6 +675,7 @@ int ath9k_init_device(u16 devid, struct
const struct ath_bus_ops *bus_ops);
void ath9k_deinit_device(struct ath_softc *sc);
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
+void ath9k_reload_chainmask_settings(struct ath_softc *sc);
void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
bool ath9k_uses_beacons(int type);
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -280,6 +280,22 @@ static bool ath_complete_reset(struct at
ath_start_ani(common);
}
+ if (ath9k_hw_ops(ah)->antdiv_comb_conf_get && sc->ant_rx != 3) {
+ struct ath_hw_antcomb_conf div_ant_conf;
+ u8 lna_conf;
+
+ ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf);
+
+ if (sc->ant_rx == 1)
+ lna_conf = ATH_ANT_DIV_COMB_LNA1;
+ else
+ lna_conf = ATH_ANT_DIV_COMB_LNA2;
+ div_ant_conf.main_lna_conf = lna_conf;
+ div_ant_conf.alt_lna_conf = lna_conf;
+
+ ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf);
+ }
+
ieee80211_wake_queues(sc->hw);
return true;
@@ -2383,6 +2399,59 @@ static int ath9k_get_stats(struct ieee80
return 0;
}
+static u32 fill_chainmask(u32 cap, u32 new)
+{
+ u32 filled = 0;
+ int i;
+
+ for (i = 0; cap && new; i++, cap >>= 1) {
+ if (!(cap & BIT(0)))
+ continue;
+
+ if (new & BIT(0))
+ filled |= BIT(i);
+
+ new >>= 1;
+ }
+
+ return filled;
+}
+
+static int ath9k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+{
+ struct ath_softc *sc = hw->priv;
+ struct ath_hw *ah = sc->sc_ah;
+
+ if (!rx_ant || !tx_ant)
+ return -EINVAL;
+
+ sc->ant_rx = rx_ant;
+ sc->ant_tx = tx_ant;
+
+ if (ah->caps.rx_chainmask == 1)
+ return 0;
+
+ /* AR9100 runs into calibration issues if not all rx chains are enabled */
+ if (AR_SREV_9100(ah))
+ ah->rxchainmask = 0x7;
+ else
+ ah->rxchainmask = fill_chainmask(ah->caps.rx_chainmask, rx_ant);
+
+ ah->txchainmask = fill_chainmask(ah->caps.tx_chainmask, tx_ant);
+ ath9k_reload_chainmask_settings(sc);
+
+ return 0;
+}
+
+static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+{
+ struct ath_softc *sc = hw->priv;
+
+ *tx_ant = sc->ant_tx;
+ *rx_ant = sc->ant_rx;
+ return 0;
+}
+
struct ieee80211_ops ath9k_ops = {
.tx = ath9k_tx,
.start = ath9k_start,
@@ -2409,4 +2478,6 @@ struct ieee80211_ops ath9k_ops = {
.tx_frames_pending = ath9k_tx_frames_pending,
.tx_last_beacon = ath9k_tx_last_beacon,
.get_stats = ath9k_get_stats,
+ .set_antenna = ath9k_set_antenna,
+ .get_antenna = ath9k_get_antenna,
};
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1956,7 +1956,7 @@ int ath_rx_tasklet(struct ath_softc *sc,
ath_rx_ps(sc, skb);
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
- if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
+ if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3)
ath_ant_comb_scan(sc, &rs);
ieee80211_rx(hw, skb);

@ -1,30 +0,0 @@
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -667,15 +667,15 @@ void ath9k_tasklet(unsigned long data)
u32 status = sc->intrstatus;
u32 rxmask;
+ ath9k_ps_wakeup(sc);
+ spin_lock(&sc->sc_pcu_lock);
+
if ((status & ATH9K_INT_FATAL) ||
(status & ATH9K_INT_BB_WATCHDOG)) {
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
- return;
+ goto out;
}
- ath9k_ps_wakeup(sc);
- spin_lock(&sc->sc_pcu_lock);
-
/*
* Only run the baseband hang check if beacons stop working in AP or
* IBSS mode, because it has a high false positive rate. For station
@@ -723,6 +723,7 @@ void ath9k_tasklet(unsigned long data)
if (status & ATH9K_INT_GENTIMER)
ath_gen_timer_isr(sc->sc_ah);
+out:
/* re-enable hardware interrupt */
ath9k_hw_enable_interrupts(ah);

@ -1,10 +0,0 @@
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -517,6 +517,7 @@ static void ath_beacon_config_ap(struct
/* Set the computed AP beacon timers */
ath9k_hw_disable_interrupts(ah);
+ sc->sc_flags |= SC_OP_TSF_RESET;
ath9k_beacon_init(sc, nexttbtt, intval);
sc->beacon.bmisscnt = 0;
ath9k_hw_set_interrupts(ah, ah->imask);

@ -1,34 +0,0 @@
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1845,7 +1845,7 @@ int ath_rx_tasklet(struct ath_softc *sc,
* If we're asked to flush receive queue, directly
* chain it back at the queue without processing it.
*/
- if (flush)
+ if (sc->sc_flags & SC_OP_RXFLUSH)
goto requeue_drop_frag;
retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
@@ -1973,7 +1973,8 @@ requeue:
} else {
list_move_tail(&bf->list, &sc->rx.rxbuf);
ath_rx_buf_link(sc, bf);
- ath9k_hw_rxena(ah);
+ if (!flush)
+ ath9k_hw_rxena(ah);
}
} while (1);
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -246,8 +246,8 @@ static bool ath_prepare_reset(struct ath
if (!flush) {
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
- ath_rx_tasklet(sc, 0, true);
- ath_rx_tasklet(sc, 0, false);
+ ath_rx_tasklet(sc, 1, true);
+ ath_rx_tasklet(sc, 1, false);
} else {
ath_flushrecv(sc);
}

@ -1,12 +0,0 @@
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -41,7 +41,8 @@ static bool ar9002_hw_is_cal_supported(s
case ADC_DC_CAL:
/* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */
if (!IS_CHAN_B(chan) &&
- !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
+ !((IS_CHAN_2GHZ(chan) || IS_CHAN_A_FAST_CLOCK(ah, chan)) &&
+ IS_CHAN_HT20(chan)))
supported = true;
break;
}

@ -1,24 +0,0 @@
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -596,7 +596,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
else
rs->rs_keyix = ATH9K_RXKEYIX_INVALID;
- rs->rs_rate = RXSTATUS_RATE(ah, (&ads));
+ rs->rs_rate = MS(ads.ds_rxstatus0, AR_RxRate);
rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -17,10 +17,6 @@
#ifndef MAC_H
#define MAC_H
-#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ? \
- MS(ads->ds_rxstatus0, AR_RxRate) : \
- (ads->ds_rxstatus3 >> 2) & 0xFF)
-
#define set11nTries(_series, _index) \
(SM((_series)[_index].Tries, AR_XmitDataTries##_index))

File diff suppressed because it is too large Load Diff

@ -101,7 +101,7 @@
+}
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -539,6 +539,7 @@ struct rt2x00lib_ops {
@@ -554,6 +554,7 @@ struct rt2x00lib_ops {
const u8 *data, const size_t len);
int (*load_firmware) (struct rt2x00_dev *rt2x00dev,
const u8 *data, const size_t len);
@ -109,7 +109,7 @@
/*
* Device initialization/deinitialization handlers.
@@ -685,6 +686,7 @@ enum rt2x00_capability_flags {
@@ -705,6 +706,7 @@ enum rt2x00_capability_flags {
REQUIRE_SW_SEQNO,
REQUIRE_HT_TX_DESC,
REQUIRE_PS_AUTOWAKE,
@ -117,7 +117,7 @@
/*
* Capabilities
@@ -940,6 +942,11 @@ struct rt2x00_dev {
@@ -960,6 +962,11 @@ struct rt2x00_dev {
const struct firmware *fw;
/*
@ -229,7 +229,7 @@
* Initialization functions.
*/
static bool rt2800pci_get_entry_state(struct queue_entry *entry)
@@ -1050,6 +1054,7 @@ static const struct rt2x00lib_ops rt2800
@@ -1052,6 +1056,7 @@ static const struct rt2x00lib_ops rt2800
.get_firmware_name = rt2800pci_get_firmware_name,
.check_firmware = rt2800_check_firmware,
.load_firmware = rt2800_load_firmware,
@ -239,7 +239,7 @@
.get_entry_state = rt2800pci_get_entry_state,
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1121,6 +1121,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
@@ -1142,6 +1142,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
@ -250,7 +250,7 @@
/*
* Let the driver probe the device to detect the capabilities.
*/
@@ -1222,6 +1226,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
@@ -1243,6 +1247,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
* Free queue structures.
*/
rt2x00queue_free(rt2x00dev);

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -751,6 +751,7 @@ struct b43_wldev {
@@ -753,6 +753,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 */
@ -10,7 +10,7 @@
struct b43_phy phy;
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -74,6 +74,11 @@ MODULE_FIRMWARE("b43/ucode16_mimo.fw");
@@ -76,6 +76,11 @@ MODULE_FIRMWARE("b43/ucode16_mimo.fw");
MODULE_FIRMWARE("b43/ucode5.fw");
MODULE_FIRMWARE("b43/ucode9.fw");
@ -22,7 +22,7 @@
static int modparam_bad_frames_preempt;
module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
MODULE_PARM_DESC(bad_frames_preempt,
@@ -2676,10 +2681,10 @@ static int b43_gpio_init(struct b43_wlde
@@ -2678,10 +2683,10 @@ static int b43_gpio_init(struct b43_wlde
& ~B43_MACCTL_GPOUTSMSK);
b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK)

@ -11,7 +11,7 @@
b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1883,9 +1883,11 @@ static void b43_do_interrupt_thread(stru
@@ -1885,9 +1885,11 @@ static void b43_do_interrupt_thread(stru
dma_reason[4], dma_reason[5]);
b43err(dev->wl, "This device does not support DMA "
"on your system. It will now be switched to PIO.\n");

Loading…
Cancel
Save