1
0
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:
nbd 2011-01-28 13:31:36 +00:00
parent bdcad9402e
commit 6850d22cf4
26 changed files with 2690 additions and 300 deletions

View File

@ -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=

View 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 */

View File

@ -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

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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);
}

View 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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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)

View 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);
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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)) {

View File

@ -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;

View File

@ -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);

View File

@ -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) {

View File

@ -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, &reg);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
+ rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+
rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, 1);

View File

@ -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) = {