From ab9bdc34d68dafc6fea0ba733231f1c9696ce9c4 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Tue, 23 Feb 2010 14:02:52 -0800 Subject: Revert "iwlwifi: Monitor and recover the aggregation TX flow failure" This reverts commit 1db5950f1d0b82e07371b211a48317b8972da063. The goal of "iwlwifi: Monitor and recover the aggregation TX flow failure" is to first detect when data transmission stalls and then to recover from this situation with a reset of the radio or the firmware, depending on how bad the transmission failures are. Unfortunately we have found that this change causes excessive resets with its current detection algorithm. It also performs its recovery action when none is really needed, like when we are not associated. Revert this change until the issues have been addressed. Signed-off-by: Reinette Chatre diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c5b724e..1fac015 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2941,21 +2941,10 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return ret; case IEEE80211_AMPDU_TX_START: IWL_DEBUG_HT(priv, "start Tx\n"); - ret = iwl_tx_agg_start(priv, sta->addr, tid, ssn); - if (ret == 0) { - priv->agg_tids_count++; - IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", - priv->agg_tids_count); - } - return ret; + return iwl_tx_agg_start(priv, sta->addr, tid, ssn); case IEEE80211_AMPDU_TX_STOP: IWL_DEBUG_HT(priv, "stop Tx\n"); ret = iwl_tx_agg_stop(priv, sta->addr, tid); - if ((ret == 0) && (priv->agg_tids_count > 0)) { - priv->agg_tids_count--; - IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", - priv->agg_tids_count); - } if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return 0; else @@ -3376,7 +3365,6 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->iw_mode = NL80211_IFTYPE_STATION; priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; - priv->agg_tids_count = 0; /* initialize force reset */ priv->force_reset[IWL_RF_RESET].reset_duration = diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 7914d65..ab891b9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1084,9 +1084,6 @@ struct iwl_priv { /* storing the jiffies when the plcp error rate is received */ unsigned long plcp_jiffies; - /* reporting the number of tids has AGG on. 0 means no AGGREGATION */ - u8 agg_tids_count; - /* force reset */ struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index fed554a..aba8f4c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -616,11 +616,6 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, #define REG_RECALIB_PERIOD (60) -/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ -#define ACK_CNT_RATIO (50) -#define BA_TIMEOUT_CNT (5) -#define BA_TIMEOUT_MAX (16) - #define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" void iwl_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) @@ -630,9 +625,6 @@ void iwl_rx_statistics(struct iwl_priv *priv, int combined_plcp_delta; unsigned int plcp_msec; unsigned long plcp_received_jiffies; - int actual_ack_cnt_delta; - int expected_ack_cnt_delta; - int ba_timeout_delta; IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", (int)sizeof(priv->statistics), @@ -647,44 +639,6 @@ void iwl_rx_statistics(struct iwl_priv *priv, #ifdef CONFIG_IWLWIFI_DEBUG iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); #endif - actual_ack_cnt_delta = le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) - - le32_to_cpu(priv->statistics.tx.actual_ack_cnt); - expected_ack_cnt_delta = le32_to_cpu( - pkt->u.stats.tx.expected_ack_cnt) - - le32_to_cpu(priv->statistics.tx.expected_ack_cnt); - ba_timeout_delta = le32_to_cpu( - pkt->u.stats.tx.agg.ba_timeout) - - le32_to_cpu(priv->statistics.tx.agg.ba_timeout); - if ((priv->agg_tids_count > 0) && - (expected_ack_cnt_delta > 0) && - (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) < - ACK_CNT_RATIO) && - (ba_timeout_delta > BA_TIMEOUT_CNT)) { - IWL_DEBUG_RADIO(priv, - "actual_ack_cnt delta = %d, expected_ack_cnt = %d\n", - actual_ack_cnt_delta, expected_ack_cnt_delta); - -#ifdef CONFIG_IWLWIFI_DEBUG - IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", - priv->delta_statistics.tx.rx_detected_cnt); - IWL_DEBUG_RADIO(priv, - "ack_or_ba_timeout_collision delta = %d\n", - priv->delta_statistics.tx.ack_or_ba_timeout_collision); -#endif - IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", - ba_timeout_delta); - if ((actual_ack_cnt_delta == 0) && - (ba_timeout_delta >= - BA_TIMEOUT_MAX)) { - IWL_DEBUG_RADIO(priv, - "call iwl_force_reset(IWL_FW_RESET)\n"); - iwl_force_reset(priv, IWL_FW_RESET); - } else { - IWL_DEBUG_RADIO(priv, - "call iwl_force_reset(IWL_RF_RESET)\n"); - iwl_force_reset(priv, IWL_RF_RESET); - } - } /* * check for plcp_err and trigger radio reset if it exceeds * the plcp error threshold plcp_delta. -- cgit v0.10.2 From 89612124d6d62230043ebd827a2b54ea5ea5280c Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 19 Feb 2010 11:49:49 -0800 Subject: iwlwifi: increase command buffer size Increase the buffer size for commands with "huge" bit set. This has been recently observed for 6050 cards where for even with huge bit set few commands were not properly allocated memory with the command overwriting the buffer allocated for it.. Also add a check to see if command size exceeds the maximum allowable size. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index e915075..cfd6c84 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2612,6 +2612,7 @@ struct iwl_ssid_ie { #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) #define IWL_GOOD_CRC_TH cpu_to_le16(1) #define IWL_MAX_SCAN_SIZE 1024 +#define IWL_MAX_CMD_SIZE 4096 #define IWL_MAX_PROBE_REQUEST 200 /* diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 8f40715..066491f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -366,7 +366,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, for (i = 0; i < actual_slots; i++) { /* only happens for cmd queue */ if (i == slots_num) - len += IWL_MAX_SCAN_SIZE; + len = IWL_MAX_CMD_SIZE; txq->cmd[i] = kmalloc(len, GFP_KERNEL); if (!txq->cmd[i]) @@ -1027,9 +1027,12 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) /* If any of the command structures end up being larger than * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then - * we will need to increase the size of the TFD entries */ + * we will need to increase the size of the TFD entries + * Also, check to see if command buffer should not exceed the size + * of device_cmd and max_cmd_size. */ BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && !(cmd->flags & CMD_SIZE_HUGE)); + BUG_ON(fix_size > IWL_MAX_CMD_SIZE); if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { IWL_WARN(priv, "Not sending command - %s KILL\n", @@ -1073,8 +1076,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (cmd->flags & CMD_SIZE_HUGE) out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; len = sizeof(struct iwl_device_cmd); - len += (idx == TFD_CMD_SLOTS) ? IWL_MAX_SCAN_SIZE : 0; - + if (idx == TFD_CMD_SLOTS) + len = IWL_MAX_CMD_SIZE; #ifdef CONFIG_IWLWIFI_DEBUG switch (out_cmd->hdr.cmd) { -- cgit v0.10.2 From a040d532b912b5dd7d88692b580cff9c88b987e3 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 23 Feb 2010 09:34:38 +0100 Subject: MAINTAINERS: update mwl8k maintenance status I am no longer with Marvell. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville diff --git a/MAINTAINERS b/MAINTAINERS index 2b4a4d2..cb0a800 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3450,9 +3450,9 @@ F: drivers/net/mv643xx_eth.* F: include/linux/mv643xx.h MARVELL MWL8K WIRELESS DRIVER -M: Lennert Buytenhek +M: Lennert Buytenhek L: linux-wireless@vger.kernel.org -S: Supported +S: Maintained F: drivers/net/wireless/mwl8k.c MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER -- cgit v0.10.2 From 7bfbae10dc10a5c94a780d117a57e875d77e8e5a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 24 Feb 2010 04:43:05 +0100 Subject: ath9k: disable RIFS search for AR91xx based chips While ath9k does not support RIFS yet, the ability to receive RIFS frames is currently enabled for most chipsets in the initvals. This is causing baseband related issues on AR9160 and AR9130 based chipsets, which can lock up under certain conditions. This patch fixes these issues by overriding the initvals, effectively disabling RIFS for all affected chipsets. Signed-off-by: Felix Fietkau Cc: stable@kernel.org Acked-by: Luis R. Rodriguez Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index f00f5c7..2e767cf 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1310,6 +1310,16 @@ static void ath9k_hw_override_ini(struct ath_hw *ah, * Necessary to avoid issues on AR5416 2.0 */ REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); + + /* + * Disable RIFS search on some chips to avoid baseband + * hang issues. + */ + if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) { + val = REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS); + val &= ~AR_PHY_RIFS_INIT_DELAY; + REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val); + } } static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index 31de27d..0999a49 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -384,6 +384,9 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah, #define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0 +#define AR_PHY_HEAVY_CLIP_FACTOR_RIFS 0x99EC +#define AR_PHY_RIFS_INIT_DELAY 0x03ff0000 + #define AR_PHY_M_SLEEP 0x99f0 #define AR_PHY_REFCLKDLY 0x99f4 #define AR_PHY_REFCLKPD 0x99f8 -- cgit v0.10.2 From b446918b77c717a34eaa853dfab55f579d330551 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Wed, 24 Feb 2010 14:19:37 +0100 Subject: mac80211: use listen interval 5 as default Currently if a driver does not set hw.max_listen_interval a listen interval of 1 is negotiated with the AP. Thus, the AP could drop buffered frames for us after just one beacon interval which can easily happen with the current powersave and scan implementation. To avoid this issue increase the default interval to 5 which should be a reasonable safe default. Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville diff --git a/net/mac80211/main.c b/net/mac80211/main.c index ec8f767..06c33b6 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -558,8 +558,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) debugfs_hw_add(local); + /* + * if the driver doesn't specify a max listen interval we + * use 5 which should be a safe default + */ if (local->hw.max_listen_interval == 0) - local->hw.max_listen_interval = 1; + local->hw.max_listen_interval = 5; local->hw.conf.listen_interval = local->hw.max_listen_interval; -- cgit v0.10.2 From caf66e581172dc5032bb84841a91bc7b77ad9876 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 25 Feb 2010 12:02:45 -0500 Subject: netdevice.h: check for CONFIG_WLAN instead of CONFIG_WLAN_80211 In "wireless: remove WLAN_80211 and WLAN_PRE80211 from Kconfig" I inadvertantly missed a line in include/linux/netdevice.h. I thereby effectively reverted "net: Set LL_MAX_HEADER properly for wireless." by accident. :-( Now we should check there for CONFIG_WLAN instead. Signed-off-by: John W. Linville Reported-by: Christoph Egger Cc: stable@kernel.org diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a3fccc8..99914e6 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -136,7 +136,7 @@ static inline bool dev_xmit_complete(int rc) * used. */ -#if defined(CONFIG_WLAN_80211) || defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) +#if defined(CONFIG_WLAN) || defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) # if defined(CONFIG_MAC80211_MESH) # define LL_MAX_HEADER 128 # else -- cgit v0.10.2 From 0e0a228398cc967c922759be36c69d32e4f62701 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Feb 2010 08:13:41 +0200 Subject: mac80211: fix direct probe loop on ieee80211_work_purge If authentication has already been performed when the WLAN interface is stopped, (sometimes) the ieee80211_work_purge would corrupt some ieee80211_work-structures. The outcome is this (cleaned up): [ 2252.398681] WARNING: at net/mac80211/work.c:995 ieee80211_work_purge [ 2252.466430] Backtrace: [ 2252.529266] (ieee80211_work_purge+0x0/0xcc [mac80211]) [ 2252.546875] (ieee80211_stop+0x0/0x4c0 [mac80211]) Additionally, one would get this, going on regarless of the WLAN interface state, going on forever: [ 2252.859985] wlan0: direct probe to 00:90:4c:60:04:00 (try -996717525) [ 2253.055419] wlan0: direct probe to 00:90:4c:60:04:00 (try -996717524) [ 2253.250610] wlan0: direct probe to 00:90:4c:60:04:00 (try -996717523) [ 2253.446014] wlan0: direct probe to 00:90:4c:60:04:00 (try -996717522) [ 2253.641357] wlan0: direct probe to 00:90:4c:60:04:00 (try -996717521) Signed-off-by: Juuso Oikarinen Reviewed-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 7e708d5..1e1ea30 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -869,6 +869,7 @@ static void ieee80211_work_work(struct work_struct *work) break; case IEEE80211_WORK_ABORT: rma = WORK_ACT_TIMEOUT; + break; case IEEE80211_WORK_DIRECT_PROBE: rma = ieee80211_direct_probe(wk); break; -- cgit v0.10.2 From 9e3bd9190800e8209b4a3e1d724c35f0738dcad2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 26 Feb 2010 10:34:27 -0800 Subject: b43: fall back gracefully to PIO mode after fatal DMA errors This makes the b43 driver just automatically fall back to PIO mode when DMA doesn't work. The driver already told the user to do it, so rather than have the user reload the module with a new flag, just make the driver do it automatically. We keep the message as an indication that something is wrong, but now just automatically fall back to the hopefully working PIO case. (Some post-2.6.33 merge fixups by Larry Finger and yours truly... -- JWL) Signed-off-by: Linus Torvalds Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 073be56..0a00d42 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -3,7 +3,6 @@ config B43 depends on SSB_POSSIBLE && MAC80211 && HAS_DMA select SSB select FW_LOADER - select SSB_BLOCKIO ---help--- b43 is a driver for the Broadcom 43xx series wireless devices. @@ -79,6 +78,14 @@ config B43_SDIO If unsure, say N. +#Data transfers to the device via PIO. We want it as a fallback even +# if we can do DMA. +config B43_PIO + bool + depends on B43 + select SSB_BLOCKIO + default y + config B43_NPHY bool "Pre IEEE 802.11n support (BROKEN)" depends on B43 && EXPERIMENTAL && BROKEN @@ -130,4 +137,12 @@ config B43_DEBUG for production use. Only say Y, if you are debugging a problem in the b43 driver sourcecode. +config B43_FORCE_PIO + bool "Force usage of PIO instead of DMA" + depends on B43 && B43_DEBUG + ---help--- + This will disable DMA and always enable PIO instead. + Say N! + This is only for debugging the PIO engine code. You do + _NOT_ want to enable this. diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 6a6ab0f..b8807fb 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -702,6 +702,7 @@ struct b43_wldev { bool radio_hw_enable; /* saved state of radio hardware enabled state */ 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 */ /* PHY/Radio device. */ struct b43_phy phy; @@ -886,6 +887,12 @@ static inline bool b43_using_pio_transfers(struct b43_wldev *dev) return dev->__using_pio_transfers; } +#ifdef CONFIG_B43_FORCE_PIO +# define B43_PIO_DEFAULT 1 +#else +# define B43_PIO_DEFAULT 0 +#endif + /* Message printing */ void b43info(struct b43_wl *wl, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 8f7a8c0..16580d0 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -107,9 +107,9 @@ int b43_modparam_verbose = B43_VERBOSITY_DEFAULT; module_param_named(verbose, b43_modparam_verbose, int, 0644); MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug"); -static int modparam_pio; -module_param_named(pio, modparam_pio, int, 0444); -MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode"); +int b43_modparam_pio = B43_PIO_DEFAULT; +module_param_named(pio, b43_modparam_pio, int, 0644); +MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO"); static const struct ssb_device_id b43_ssb_tbl[] = { SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), @@ -1804,8 +1804,9 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) dma_reason[4], dma_reason[5]); b43err(dev->wl, "This device does not support DMA " "on your system. Please use PIO instead.\n"); - b43err(dev->wl, "Unload the b43 module and reload " - "with 'pio=1'\n"); + /* Fall back to PIO transfers if we get fatal DMA errors! */ + dev->use_pio = 1; + b43_controller_restart(dev, "DMA error"); return; } if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { @@ -4357,7 +4358,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) || - modparam_pio) { + dev->use_pio) { dev->__using_pio_transfers = 1; err = b43_pio_init(dev); } else { @@ -4824,6 +4825,7 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl) if (!wldev) goto out; + wldev->use_pio = b43_modparam_pio; wldev->dev = dev; wldev->wl = wl; b43_set_status(wldev, B43_STAT_UNINIT); -- cgit v0.10.2