mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-11-27 17:13:11 +02:00
mac80211: backport 2011-01-24 from trunk
git-svn-id: svn://svn.openwrt.org/openwrt/branches/backfire@25198 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
bdcad9402e
commit
6850d22cf4
@ -10,10 +10,10 @@ include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=mac80211
|
||||
|
||||
PKG_VERSION:=2011-01-05
|
||||
PKG_VERSION:=2011-01-24
|
||||
PKG_RELEASE:=1
|
||||
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
|
||||
PKG_MD5SUM:=2b87fdd08d95fa5def39f56f49c4906d
|
||||
PKG_MD5SUM:=c91b57972276b26824d4b18e927a9e5f
|
||||
|
||||
PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2
|
||||
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
|
||||
@ -991,7 +991,8 @@ MAKE_OPTS:= \
|
||||
KLIB_BUILD="$(LINUX_DIR)" \
|
||||
MODPROBE=: \
|
||||
KLIB=$(TARGET_MODULES_DIR) \
|
||||
KERNEL_SUBLEVEL=$(lastword $(subst ., ,$(KERNEL_PATCHVER)))
|
||||
KERNEL_SUBLEVEL=$(lastword $(subst ., ,$(KERNEL_PATCHVER))) \
|
||||
KBUILD_LDFLAGS_MODULE_PREREQ=
|
||||
|
||||
ifeq ($(CONFIG_PACKAGE_kmod-libertas-sd)$(CONFIG_PACKAGE_kmod-libertas-usb)$(CONFIG_PACKAGE_kmod-rt2x00-lib),)
|
||||
MAKE_OPTS += CONFIG_COMPAT_KFIFO=
|
||||
|
50
package/mac80211/patches/050-fix_br_port_exists.patch
Normal file
50
package/mac80211/patches/050-fix_br_port_exists.patch
Normal file
@ -0,0 +1,50 @@
|
||||
--- a/include/linux/compat-2.6.38.h
|
||||
+++ b/include/linux/compat-2.6.38.h
|
||||
@@ -8,23 +8,6 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
-/*
|
||||
- * This is not part of The 2.6.37 kernel yet but we
|
||||
- * we use it to optimize the backport code we
|
||||
- * need to implement. Instead of using ifdefs
|
||||
- * to check what version of the check we use
|
||||
- * we just replace all checks on current code
|
||||
- * with this. I'll submit this upstream too, that
|
||||
- * way all we'd have to do is to implement this
|
||||
- * for older kernels, then we would not have to
|
||||
- * edit the upstrema code for backport efforts.
|
||||
- */
|
||||
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
|
||||
-#define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT)
|
||||
-#else
|
||||
-#define br_port_exists(dev) (dev->br_port)
|
||||
-#endif
|
||||
-
|
||||
/* rename member in struct mmc_host in include/linux/mmc/host.h */
|
||||
#define max_segs max_hw_segs
|
||||
|
||||
--- a/include/linux/compat-2.6.h
|
||||
+++ b/include/linux/compat-2.6.h
|
||||
@@ -32,4 +32,21 @@
|
||||
#include <linux/compat-2.6.37.h>
|
||||
#include <linux/compat-2.6.38.h>
|
||||
|
||||
+/*
|
||||
+ * This is not part of The 2.6.37 kernel yet but we
|
||||
+ * we use it to optimize the backport code we
|
||||
+ * need to implement. Instead of using ifdefs
|
||||
+ * to check what version of the check we use
|
||||
+ * we just replace all checks on current code
|
||||
+ * with this. I'll submit this upstream too, that
|
||||
+ * way all we'd have to do is to implement this
|
||||
+ * for older kernels, then we would not have to
|
||||
+ * edit the upstrema code for backport efforts.
|
||||
+ */
|
||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
|
||||
+#define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT)
|
||||
+#else
|
||||
+#define br_port_exists(dev) (dev->br_port)
|
||||
+#endif
|
||||
+
|
||||
#endif /* LINUX_26_COMPAT_H */
|
@ -9,7 +9,7 @@
|
||||
{ AR5K_RXCFG, AR5K_DMASIZE_128B },
|
||||
+#else
|
||||
+ /* WAR for AR71xx PCI bug */
|
||||
+ { AR5K_TXCFG, AR5K_DMASIZE_4B },
|
||||
+ { AR5K_TXCFG, AR5K_DMASIZE_128B },
|
||||
+ { AR5K_RXCFG, AR5K_DMASIZE_4B },
|
||||
+#endif
|
||||
{ AR5K_CFG, AR5K_INIT_CFG },
|
||||
@ -29,7 +29,7 @@
|
||||
+#else
|
||||
+ /* WAR for AR71xx PCI bug */
|
||||
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
|
||||
+ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_4B);
|
||||
+ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
|
||||
+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
|
||||
+ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_4B);
|
||||
+#endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -927,6 +927,12 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
@@ -1200,6 +1200,12 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
sc->debug.debugfs_phy, &ah->config.cwm_ignore_extcca))
|
||||
goto err;
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
err:
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
||||
@@ -791,6 +791,8 @@ struct ath_hw {
|
||||
@@ -795,6 +795,8 @@ struct ath_hw {
|
||||
int initPDADC;
|
||||
int PDADCdelta;
|
||||
u8 led_pin;
|
||||
@ -26,7 +26,7 @@
|
||||
struct ar5416IniArray iniCommon;
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
|
||||
@@ -1171,6 +1171,20 @@ static bool ath9k_hw_channel_change(stru
|
||||
@@ -1175,6 +1175,20 @@ static bool ath9k_hw_channel_change(stru
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
bool ath9k_hw_check_alive(struct ath_hw *ah)
|
||||
{
|
||||
int count = 50;
|
||||
@@ -1459,6 +1473,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
|
||||
@@ -1463,6 +1477,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
|
||||
if (AR_SREV_9300_20_OR_LATER(ah))
|
||||
ar9003_hw_bb_watchdog_config(ah);
|
||||
|
||||
|
2294
package/mac80211/patches/310-pending_work.patch
Normal file
2294
package/mac80211/patches/310-pending_work.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,7 @@
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "hw.h"
|
||||
@@ -428,8 +429,16 @@ static int ath9k_hw_init_macaddr(struct
|
||||
@@ -431,8 +432,16 @@ static int ath9k_hw_init_macaddr(struct
|
||||
common->macaddr[2 * i] = eeval >> 8;
|
||||
common->macaddr[2 * i + 1] = eeval & 0xff;
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
#include "ath9k.h"
|
||||
|
||||
@@ -528,6 +529,7 @@ static void ath9k_init_misc(struct ath_s
|
||||
@@ -526,6 +527,7 @@ static void ath9k_init_misc(struct ath_s
|
||||
static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
|
||||
const struct ath_bus_ops *bus_ops)
|
||||
{
|
||||
@ -26,7 +26,7 @@
|
||||
struct ath_hw *ah = NULL;
|
||||
struct ath_common *common;
|
||||
int ret = 0, i;
|
||||
@@ -541,7 +543,7 @@ static int ath9k_init_softc(u16 devid, s
|
||||
@@ -540,7 +542,7 @@ static int ath9k_init_softc(u16 devid, s
|
||||
ah->hw_version.subsysid = subsysid;
|
||||
sc->sc_ah = ah;
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
ah->ah_flags |= AH_USE_EEPROM;
|
||||
|
||||
common = ath9k_hw_common(ah);
|
||||
@@ -574,6 +576,9 @@ static int ath9k_init_softc(u16 devid, s
|
||||
@@ -576,6 +578,9 @@ static int ath9k_init_softc(u16 devid, s
|
||||
if (ret)
|
||||
goto err_hw;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -543,8 +543,14 @@ static int ath9k_init_softc(u16 devid, s
|
||||
@@ -542,8 +542,14 @@ static int ath9k_init_softc(u16 devid, s
|
||||
ah->hw_version.subsysid = subsysid;
|
||||
sc->sc_ah = ah;
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
common->ops = &ath9k_common_ops;
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
||||
@@ -790,7 +790,7 @@ struct ath_hw {
|
||||
@@ -794,7 +794,7 @@ struct ath_hw {
|
||||
u32 originalGain[22];
|
||||
int initPDADC;
|
||||
int PDADCdelta;
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#include "ath5k.h"
|
||||
#include "reg.h"
|
||||
@@ -1726,7 +1728,7 @@ ath5k_eeprom_read_spur_chans(struct ath5
|
||||
@@ -1722,7 +1724,7 @@ ath5k_eeprom_read_spur_chans(struct ath5
|
||||
}
|
||||
|
||||
/*
|
||||
@ -18,10 +18,10 @@
|
||||
*/
|
||||
int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
|
||||
{
|
||||
@@ -1734,6 +1736,16 @@ int ath5k_eeprom_read_mac(struct ath5k_h
|
||||
@@ -1730,6 +1732,16 @@ int ath5k_eeprom_read_mac(struct ath5k_h
|
||||
u32 total, offset;
|
||||
u16 data;
|
||||
int octet, ret;
|
||||
int octet;
|
||||
+ struct ath5k_platform_data *pdata = NULL;
|
||||
+
|
||||
+ if (ah->ah_sc->pdev)
|
||||
@ -33,8 +33,8 @@
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
ret = ath5k_hw_nvram_read(ah, 0x20, &data);
|
||||
if (ret)
|
||||
AR5K_EEPROM_READ(0x20, data);
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath5k/pci.c
|
||||
+++ b/drivers/net/wireless/ath/ath5k/pci.c
|
||||
@@ -17,6 +17,7 @@
|
||||
@ -45,7 +45,7 @@
|
||||
#include "../ath.h"
|
||||
#include "ath5k.h"
|
||||
#include "debug.h"
|
||||
@@ -73,6 +74,19 @@ bool ath5k_pci_eeprom_read(struct ath_co
|
||||
@@ -74,6 +75,19 @@ ath5k_pci_eeprom_read(struct ath_common
|
||||
{
|
||||
struct ath5k_hw *ah = (struct ath5k_hw *) common->ah;
|
||||
u32 status, timeout;
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -871,6 +871,53 @@ static const struct file_operations fops
|
||||
@@ -1007,6 +1007,53 @@ static const struct file_operations fops
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
@ -54,7 +54,7 @@
|
||||
int ath9k_init_debug(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
@@ -933,6 +980,10 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
@@ -1077,6 +1124,10 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -441,26 +441,20 @@ void ath9k_btcoex_timer_pause(struct ath
|
||||
@@ -447,26 +447,20 @@ void ath9k_btcoex_timer_pause(struct ath
|
||||
|
||||
#define ATH_LED_PIN_DEF 1
|
||||
#define ATH_LED_PIN_9287 8
|
||||
@ -38,7 +38,7 @@
|
||||
|
||||
/* Antenna diversity/combining */
|
||||
#define ATH_ANT_RX_CURRENT_SHIFT 4
|
||||
@@ -611,15 +605,11 @@ struct ath_softc {
|
||||
@@ -618,15 +612,11 @@ struct ath_softc {
|
||||
struct ath_beacon beacon;
|
||||
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
|
||||
|
||||
@ -57,8 +57,8 @@
|
||||
+ struct led_classdev led_cdev;
|
||||
+#endif
|
||||
|
||||
int beacon_interval;
|
||||
|
||||
struct ath9k_hw_cal_data caldata;
|
||||
int last_rssi;
|
||||
--- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
@@ -20,120 +20,25 @@
|
||||
@ -253,9 +253,9 @@
|
||||
/* Rfkill */
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -1270,9 +1270,6 @@ static void ath9k_stop(struct ieee80211_
|
||||
@@ -1259,9 +1259,6 @@ static void ath9k_stop(struct ieee80211_
|
||||
|
||||
aphy->state = ATH_WIPHY_INACTIVE;
|
||||
mutex_lock(&sc->mutex);
|
||||
|
||||
- if (led_blink)
|
||||
- cancel_delayed_work_sync(&sc->ath_led_blink_work);
|
||||
@ -287,7 +287,7 @@
|
||||
static void ath9k_deinit_softc(struct ath_softc *sc);
|
||||
|
||||
/*
|
||||
@@ -747,6 +762,13 @@ int ath9k_init_device(u16 devid, struct
|
||||
@@ -748,6 +763,13 @@ int ath9k_init_device(u16 devid, struct
|
||||
|
||||
ath9k_init_txpower_limits(sc);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
|
||||
@@ -1425,8 +1425,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
|
||||
@@ -1429,8 +1429,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
|
||||
REG_WRITE(ah, AR_OBS, 8);
|
||||
|
||||
if (ah->config.rx_intr_mitigation) {
|
||||
|
@ -1,11 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -169,7 +169,7 @@ static void ath_tx_flush_tid(struct ath_
|
||||
ath_tx_update_baw(sc, tid, fi->seqno);
|
||||
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
|
||||
} else {
|
||||
- ath_tx_send_normal(sc, txq, tid, &bf_head);
|
||||
+ ath_tx_send_normal(sc, txq, NULL, &bf_head);
|
||||
}
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
}
|
12
package/mac80211/patches/530-mac80211_fix_beacon_race.patch
Normal file
12
package/mac80211/patches/530-mac80211_fix_beacon_race.patch
Normal file
@ -0,0 +1,12 @@
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -2241,6 +2241,9 @@ struct sk_buff *ieee80211_beacon_get_tim
|
||||
|
||||
sdata = vif_to_sdata(vif);
|
||||
|
||||
+ if (!ieee80211_sdata_running(sdata))
|
||||
+ goto out;
|
||||
+
|
||||
if (tim_offset)
|
||||
*tim_offset = 0;
|
||||
if (tim_length)
|
@ -1,11 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -856,7 +856,7 @@ int ath_tx_aggr_start(struct ath_softc *
|
||||
|
||||
txtid->state |= AGGR_ADDBA_PROGRESS;
|
||||
txtid->paused = true;
|
||||
- *ssn = txtid->seq_start;
|
||||
+ *ssn = txtid->seq_start = txtid->seq_next;
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -858,6 +858,9 @@ int ath_tx_aggr_start(struct ath_softc *
|
||||
txtid->paused = true;
|
||||
*ssn = txtid->seq_start = txtid->seq_next;
|
||||
|
||||
+ memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf));
|
||||
+ txtid->baw_head = txtid->baw_tail = 0;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,30 +0,0 @@
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -251,6 +251,9 @@ int ath_set_channel(struct ath_softc *sc
|
||||
if (!ath_stoprecv(sc))
|
||||
stopped = false;
|
||||
|
||||
+ if (!ath9k_hw_check_alive(ah))
|
||||
+ stopped = false;
|
||||
+
|
||||
/* XXX: do not flush receive queue here. We don't want
|
||||
* to flush data frames already in queue because of
|
||||
* changing channel. */
|
||||
@@ -602,7 +605,15 @@ void ath9k_tasklet(unsigned long data)
|
||||
|
||||
spin_lock(&sc->sc_pcu_lock);
|
||||
|
||||
- if (!ath9k_hw_check_alive(ah))
|
||||
+ /*
|
||||
+ * 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
|
||||
+ * mode it should not be necessary, since the upper layers will detect
|
||||
+ * this through a beacon miss automatically and the following channel
|
||||
+ * change will trigger a hardware reset anyway
|
||||
+ */
|
||||
+ if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0 &&
|
||||
+ !ath9k_hw_check_alive(ah))
|
||||
ieee80211_queue_work(sc->hw, &sc->hw_check_work);
|
||||
|
||||
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
|
101
package/mac80211/patches/540-ath9k_fix_queue_debug.patch
Normal file
101
package/mac80211/patches/540-ath9k_fix_queue_debug.patch
Normal file
@ -0,0 +1,101 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -450,14 +450,15 @@ static const struct file_operations fops
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
+#define PR_QNUM(_n) sc->tx.txq_map[_n]->axq_qnum
|
||||
#define PR(str, elem) \
|
||||
do { \
|
||||
len += snprintf(buf + len, size - len, \
|
||||
"%s%13u%11u%10u%10u\n", str, \
|
||||
- sc->debug.stats.txstats[WME_AC_BE].elem, \
|
||||
- sc->debug.stats.txstats[WME_AC_BK].elem, \
|
||||
- sc->debug.stats.txstats[WME_AC_VI].elem, \
|
||||
- sc->debug.stats.txstats[WME_AC_VO].elem); \
|
||||
+ sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].elem, \
|
||||
+ sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].elem, \
|
||||
+ sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].elem, \
|
||||
+ sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].elem); \
|
||||
if (len >= size) \
|
||||
goto done; \
|
||||
} while(0)
|
||||
@@ -466,10 +467,10 @@ static const struct file_operations fops
|
||||
do { \
|
||||
len += snprintf(buf + len, size - len, \
|
||||
"%s%13u%11u%10u%10u\n", str, \
|
||||
- (unsigned int)(sc->tx.txq[ATH_TXQ_AC_BE].elem), \
|
||||
- (unsigned int)(sc->tx.txq[ATH_TXQ_AC_BK].elem), \
|
||||
- (unsigned int)(sc->tx.txq[ATH_TXQ_AC_VI].elem), \
|
||||
- (unsigned int)(sc->tx.txq[ATH_TXQ_AC_VO].elem)); \
|
||||
+ (unsigned int)(sc->tx.txq_map[WME_AC_BE]->elem), \
|
||||
+ (unsigned int)(sc->tx.txq_map[WME_AC_BK]->elem), \
|
||||
+ (unsigned int)(sc->tx.txq_map[WME_AC_VI]->elem), \
|
||||
+ (unsigned int)(sc->tx.txq_map[WME_AC_VO]->elem)); \
|
||||
if (len >= size) \
|
||||
goto done; \
|
||||
} while(0)
|
||||
@@ -478,10 +479,10 @@ do { \
|
||||
do { \
|
||||
len += snprintf(buf + len, size - len, \
|
||||
"%s%13i%11i%10i%10i\n", str, \
|
||||
- list_empty(&sc->tx.txq[ATH_TXQ_AC_BE].elem), \
|
||||
- list_empty(&sc->tx.txq[ATH_TXQ_AC_BK].elem), \
|
||||
- list_empty(&sc->tx.txq[ATH_TXQ_AC_VI].elem), \
|
||||
- list_empty(&sc->tx.txq[ATH_TXQ_AC_VO].elem)); \
|
||||
+ list_empty(&sc->tx.txq_map[WME_AC_BE]->elem), \
|
||||
+ list_empty(&sc->tx.txq_map[WME_AC_BK]->elem), \
|
||||
+ list_empty(&sc->tx.txq_map[WME_AC_VI]->elem), \
|
||||
+ list_empty(&sc->tx.txq_map[WME_AC_VO]->elem)); \
|
||||
if (len >= size) \
|
||||
goto done; \
|
||||
} while (0)
|
||||
@@ -528,10 +529,10 @@ static ssize_t read_file_xmit(struct fil
|
||||
PR("hw-tx-proc-desc: ", txprocdesc);
|
||||
len += snprintf(buf + len, size - len,
|
||||
"%s%11p%11p%10p%10p\n", "txq-memory-address:",
|
||||
- &(sc->tx.txq[ATH_TXQ_AC_BE]),
|
||||
- &(sc->tx.txq[ATH_TXQ_AC_BK]),
|
||||
- &(sc->tx.txq[ATH_TXQ_AC_VI]),
|
||||
- &(sc->tx.txq[ATH_TXQ_AC_VO]));
|
||||
+ &(sc->tx.txq_map[WME_AC_BE]),
|
||||
+ &(sc->tx.txq_map[WME_AC_BK]),
|
||||
+ &(sc->tx.txq_map[WME_AC_VI]),
|
||||
+ &(sc->tx.txq_map[WME_AC_VO]));
|
||||
if (len >= size)
|
||||
goto done;
|
||||
|
||||
@@ -751,9 +752,9 @@ static ssize_t read_file_misc(struct fil
|
||||
}
|
||||
|
||||
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
|
||||
- struct ath_tx_status *ts)
|
||||
+ struct ath_tx_status *ts, struct ath_txq *txq)
|
||||
{
|
||||
- int qnum = skb_get_queue_mapping(bf->bf_mpdu);
|
||||
+ int qnum = txq->axq_qnum;
|
||||
|
||||
TX_STAT_INC(qnum, tx_pkts_all);
|
||||
sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.h
|
||||
@@ -175,7 +175,7 @@ int ath9k_init_debug(struct ath_hw *ah);
|
||||
|
||||
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
|
||||
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
|
||||
- struct ath_tx_status *ts);
|
||||
+ struct ath_tx_status *ts, struct ath_txq *txq);
|
||||
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
|
||||
|
||||
#else
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -1913,7 +1913,7 @@ static void ath_tx_complete_buf(struct a
|
||||
else
|
||||
complete(&sc->paprd_complete);
|
||||
} else {
|
||||
- ath_debug_stat_tx(sc, bf, ts);
|
||||
+ ath_debug_stat_tx(sc, bf, ts, txq);
|
||||
ath_tx_complete(sc, skb, tx_flags,
|
||||
bf->bf_state.bfs_ftype, txq);
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
|
||||
@@ -615,7 +615,7 @@ int ath9k_hw_process_rxdesc_edma(struct
|
||||
*/
|
||||
if (rxsp->status11 & AR_CRCErr)
|
||||
rxs->rs_status |= ATH9K_RXERR_CRC;
|
||||
- if (rxsp->status11 & AR_PHYErr) {
|
||||
+ else if (rxsp->status11 & AR_PHYErr) {
|
||||
phyerr = MS(rxsp->status11, AR_PHYErrCode);
|
||||
/*
|
||||
* If we reach a point here where AR_PostDelimCRCErr is
|
||||
@@ -638,11 +638,11 @@ int ath9k_hw_process_rxdesc_edma(struct
|
||||
rxs->rs_phyerr = phyerr;
|
||||
}
|
||||
|
||||
- }
|
||||
- if (rxsp->status11 & AR_DecryptCRCErr)
|
||||
+ } else if (rxsp->status11 & AR_DecryptCRCErr)
|
||||
rxs->rs_status |= ATH9K_RXERR_DECRYPT;
|
||||
- if (rxsp->status11 & AR_MichaelErr)
|
||||
+ else if (rxsp->status11 & AR_MichaelErr)
|
||||
rxs->rs_status |= ATH9K_RXERR_MIC;
|
||||
+
|
||||
if (rxsp->status11 & AR_KeyMiss)
|
||||
rxs->rs_status |= ATH9K_RXERR_DECRYPT;
|
||||
}
|
||||
--- a/drivers/net/wireless/ath/ath9k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/mac.c
|
||||
@@ -690,17 +690,23 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
|
||||
rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
|
||||
|
||||
if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
|
||||
+ /*
|
||||
+ * Treat these errors as mutually exclusive to avoid spurious
|
||||
+ * extra error reports from the hardware. If a CRC error is
|
||||
+ * reported, then decryption and MIC errors are irrelevant,
|
||||
+ * the frame is going to be dropped either way
|
||||
+ */
|
||||
if (ads.ds_rxstatus8 & AR_CRCErr)
|
||||
rs->rs_status |= ATH9K_RXERR_CRC;
|
||||
- if (ads.ds_rxstatus8 & AR_PHYErr) {
|
||||
+ else if (ads.ds_rxstatus8 & AR_PHYErr) {
|
||||
rs->rs_status |= ATH9K_RXERR_PHY;
|
||||
phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
|
||||
rs->rs_phyerr = phyerr;
|
||||
- }
|
||||
- if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
|
||||
+ } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
|
||||
rs->rs_status |= ATH9K_RXERR_DECRYPT;
|
||||
- if (ads.ds_rxstatus8 & AR_MichaelErr)
|
||||
+ else if (ads.ds_rxstatus8 & AR_MichaelErr)
|
||||
rs->rs_status |= ATH9K_RXERR_MIC;
|
||||
+
|
||||
if (ads.ds_rxstatus8 & AR_KeyMiss)
|
||||
rs->rs_status |= ATH9K_RXERR_DECRYPT;
|
||||
}
|
@ -0,0 +1,200 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -1291,6 +1291,11 @@ static void ath9k_stop(struct ieee80211_
|
||||
} else
|
||||
sc->rx.rxlink = NULL;
|
||||
|
||||
+ if (sc->rx.frag) {
|
||||
+ dev_kfree_skb_any(sc->rx.frag);
|
||||
+ sc->rx.frag = NULL;
|
||||
+ }
|
||||
+
|
||||
/* disable HAL and put h/w to sleep */
|
||||
ath9k_hw_disable(ah);
|
||||
ath9k_hw_configpcipowersave(ah, 1, 1);
|
||||
--- a/drivers/net/wireless/ath/ath9k/recv.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/recv.c
|
||||
@@ -209,11 +209,6 @@ static int ath_rx_edma_init(struct ath_s
|
||||
int error = 0, i;
|
||||
u32 size;
|
||||
|
||||
-
|
||||
- common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN +
|
||||
- ah->caps.rx_status_len,
|
||||
- min(common->cachelsz, (u16)64));
|
||||
-
|
||||
ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize -
|
||||
ah->caps.rx_status_len);
|
||||
|
||||
@@ -300,12 +295,12 @@ int ath_rx_init(struct ath_softc *sc, in
|
||||
sc->sc_flags &= ~SC_OP_RXFLUSH;
|
||||
spin_lock_init(&sc->rx.rxbuflock);
|
||||
|
||||
+ common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 + common->cachelsz +
|
||||
+ sc->sc_ah->caps.rx_status_len;
|
||||
+
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
|
||||
return ath_rx_edma_init(sc, nbufs);
|
||||
} else {
|
||||
- common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
|
||||
- min(common->cachelsz, (u16)64));
|
||||
-
|
||||
ath_dbg(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
|
||||
common->cachelsz, common->rx_bufsize);
|
||||
|
||||
@@ -815,15 +810,9 @@ static bool ath9k_rx_accept(struct ath_c
|
||||
if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len))
|
||||
return false;
|
||||
|
||||
- /*
|
||||
- * rs_more indicates chained descriptors which can be used
|
||||
- * to link buffers together for a sort of scatter-gather
|
||||
- * operation.
|
||||
- * reject the frame, we don't support scatter-gather yet and
|
||||
- * the frame is probably corrupt anyway
|
||||
- */
|
||||
+ /* Only use error bits from the last fragment */
|
||||
if (rx_stats->rs_more)
|
||||
- return false;
|
||||
+ return true;
|
||||
|
||||
/*
|
||||
* The rx_stats->rs_status will not be set until the end of the
|
||||
@@ -981,6 +970,10 @@ static int ath9k_rx_skb_preprocess(struc
|
||||
if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
|
||||
return -EINVAL;
|
||||
|
||||
+ /* Only use status info from the last fragment */
|
||||
+ if (rx_stats->rs_more)
|
||||
+ return 0;
|
||||
+
|
||||
ath9k_process_rssi(common, hw, hdr, rx_stats);
|
||||
|
||||
if (ath9k_process_rate(common, hw, rx_stats, rx_status))
|
||||
@@ -1582,7 +1575,7 @@ div_comb_done:
|
||||
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||
{
|
||||
struct ath_buf *bf;
|
||||
- struct sk_buff *skb = NULL, *requeue_skb;
|
||||
+ struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb;
|
||||
struct ieee80211_rx_status *rxs;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
@@ -1633,8 +1626,17 @@ int ath_rx_tasklet(struct ath_softc *sc,
|
||||
if (!skb)
|
||||
continue;
|
||||
|
||||
- hdr = (struct ieee80211_hdr *) (skb->data + rx_status_len);
|
||||
- rxs = IEEE80211_SKB_RXCB(skb);
|
||||
+ /*
|
||||
+ * Take frame header from the first fragment and RX status from
|
||||
+ * the last one.
|
||||
+ */
|
||||
+ if (sc->rx.frag)
|
||||
+ hdr_skb = sc->rx.frag;
|
||||
+ else
|
||||
+ hdr_skb = skb;
|
||||
+
|
||||
+ hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len);
|
||||
+ rxs = IEEE80211_SKB_RXCB(hdr_skb);
|
||||
|
||||
ath_debug_stat_rx(sc, &rs);
|
||||
|
||||
@@ -1643,12 +1645,12 @@ int ath_rx_tasklet(struct ath_softc *sc,
|
||||
* chain it back at the queue without processing it.
|
||||
*/
|
||||
if (flush)
|
||||
- goto requeue;
|
||||
+ goto requeue_drop_frag;
|
||||
|
||||
retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
|
||||
rxs, &decrypt_error);
|
||||
if (retval)
|
||||
- goto requeue;
|
||||
+ goto requeue_drop_frag;
|
||||
|
||||
rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
|
||||
if (rs.rs_tstamp > tsf_lower &&
|
||||
@@ -1668,7 +1670,7 @@ int ath_rx_tasklet(struct ath_softc *sc,
|
||||
* skb and put it at the tail of the sc->rx.rxbuf list for
|
||||
* processing. */
|
||||
if (!requeue_skb)
|
||||
- goto requeue;
|
||||
+ goto requeue_drop_frag;
|
||||
|
||||
/* Unmap the frame */
|
||||
dma_unmap_single(sc->dev, bf->bf_buf_addr,
|
||||
@@ -1679,8 +1681,9 @@ int ath_rx_tasklet(struct ath_softc *sc,
|
||||
if (ah->caps.rx_status_len)
|
||||
skb_pull(skb, ah->caps.rx_status_len);
|
||||
|
||||
- ath9k_rx_skb_postprocess(common, skb, &rs,
|
||||
- rxs, decrypt_error);
|
||||
+ if (!rs.rs_more)
|
||||
+ ath9k_rx_skb_postprocess(common, hdr_skb, &rs,
|
||||
+ rxs, decrypt_error);
|
||||
|
||||
/* We will now give hardware our shiny new allocated skb */
|
||||
bf->bf_mpdu = requeue_skb;
|
||||
@@ -1697,6 +1700,38 @@ int ath_rx_tasklet(struct ath_softc *sc,
|
||||
break;
|
||||
}
|
||||
|
||||
+ if (rs.rs_more) {
|
||||
+ /*
|
||||
+ * rs_more indicates chained descriptors which can be
|
||||
+ * used to link buffers together for a sort of
|
||||
+ * scatter-gather operation.
|
||||
+ */
|
||||
+ if (sc->rx.frag) {
|
||||
+ /* too many fragments - cannot handle frame */
|
||||
+ dev_kfree_skb_any(sc->rx.frag);
|
||||
+ dev_kfree_skb_any(skb);
|
||||
+ skb = NULL;
|
||||
+ }
|
||||
+ sc->rx.frag = skb;
|
||||
+ goto requeue;
|
||||
+ }
|
||||
+
|
||||
+ if (sc->rx.frag) {
|
||||
+ int space = skb->len - skb_tailroom(hdr_skb);
|
||||
+
|
||||
+ sc->rx.frag = NULL;
|
||||
+
|
||||
+ if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) {
|
||||
+ dev_kfree_skb(skb);
|
||||
+ goto requeue_drop_frag;
|
||||
+ }
|
||||
+
|
||||
+ skb_copy_from_linear_data(skb, skb_put(hdr_skb, skb->len),
|
||||
+ skb->len);
|
||||
+ dev_kfree_skb_any(skb);
|
||||
+ skb = hdr_skb;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* change the default rx antenna if rx diversity chooses the
|
||||
* other antenna 3 times in a row.
|
||||
@@ -1722,6 +1757,11 @@ int ath_rx_tasklet(struct ath_softc *sc,
|
||||
|
||||
ieee80211_rx(hw, skb);
|
||||
|
||||
+requeue_drop_frag:
|
||||
+ if (sc->rx.frag) {
|
||||
+ dev_kfree_skb_any(sc->rx.frag);
|
||||
+ sc->rx.frag = NULL;
|
||||
+ }
|
||||
requeue:
|
||||
if (edma) {
|
||||
list_add_tail(&bf->list, &sc->rx.rxbuf);
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -311,6 +311,8 @@ struct ath_rx {
|
||||
struct ath_descdma rxdma;
|
||||
struct ath_buf *rx_bufptr;
|
||||
struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
|
||||
+
|
||||
+ struct sk_buff *frag;
|
||||
};
|
||||
|
||||
int ath_startrecv(struct ath_softc *sc);
|
@ -1,29 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -1224,12 +1224,14 @@ void ath_tx_cleanupq(struct ath_softc *s
|
||||
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
|
||||
{
|
||||
struct ath_atx_ac *ac;
|
||||
- struct ath_atx_tid *tid;
|
||||
+ struct ath_atx_tid *tid, *last;
|
||||
|
||||
- if (list_empty(&txq->axq_acq))
|
||||
+ if (list_empty(&txq->axq_acq) ||
|
||||
+ txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
|
||||
return;
|
||||
|
||||
ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
|
||||
+ last = list_entry(ac->tid_q.prev, struct ath_atx_tid, list);
|
||||
list_del(&ac->list);
|
||||
ac->sched = false;
|
||||
|
||||
@@ -1253,7 +1255,8 @@ void ath_txq_schedule(struct ath_softc *
|
||||
if (!list_empty(&tid->buf_q))
|
||||
ath_tx_queue_tid(txq, tid);
|
||||
|
||||
- break;
|
||||
+ if (tid == last || txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
|
||||
+ break;
|
||||
} while (!list_empty(&ac->tid_q));
|
||||
|
||||
if (!list_empty(&ac->tid_q)) {
|
@ -1,11 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -429,7 +429,7 @@ static void ath_tx_complete_aggr(struct
|
||||
|
||||
ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
|
||||
while (bf) {
|
||||
- txfail = txpending = 0;
|
||||
+ txfail = txpending = sendbar = 0;
|
||||
bf_next = bf->bf_next;
|
||||
|
||||
skb = bf->bf_mpdu;
|
@ -1,18 +0,0 @@
|
||||
--- a/net/mac80211/rx.c
|
||||
+++ b/net/mac80211/rx.c
|
||||
@@ -1561,9 +1561,13 @@ __ieee80211_data_to_8023(struct ieee8021
|
||||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta)
|
||||
return -1;
|
||||
|
||||
+ if (!ieee80211_802_1x_port_control(rx) &&
|
||||
+ sdata->vif.type == NL80211_IFTYPE_STATION &&
|
||||
+ !!sdata->u.mgd.use_4addr != !!ieee80211_has_a4(hdr->frame_control))
|
||||
+ return -1;
|
||||
+
|
||||
if (is_multicast_ether_addr(hdr->addr1) &&
|
||||
- ((sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta) ||
|
||||
- (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.use_4addr)))
|
||||
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta)
|
||||
return -1;
|
||||
|
||||
return ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type);
|
@ -1,61 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -2111,9 +2111,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");
|
||||
- ath9k_ps_wakeup(sc);
|
||||
ath_reset(sc, true);
|
||||
- ath9k_ps_restore(sc);
|
||||
}
|
||||
|
||||
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -592,19 +592,16 @@ void ath9k_tasklet(unsigned long data)
|
||||
struct ath_softc *sc = (struct ath_softc *)data;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
-
|
||||
u32 status = sc->intrstatus;
|
||||
u32 rxmask;
|
||||
|
||||
- ath9k_ps_wakeup(sc);
|
||||
-
|
||||
if (status & ATH9K_INT_FATAL) {
|
||||
ath_reset(sc, true);
|
||||
- ath9k_ps_restore(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock(&sc->sc_pcu_lock);
|
||||
+ ath9k_ps_wakeup(sc);
|
||||
|
||||
/*
|
||||
* Only run the baseband hang check if beacons stop working in AP or
|
||||
@@ -980,6 +977,7 @@ int ath_reset(struct ath_softc *sc, bool
|
||||
/* Stop ANI */
|
||||
del_timer_sync(&common->ani.timer);
|
||||
|
||||
+ ath9k_ps_wakeup(sc);
|
||||
spin_lock_bh(&sc->sc_pcu_lock);
|
||||
|
||||
ieee80211_stop_queues(hw);
|
||||
@@ -1026,6 +1024,7 @@ int ath_reset(struct ath_softc *sc, bool
|
||||
|
||||
/* Start ANI */
|
||||
ath_start_ani(common);
|
||||
+ ath9k_ps_restore(sc);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -1748,7 +1747,9 @@ static int ath9k_config(struct ieee80211
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_POWER) {
|
||||
sc->config.txpowlimit = 2 * conf->power_level;
|
||||
+ ath9k_ps_wakeup(sc);
|
||||
ath_update_txpow(sc);
|
||||
+ ath9k_ps_restore(sc);
|
||||
}
|
||||
|
||||
if (disable_radio) {
|
@ -1,29 +0,0 @@
|
||||
From 27ed5ec6924c17b76d65b697a162bafee7bd8e4e Mon Sep 17 00:00:00 2001
|
||||
From: Helmut Schaa <helmut.schaa@googlemail.com>
|
||||
Date: Mon, 21 Jun 2010 10:03:05 +0200
|
||||
Subject: [PATCH] rt2x00: fix rt2800pci hang on ifdown
|
||||
|
||||
rt2800pci hangs the system on rt305x SoC devices on ifdown. Work around
|
||||
this issue by disabling TX DMA prior to resetting the TX queue indices.
|
||||
|
||||
This patch is not suitable for upstream inclusion but is just meant as
|
||||
a workaround until a proper solution is implemented.
|
||||
|
||||
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
|
||||
---
|
||||
drivers/net/wireless/rt2x00/rt2800pci.c | 4 ++++
|
||||
1 files changed, 4 insertions(+), 0 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
|
||||
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
|
||||
@@ -481,6 +481,10 @@ static void rt2800pci_disable_radio(stru
|
||||
|
||||
rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280);
|
||||
|
||||
+ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®);
|
||||
+ rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
|
||||
+ rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
|
||||
+
|
||||
rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®);
|
||||
rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1);
|
||||
rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1);
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/mwl8k.c
|
||||
+++ b/drivers/net/wireless/mwl8k.c
|
||||
@@ -4056,6 +4056,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
|
||||
@@ -4484,6 +4484,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
|
||||
MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
|
||||
|
Loading…
Reference in New Issue
Block a user