mirror of https://github.com/hak5/openwrt.git
parent
98372a8eb5
commit
22be36418e
|
@ -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(®_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,10 +27,10 @@
|
|||
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);
|
||||
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…
Reference in New Issue