diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
40 files changed, 1826 insertions, 2066 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 82b66a3d3a5d..b0ac0ce3fb9f 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -14,18 +14,49 @@ config IWLWIFI_LEDS default n config IWLWIFI_RFKILL - boolean "IWLWIFI RF kill support" + boolean "Iwlwifi RF kill support" depends on IWLCORE -config IWL4965 - tristate "Intel Wireless WiFi 4965AGN" +config IWLWIFI_DEBUG + bool "Enable full debugging output in iwlagn driver" + depends on IWLCORE + ---help--- + This option will enable debug tracing output for the iwlwifi drivers + + This will result in the kernel module being ~100k larger. You can + control which debug output is sent to the kernel log by setting the + value in + + /sys/class/net/wlan0/device/debug_level + + This entry will only exist if this option is enabled. + + To set a value, simply echo an 8-byte hex value to the same file: + + % echo 0x43fff > /sys/class/net/wlan0/device/debug_level + + You can find the list of debug mask values in: + drivers/net/wireless/iwlwifi/iwl-debug.h + + If this is your first time using this driver, you should say Y here + as the debug information can assist others in helping you resolve + any problems you may encounter. + +config IWLWIFI_DEBUGFS + bool "Iwlwifi debugfs support" + depends on IWLCORE && IWLWIFI_DEBUG && MAC80211_DEBUGFS + ---help--- + Enable creation of debugfs files for the iwlwifi drivers. + +config IWLAGN + tristate "Intel Wireless WiFi Next Gen AGN" depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL select FW_LOADER select IWLCORE ---help--- Select to build the driver supporting the: - Intel Wireless WiFi Link 4965AGN + Intel Wireless WiFi Link Next-Gen AGN This driver uses the kernel's mac80211 subsystem. @@ -42,60 +73,33 @@ config IWL4965 If you want to compile the driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read <file:Documentation/kbuild/modules.txt>. The - module will be called iwl4965.ko. - -config IWL4965_LEDS - bool "Enable LEDS features in iwl4965 driver" - depends on IWL4965 - select IWLWIFI_LEDS - ---help--- - This option enables LEDS for the iwlwifi drivers + module will be called iwlagn.ko. - -config IWL4965_SPECTRUM_MEASUREMENT - bool "Enable Spectrum Measurement in iwl4965 driver" - depends on IWL4965 +config IWLAGN_SPECTRUM_MEASUREMENT + bool "Enable Spectrum Measurement in iwlagn driver" + depends on IWLAGN ---help--- - This option will enable spectrum measurement for the iwl4965 driver. + This option will enable spectrum measurement for the iwlagn driver. -config IWLWIFI_DEBUG - bool "Enable full debugging output in iwl4965 driver" - depends on IWL4965 +config IWLAGN_LEDS + bool "Enable LEDS features in iwlagn driver" + depends on IWLAGN + select IWLWIFI_LEDS ---help--- - This option will enable debug tracing output for the iwl4965 - driver. - - This will result in the kernel module being ~100k larger. You can - control which debug output is sent to the kernel log by setting the - value in - - /sys/class/net/wlan0/device/debug_level - - This entry will only exist if this option is enabled. - - To set a value, simply echo an 8-byte hex value to the same file: - - % echo 0x43fff > /sys/class/net/wlan0/device/debug_level + This option enables LEDS for the iwlagn drivers - You can find the list of debug mask values in: - drivers/net/wireless/iwlwifi/iwl-4965-debug.h - If this is your first time using this driver, you should say Y here - as the debug information can assist others in helping you resolve - any problems you may encounter. +config IWL4965 + bool "Intel Wireless WiFi 4965AGN" + depends on IWLAGN + ---help--- + This option enables support for Intel Wireless WiFi Link 4965AGN config IWL5000 bool "Intel Wireless WiFi 5000AGN" - depends on IWL4965 + depends on IWLAGN ---help--- This option enables support for Intel Wireless WiFi Link 5000AGN Family - Dependency on 4965 is temporary - -config IWLWIFI_DEBUGFS - bool "Iwlwifi debugfs support" - depends on IWLCORE && IWLWIFI_DEBUG && MAC80211_DEBUGFS - ---help--- - Enable creation of debugfs files for the iwlwifi drivers. config IWL3945 tristate "Intel PRO/Wireless 3945ABG/BG Network Connection" diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 1f52b92f08b5..47aa28f6a513 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -6,15 +6,14 @@ iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o +obj-$(CONFIG_IWLAGN) += iwlagn.o +iwlagn-objs := iwl-agn.o iwl-agn-rs.o + +iwlagn-$(CONFIG_IWL4965) += iwl-4965.o +iwlagn-$(CONFIG_IWL5000) += iwl-5000.o + obj-$(CONFIG_IWL3945) += iwl3945.o iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl3945-$(CONFIG_IWL3945_LEDS) += iwl-3945-led.o -obj-$(CONFIG_IWL4965) += iwl4965.o -iwl4965-objs := iwl4965-base.o iwl-4965.o iwl-4965-rs.o - -ifeq ($(CONFIG_IWL5000),y) - iwl4965-objs += iwl-5000.o -endif - diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h index f1d002f7b790..33016fb5e9b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h @@ -34,12 +34,12 @@ extern u32 iwl3945_debug_level; #define IWL_DEBUG(level, fmt, args...) \ do { if (iwl3945_debug_level & (level)) \ printk(KERN_ERR DRV_NAME": %c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) + in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) #define IWL_DEBUG_LIMIT(level, fmt, args...) \ do { if ((iwl3945_debug_level & (level)) && net_ratelimit()) \ printk(KERN_ERR DRV_NAME": %c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) + in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) static inline void iwl3945_print_hex_dump(int level, void *p, u32 len) { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-io.h b/drivers/net/wireless/iwlwifi/iwl-3945-io.h index 0b9475114618..b3fe48de3ae7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-io.h @@ -59,7 +59,7 @@ * */ -#define _iwl3945_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs)) +#define _iwl3945_write32(priv, ofs, val) iowrite32((val), (priv)->hw_base + (ofs)) #ifdef CONFIG_IWL3945_DEBUG static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv *priv, u32 ofs, u32 val) @@ -73,14 +73,14 @@ static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv * #define iwl3945_write32(priv, ofs, val) _iwl3945_write32(priv, ofs, val) #endif -#define _iwl3945_read32(priv, ofs) readl((priv)->hw_base + (ofs)) +#define _iwl3945_read32(priv, ofs) ioread32((priv)->hw_base + (ofs)) #ifdef CONFIG_IWL3945_DEBUG static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl3945_priv *priv, u32 ofs) { IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l); return _iwl3945_read32(priv, ofs); } -#define iwl3945_read32(priv, ofs) __iwl3945_read32(__FILE__, __LINE__, priv, ofs) +#define iwl3945_read32(priv, ofs)__iwl3945_read32(__FILE__, __LINE__, priv, ofs) #else #define iwl3945_read32(p, o) _iwl3945_read32(p, o) #endif @@ -153,28 +153,10 @@ static inline void __iwl3945_clear_bit(const char *f, u32 l, static inline int _iwl3945_grab_nic_access(struct iwl3945_priv *priv) { int ret; - u32 gp_ctl; - #ifdef CONFIG_IWL3945_DEBUG if (atomic_read(&priv->restrict_refcnt)) return 0; #endif - if (test_bit(STATUS_RF_KILL_HW, &priv->status) || - test_bit(STATUS_RF_KILL_SW, &priv->status)) { - IWL_WARNING("WARNING: Requesting MAC access during RFKILL " - "wakes up NIC\n"); - - /* 10 msec allows time for NIC to complete its data save */ - gp_ctl = _iwl3945_read32(priv, CSR_GP_CNTRL); - if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) { - IWL_DEBUG_RF_KILL("Wait for complete power-down, " - "gpctl = 0x%08x\n", gp_ctl); - mdelay(10); - } else - IWL_DEBUG_RF_KILL("power-down complete, " - "gpctl = 0x%08x\n", gp_ctl); - } - /* this bit wakes up the NIC */ _iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); ret = _iwl3945_poll_bit(priv, CSR_GP_CNTRL, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index 6be1fe13fa57..705c65bed9fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -27,7 +27,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/dma-mapping.h> @@ -206,12 +205,12 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, static int iwl3945_led_register_led(struct iwl3945_priv *priv, struct iwl3945_led *led, enum led_type type, u8 set_led, - const char *name, char *trigger) + char *trigger) { struct device *device = wiphy_dev(priv->hw->wiphy); int ret; - led->led_dev.name = name; + led->led_dev.name = led->name; led->led_dev.brightness_set = iwl3945_led_brightness_set; led->led_dev.default_trigger = trigger; @@ -308,7 +307,6 @@ void iwl3945_led_background(struct iwl3945_priv *priv) int iwl3945_led_register(struct iwl3945_priv *priv) { char *trigger; - char name[32]; int ret; priv->last_blink_rate = 0; @@ -318,7 +316,8 @@ int iwl3945_led_register(struct iwl3945_priv *priv) priv->allow_blinking = 0; trigger = ieee80211_get_radio_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:radio", + snprintf(priv->led[IWL_LED_TRG_RADIO].name, + sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s:radio", wiphy_name(priv->hw->wiphy)); priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on; @@ -327,19 +326,20 @@ int iwl3945_led_register(struct iwl3945_priv *priv) ret = iwl3945_led_register_led(priv, &priv->led[IWL_LED_TRG_RADIO], - IWL_LED_TRG_RADIO, 1, - name, trigger); + IWL_LED_TRG_RADIO, 1, trigger); + if (ret) goto exit_fail; trigger = ieee80211_get_assoc_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:assoc", + snprintf(priv->led[IWL_LED_TRG_ASSOC].name, + sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s:assoc", wiphy_name(priv->hw->wiphy)); ret = iwl3945_led_register_led(priv, &priv->led[IWL_LED_TRG_ASSOC], - IWL_LED_TRG_ASSOC, 0, - name, trigger); + IWL_LED_TRG_ASSOC, 0, trigger); + /* for assoc always turn led on */ priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on; priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on; @@ -349,14 +349,13 @@ int iwl3945_led_register(struct iwl3945_priv *priv) goto exit_fail; trigger = ieee80211_get_rx_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:RX", + snprintf(priv->led[IWL_LED_TRG_RX].name, + sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s:RX", wiphy_name(priv->hw->wiphy)); - ret = iwl3945_led_register_led(priv, &priv->led[IWL_LED_TRG_RX], - IWL_LED_TRG_RX, 0, - name, trigger); + IWL_LED_TRG_RX, 0, trigger); priv->led[IWL_LED_TRG_RX].led_on = iwl3945_led_associated; priv->led[IWL_LED_TRG_RX].led_off = iwl3945_led_associated; @@ -366,13 +365,14 @@ int iwl3945_led_register(struct iwl3945_priv *priv) goto exit_fail; trigger = ieee80211_get_tx_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:TX", + snprintf(priv->led[IWL_LED_TRG_TX].name, + sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s:TX", wiphy_name(priv->hw->wiphy)); ret = iwl3945_led_register_led(priv, &priv->led[IWL_LED_TRG_TX], - IWL_LED_TRG_TX, 0, - name, trigger); + IWL_LED_TRG_TX, 0, trigger); + priv->led[IWL_LED_TRG_TX].led_on = iwl3945_led_associated; priv->led[IWL_LED_TRG_TX].led_off = iwl3945_led_associated; priv->led[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h index 47b7e0bac802..2fbd126c1347 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h @@ -50,6 +50,7 @@ enum led_type { struct iwl3945_led { struct iwl3945_priv *priv; struct led_classdev led_dev; + char name[32]; int (*led_on) (struct iwl3945_priv *priv, int led_id); int (*led_off) (struct iwl3945_priv *priv, int led_id); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 10c64bdb314c..6fc5e7361f26 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -36,8 +36,6 @@ #include <linux/workqueue.h> -#include "../net/mac80211/rate.h" - #include "iwl-3945.h" #define RS_NAME "iwl-3945-rs" @@ -65,6 +63,9 @@ struct iwl3945_rs_sta { u8 ibss_sta_added; struct timer_list rate_scale_flush; struct iwl3945_rate_scale_data win[IWL_RATE_COUNT]; + + /* used to be in sta_info */ + int last_txrate_idx; }; static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT] = { @@ -316,9 +317,10 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, } } -static void rs_rate_init(void *priv_rate, void *priv_sta, - struct ieee80211_local *local, struct sta_info *sta) +static void rs_rate_init(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta) { + struct iwl3945_rs_sta *rs_sta = priv_sta; int i; IWL_DEBUG_RATE("enter\n"); @@ -329,24 +331,22 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, * after assoc.. */ for (i = IWL_RATE_COUNT - 1; i >= 0; i--) { - if (sta->supp_rates[local->hw.conf.channel->band] & (1 << i)) { - sta->txrate_idx = i; + if (sta->supp_rates[sband->band] & (1 << i)) { + rs_sta->last_txrate_idx = i; break; } } - sta->last_txrate_idx = sta->txrate_idx; - /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ - if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) - sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; + if (sband->band == IEEE80211_BAND_5GHZ) + rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; IWL_DEBUG_RATE("leave\n"); } -static void *rs_alloc(struct ieee80211_local *local) +static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) { - return local->hw.priv; + return hw->priv; } /* rate scale requires free function to be implemented */ @@ -354,17 +354,24 @@ static void rs_free(void *priv) { return; } + static void rs_clear(void *priv) { return; } -static void *rs_alloc_sta(void *priv, gfp_t gfp) +static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) { struct iwl3945_rs_sta *rs_sta; + struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; int i; + /* + * XXX: If it's using sta->drv_priv anyway, it might + * as well just put all the information there. + */ + IWL_DEBUG_RATE("enter\n"); rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp); @@ -373,6 +380,8 @@ static void *rs_alloc_sta(void *priv, gfp_t gfp) return NULL; } + psta->rs_sta = rs_sta; + spin_lock_init(&rs_sta->lock); rs_sta->start_rate = IWL_RATE_INVALID; @@ -398,10 +407,14 @@ static void *rs_alloc_sta(void *priv, gfp_t gfp) return rs_sta; } -static void rs_free_sta(void *priv, void *priv_sta) +static void rs_free_sta(void *priv, struct ieee80211_sta *sta, + void *priv_sta) { + struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; struct iwl3945_rs_sta *rs_sta = priv_sta; + psta->rs_sta = NULL; + IWL_DEBUG_RATE("enter\n"); del_timer_sync(&rs_sta->rate_scale_flush); kfree(rs_sta); @@ -443,26 +456,19 @@ static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate) * NOTE: Uses iwl3945_priv->retry_rate for the # of retries attempted by * the hardware for each rate. */ -static void rs_tx_status(void *priv_rate, - struct net_device *dev, +static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { u8 retries, current_count; int scale_rate_index, first_index, last_index; unsigned long flags; - struct sta_info *sta; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct iwl3945_rs_sta *rs_sta; - struct ieee80211_supported_band *sband; + struct iwl3945_rs_sta *rs_sta = priv_sta; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); IWL_DEBUG_RATE("enter\n"); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - retries = info->status.retry_count; first_index = sband->bitrates[info->tx_rate_idx].hw_value; if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { @@ -470,17 +476,11 @@ static void rs_tx_status(void *priv_rate, return; } - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); - if (!sta || !sta->rate_ctrl_priv) { - rcu_read_unlock(); + if (!priv_sta) { IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); return; } - rs_sta = (void *)sta->rate_ctrl_priv; - rs_sta->tx_packets++; scale_rate_index = first_index; @@ -547,8 +547,6 @@ static void rs_tx_status(void *priv_rate, spin_unlock_irqrestore(&rs_sta->lock, flags); - rcu_read_unlock(); - IWL_DEBUG_RATE("leave\n"); return; @@ -632,16 +630,15 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, * rate table and must reference the driver allocated rate table * */ -static void rs_get_rate(void *priv_rate, struct net_device *dev, - struct ieee80211_supported_band *sband, - struct sk_buff *skb, - struct rate_selection *sel) +static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb, struct rate_selection *sel) { u8 low = IWL_RATE_INVALID; u8 high = IWL_RATE_INVALID; u16 high_low; int index; - struct iwl3945_rs_sta *rs_sta; + struct iwl3945_rs_sta *rs_sta = priv_sta; struct iwl3945_rate_scale_data *window = NULL; int current_tpt = IWL_INV_TPT; int low_tpt = IWL_INV_TPT; @@ -649,40 +646,31 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, u32 fail_count; s8 scale_action = 0; unsigned long flags; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct sta_info *sta; u16 fc, rate_mask; - struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; + struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r; DECLARE_MAC_BUF(mac); IWL_DEBUG_RATE("enter\n"); - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); - /* Send management frames and broadcast/multicast data using lowest * rate. */ fc = le16_to_cpu(hdr->frame_control); if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || is_multicast_ether_addr(hdr->addr1) || - !sta || !sta->rate_ctrl_priv) { + !sta || !priv_sta) { IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); - sel->rate_idx = rate_lowest_index(local, sband, sta); - rcu_read_unlock(); + sel->rate_idx = rate_lowest_index(sband, sta); return; } rate_mask = sta->supp_rates[sband->band]; - index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); + index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); if (sband->band == IEEE80211_BAND_5GHZ) rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; - rs_sta = (void *)sta->rate_ctrl_priv; - - if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && + if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && !rs_sta->ibss_sta_added) { u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1); @@ -803,17 +791,13 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, out: - sta->last_txrate_idx = index; + rs_sta->last_txrate_idx = index; if (sband->band == IEEE80211_BAND_5GHZ) - sta->txrate_idx = sta->last_txrate_idx - IWL_FIRST_OFDM_RATE; + sel->rate_idx = rs_sta->last_txrate_idx - IWL_FIRST_OFDM_RATE; else - sta->txrate_idx = sta->last_txrate_idx; - - rcu_read_unlock(); + sel->rate_idx = rs_sta->last_txrate_idx; IWL_DEBUG_RATE("leave: %d\n", index); - - sel->rate_idx = sta->txrate_idx; } static struct rate_control_ops rs_ops = { @@ -829,114 +813,28 @@ static struct rate_control_ops rs_ops = { .free_sta = rs_free_sta, }; -int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) -{ - struct ieee80211_local *local = hw_to_local(hw); - struct iwl3945_priv *priv = hw->priv; - struct iwl3945_rs_sta *rs_sta; - struct sta_info *sta; - unsigned long flags; - int count = 0, i; - u32 samples = 0, success = 0, good = 0; - unsigned long now = jiffies; - u32 max_time = 0; - - rcu_read_lock(); - - sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); - if (!sta || !sta->rate_ctrl_priv) { - if (sta) - IWL_DEBUG_RATE("leave - no private rate data!\n"); - else - IWL_DEBUG_RATE("leave - no station!\n"); - rcu_read_unlock(); - return sprintf(buf, "station %d not found\n", sta_id); - } - - rs_sta = (void *)sta->rate_ctrl_priv; - spin_lock_irqsave(&rs_sta->lock, flags); - i = IWL_RATE_54M_INDEX; - while (1) { - u64 mask; - int j; - - count += - sprintf(&buf[count], " %2dMbs: ", iwl3945_rates[i].ieee / 2); - - mask = (1ULL << (IWL_RATE_MAX_WINDOW - 1)); - for (j = 0; j < IWL_RATE_MAX_WINDOW; j++, mask >>= 1) - buf[count++] = - (rs_sta->win[i].data & mask) ? '1' : '0'; - - samples += rs_sta->win[i].counter; - good += rs_sta->win[i].success_counter; - success += rs_sta->win[i].success_counter * - iwl3945_rates[i].ieee; - - if (rs_sta->win[i].stamp) { - int delta = - jiffies_to_msecs(now - rs_sta->win[i].stamp); - - if (delta > max_time) - max_time = delta; - - count += sprintf(&buf[count], "%5dms\n", delta); - } else - buf[count++] = '\n'; - - j = iwl3945_get_prev_ieee_rate(i); - if (j == i) - break; - i = j; - } - spin_unlock_irqrestore(&rs_sta->lock, flags); - rcu_read_unlock(); - - /* Display the average rate of all samples taken. - * - * NOTE: We multiple # of samples by 2 since the IEEE measurement - * added from iwl3945_rates is actually 2X the rate */ - if (samples) - count += sprintf( - &buf[count], - "\nAverage rate is %3d.%02dMbs over last %4dms\n" - "%3d%% success (%d good packets over %d tries)\n", - success / (2 * samples), (success * 5 / samples) % 10, - max_time, good * 100 / samples, good, samples); - else - count += sprintf(&buf[count], "\nAverage rate: 0Mbs\n"); - - return count; -} - void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) { struct iwl3945_priv *priv = hw->priv; s32 rssi = 0; unsigned long flags; - struct ieee80211_local *local = hw_to_local(hw); struct iwl3945_rs_sta *rs_sta; - struct sta_info *sta; + struct ieee80211_sta *sta; + struct iwl3945_sta_priv *psta; IWL_DEBUG_RATE("enter\n"); - if (!local->rate_ctrl->ops->name || - strcmp(local->rate_ctrl->ops->name, RS_NAME)) { - IWL_WARNING("iwl-3945-rs not selected as rate control algo!\n"); - IWL_DEBUG_RATE("leave - mac80211 picked the wrong RC algo.\n"); - return; - } - rcu_read_lock(); - sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); - if (!sta || !sta->rate_ctrl_priv) { + sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr); + psta = (void *) sta->drv_priv; + if (!sta || !psta) { IWL_DEBUG_RATE("leave - no private rate data!\n"); rcu_read_unlock(); return; } - rs_sta = (void *)sta->rate_ctrl_priv; + rs_sta = psta->rs_sta; spin_lock_irqsave(&rs_sta->lock, flags); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h index f085d330bdcf..98b17ae6ef24 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h @@ -176,15 +176,6 @@ static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index) } /** - * iwl3945_fill_rs_info - Fill an output text buffer with the rate representation - * - * NOTE: This is provided as a quick mechanism for a user to visualize - * the performance of the rate control algorithm and is not meant to be - * parsed software. - */ -extern int iwl3945_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id); - -/** * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info * * The specific throughput table used is based on the type of network diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index c2a76785b665..7ca5627cc078 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -26,7 +26,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/dma-mapping.h> @@ -521,10 +520,10 @@ static int iwl3945_is_network_packet(struct iwl3945_priv *priv, /* Filter incoming packets to determine if they are targeted toward * this network, discarding packets coming from ourselves */ switch (priv->iw_mode) { - case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */ + case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */ /* packets to our IBSS update information */ return !compare_ether_addr(header->addr3, priv->bssid); - case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */ + case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */ /* packets to our IBSS update information */ return !compare_ether_addr(header->addr2, priv->bssid); default: @@ -532,105 +531,14 @@ static int iwl3945_is_network_packet(struct iwl3945_priv *priv, } } -static void iwl3945_add_radiotap(struct iwl3945_priv *priv, - struct sk_buff *skb, - struct iwl3945_rx_frame_hdr *rx_hdr, - struct ieee80211_rx_status *stats) -{ - /* First cache any information we need before we overwrite - * the information provided in the skb from the hardware */ - s8 signal = stats->signal; - s8 noise = 0; - int rate = stats->rate_idx; - u64 tsf = stats->mactime; - __le16 phy_flags_hw = rx_hdr->phy_flags, antenna; - - struct iwl3945_rt_rx_hdr { - struct ieee80211_radiotap_header rt_hdr; - __le64 rt_tsf; /* TSF */ - u8 rt_flags; /* radiotap packet flags */ - u8 rt_rate; /* rate in 500kb/s */ - __le16 rt_channelMHz; /* channel in MHz */ - __le16 rt_chbitmask; /* channel bitfield */ - s8 rt_dbmsignal; /* signal in dBm, kluged to signed */ - s8 rt_dbmnoise; - u8 rt_antenna; /* antenna number */ - } __attribute__ ((packed)) *iwl3945_rt; - - if (skb_headroom(skb) < sizeof(*iwl3945_rt)) { - if (net_ratelimit()) - printk(KERN_ERR "not enough headroom [%d] for " - "radiotap head [%zd]\n", - skb_headroom(skb), sizeof(*iwl3945_rt)); - return; - } - - /* put radiotap header in front of 802.11 header and data */ - iwl3945_rt = (void *)skb_push(skb, sizeof(*iwl3945_rt)); - - /* initialise radiotap header */ - iwl3945_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; - iwl3945_rt->rt_hdr.it_pad = 0; - - /* total header + data */ - put_unaligned_le16(sizeof(*iwl3945_rt), &iwl3945_rt->rt_hdr.it_len); - - /* Indicate all the fields we add to the radiotap header */ - put_unaligned_le32((1 << IEEE80211_RADIOTAP_TSFT) | - (1 << IEEE80211_RADIOTAP_FLAGS) | - (1 << IEEE80211_RADIOTAP_RATE) | - (1 << IEEE80211_RADIOTAP_CHANNEL) | - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | - (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | - (1 << IEEE80211_RADIOTAP_ANTENNA), - &iwl3945_rt->rt_hdr.it_present); - - /* Zero the flags, we'll add to them as we go */ - iwl3945_rt->rt_flags = 0; - - put_unaligned_le64(tsf, &iwl3945_rt->rt_tsf); - - iwl3945_rt->rt_dbmsignal = signal; - iwl3945_rt->rt_dbmnoise = noise; - - /* Convert the channel frequency and set the flags */ - put_unaligned_le16(stats->freq, &iwl3945_rt->rt_channelMHz); - if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK)) - put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, - &iwl3945_rt->rt_chbitmask); - else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK) - put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ, - &iwl3945_rt->rt_chbitmask); - else /* 802.11g */ - put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ, - &iwl3945_rt->rt_chbitmask); - - if (rate == -1) - iwl3945_rt->rt_rate = 0; - else { - if (stats->band == IEEE80211_BAND_5GHZ) - rate += IWL_FIRST_OFDM_RATE; - - iwl3945_rt->rt_rate = iwl3945_rates[rate].ieee; - } - - /* antenna number */ - antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK; - iwl3945_rt->rt_antenna = le16_to_cpu(antenna) >> 4; - - /* set the preamble flag if we have it */ - if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) - iwl3945_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; - - stats->flag |= RX_FLAG_RADIOTAP; -} - static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb, struct ieee80211_rx_status *stats) { struct iwl3945_rx_packet *pkt = (struct iwl3945_rx_packet *)rxb->skb->data; +#ifdef CONFIG_IWL3945_LEDS struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); +#endif struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); short len = le16_to_cpu(rx_hdr->len); @@ -656,9 +564,6 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv, iwl3945_set_decrypted_flag(priv, rxb->skb, le32_to_cpu(rx_end->status), stats); - if (priv->add_radiotap) - iwl3945_add_radiotap(priv, rxb->skb, rx_hdr, stats); - #ifdef CONFIG_IWL3945_LEDS if (ieee80211_is_data(hdr->frame_control)) priv->rxtxpackets += len; @@ -683,7 +588,6 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff); u8 network_packet; - rx_status.antenna = 0; rx_status.flag = 0; rx_status.mactime = le64_to_cpu(rx_end->timestamp); rx_status.freq = @@ -695,6 +599,13 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, if (rx_status.band == IEEE80211_BAND_5GHZ) rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; + rx_status.antenna = le16_to_cpu(rx_hdr->phy_flags & + RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4; + + /* set the preamble flag if appropriate */ + if (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) + rx_status.flag |= RX_FLAG_SHORTPRE; + if ((unlikely(rx_stats->phy_count > 20))) { IWL_DEBUG_DROP ("dsp size out of range [0,20]: " @@ -708,10 +619,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, return; } - if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { - iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); - return; - } + /* Convert 3945's rssi indicator to dBm */ rx_status.signal = rx_stats->rssi - IWL_RSSI_OFFSET; @@ -773,96 +681,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, priv->last_rx_noise = rx_status.noise; } - switch (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FTYPE) { - case IEEE80211_FTYPE_MGMT: - switch (le16_to_cpu(header->frame_control) & - IEEE80211_FCTL_STYPE) { - case IEEE80211_STYPE_PROBE_RESP: - case IEEE80211_STYPE_BEACON:{ - /* If this is a beacon or probe response for - * our network then cache the beacon - * timestamp */ - if ((((priv->iw_mode == IEEE80211_IF_TYPE_STA) - && !compare_ether_addr(header->addr2, - priv->bssid)) || - ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) - && !compare_ether_addr(header->addr3, - priv->bssid)))) { - struct ieee80211_mgmt *mgmt = - (struct ieee80211_mgmt *)header; - __le32 *pos; - pos = - (__le32 *) & mgmt->u.beacon. - timestamp; - priv->timestamp0 = le32_to_cpu(pos[0]); - priv->timestamp1 = le32_to_cpu(pos[1]); - priv->beacon_int = le16_to_cpu( - mgmt->u.beacon.beacon_int); - if (priv->call_post_assoc_from_beacon && - (priv->iw_mode == - IEEE80211_IF_TYPE_STA)) - queue_work(priv->workqueue, - &priv->post_associate.work); - - priv->call_post_assoc_from_beacon = 0; - } - - break; - } - - case IEEE80211_STYPE_ACTION: - /* TODO: Parse 802.11h frames for CSA... */ - break; - - /* - * TODO: Use the new callback function from - * mac80211 instead of sniffing these packets. - */ - case IEEE80211_STYPE_ASSOC_RESP: - case IEEE80211_STYPE_REASSOC_RESP:{ - struct ieee80211_mgmt *mgnt = - (struct ieee80211_mgmt *)header; - - /* We have just associated, give some - * time for the 4-way handshake if - * any. Don't start scan too early. */ - priv->next_scan_jiffies = jiffies + - IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; - - priv->assoc_id = (~((1 << 15) | (1 << 14)) & - le16_to_cpu(mgnt->u. - assoc_resp.aid)); - priv->assoc_capability = - le16_to_cpu(mgnt->u.assoc_resp.capab_info); - if (priv->beacon_int) - queue_work(priv->workqueue, - &priv->post_associate.work); - else - priv->call_post_assoc_from_beacon = 1; - break; - } - - case IEEE80211_STYPE_PROBE_REQ:{ - DECLARE_MAC_BUF(mac1); - DECLARE_MAC_BUF(mac2); - DECLARE_MAC_BUF(mac3); - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) - IWL_DEBUG_DROP - ("Dropping (non network): %s" - ", %s, %s\n", - print_mac(mac1, header->addr1), - print_mac(mac2, header->addr2), - print_mac(mac3, header->addr3)); - return; - } - } - - case IEEE80211_FTYPE_DATA: - /* fall through */ - default: - iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); - break; - } + iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); } int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl3945_priv *priv, void *ptr, @@ -988,7 +807,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv, priv->stations[sta_id].current_rate.rate_n_flags = rate; - if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && + if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && (sta_id != priv->hw_setting.bcast_sta_id) && (sta_id != IWL_MULTICAST_ID)) priv->stations[IWL_STA_ID].current_rate.rate_n_flags = rate; @@ -1505,7 +1324,7 @@ static int iwl3945_hw_reg_adjust_power_by_temp(int new_reading, int old_reading) */ static inline int iwl3945_hw_reg_temp_out_of_range(int temperature) { - return (((temperature < -260) || (temperature > 25)) ? 1 : 0); + return ((temperature < -260) || (temperature > 25)) ? 1 : 0; } int iwl3945_hw_get_temperature(struct iwl3945_priv *priv) @@ -2626,7 +2445,7 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv, tx_beacon_cmd->tx.supp_rates[1] = (IWL_CCK_BASIC_RATES_MASK & 0xF); - return (sizeof(struct iwl3945_tx_beacon_cmd) + frame_size); + return sizeof(struct iwl3945_tx_beacon_cmd) + frame_size; } void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index fa81ba1af3d3..bdd32475b99c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -73,6 +73,10 @@ extern struct pci_device_id iwl3945_hw_card_ids[]; extern int iwl3945_param_hwcrypto; extern int iwl3945_param_queues_num; +struct iwl3945_sta_priv { + struct iwl3945_rs_sta *rs_sta; +}; + enum iwl3945_antenna { IWL_ANTENNA_DIVERSITY, IWL_ANTENNA_MAIN, @@ -707,7 +711,6 @@ struct iwl3945_priv { enum ieee80211_band band; int alloc_rxb_skb; - bool add_radiotap; void (*rx_handlers[REPLY_MAX])(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb); @@ -852,7 +855,7 @@ struct iwl3945_priv { /* eeprom */ struct iwl3945_eeprom eeprom; - enum ieee80211_if_types iw_mode; + enum nl80211_iftype iw_mode; struct sk_buff *ibss_beacon; @@ -895,7 +898,6 @@ struct iwl3945_priv { struct delayed_work thermal_periodic; struct delayed_work gather_stats; struct delayed_work scan_check; - struct delayed_work post_associate; #define IWL_DEFAULT_TX_POWER 0x0F s8 user_txpower_limit; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index fce950f4163c..f4793a609443 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -98,16 +98,17 @@ #define IWL_RSSI_OFFSET 44 -#include "iwl-commands.h" /* PCI registers */ -#define PCI_LINK_CTRL 0x0F0 /* 1 byte */ -#define PCI_POWER_SOURCE 0x0C8 -#define PCI_REG_WUM8 0x0E8 +#define PCI_CFG_RETRY_TIMEOUT 0x041 +#define PCI_CFG_POWER_SOURCE 0x0C8 +#define PCI_REG_WUM8 0x0E8 +#define PCI_CFG_LINK_CTRL 0x0F0 /* PCI register values */ -#define PCI_LINK_VAL_L0S_EN 0x01 -#define PCI_LINK_VAL_L1_EN 0x02 +#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 +#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 +#define PCI_CFG_CMD_REG_INT_DIS_MSK 0x04 #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000) #define TFD_QUEUE_SIZE_MAX (256) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 9afecb813716..9838de5f4369 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -26,7 +26,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/dma-mapping.h> @@ -341,39 +340,6 @@ err: return -EINVAL; } -int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) -{ - int ret; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - ret = iwl_grab_nic_access(priv); - if (ret) { - spin_unlock_irqrestore(&priv->lock, flags); - return ret; - } - - if (src == IWL_PWR_SRC_VAUX) { - u32 val; - ret = pci_read_config_dword(priv->pci_dev, PCI_POWER_SOURCE, - &val); - - if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT) { - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_PWR_SRC_VAUX, - ~APMG_PS_CTRL_MSK_PWR_SRC); - } - } else { - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, - ~APMG_PS_CTRL_MSK_PWR_SRC); - } - - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - return ret; -} /* * Activate/Deactivat Tx DMA/FIFO channels according tx fifos mask @@ -433,7 +399,7 @@ static void iwl4965_nic_config(struct iwl_priv *priv) unsigned long flags; u32 val; u16 radio_cfg; - u8 val_link; + u16 link; spin_lock_irqsave(&priv->lock, flags); @@ -444,10 +410,10 @@ static void iwl4965_nic_config(struct iwl_priv *priv) val & ~(1 << 11)); } - pci_read_config_byte(priv->pci_dev, PCI_LINK_CTRL, &val_link); + pci_read_config_word(priv->pci_dev, PCI_CFG_LINK_CTRL, &link); /* L1 is enabled by BIOS */ - if ((val_link & PCI_LINK_VAL_L1_EN) == PCI_LINK_VAL_L1_EN) + if ((link & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN) /* diable L0S disabled L1A enabled */ iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); else @@ -508,8 +474,8 @@ static void iwl4965_apm_stop(struct iwl_priv *priv) iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); udelay(10); - - iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + /* clear "init complete" move adapter D0A* --> D0U state */ + iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); spin_unlock_irqrestore(&priv->lock, flags); } @@ -875,18 +841,6 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) return 0; } -/* set card power command */ -static int iwl4965_set_power(struct iwl_priv *priv, - void *cmd) -{ - int ret = 0; - - ret = iwl_send_cmd_pdu_async(priv, POWER_TABLE_CMD, - sizeof(struct iwl4965_powertable_cmd), - cmd, NULL); - return ret; -} - static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res) { s32 sign = 1; @@ -1012,7 +966,7 @@ static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel, s = iwl4965_get_sub_band(priv, channel); if (s >= EEPROM_TX_POWER_BANDS) { - IWL_ERROR("Tx Power can not find channel %d ", channel); + IWL_ERROR("Tx Power can not find channel %d\n", channel); return -1; } @@ -1560,11 +1514,11 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, c, atten_value, power_index, tx_power.s.radio_tx_gain[c], tx_power.s.dsp_predis_atten[c]); - }/* for each chain */ + } /* for each chain */ tx_power_tbl->power_tbl[i].dw = cpu_to_le32(tx_power.dw); - }/* for each rate */ + } /* for each rate */ return 0; } @@ -1653,8 +1607,8 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) return ret; } - -int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) +#ifdef IEEE80211_CONF_CHANNEL_SWITCH +static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) { int rc; u8 band = 0; @@ -1694,6 +1648,7 @@ int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); return rc; } +#endif static int iwl4965_shared_mem_rx_idx(struct iwl_priv *priv) { @@ -1701,38 +1656,6 @@ static int iwl4965_shared_mem_rx_idx(struct iwl_priv *priv) return le32_to_cpu(s->rb_closed) & 0xFFF; } -unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, - struct iwl_frame *frame, u8 rate) -{ - struct iwl4965_tx_beacon_cmd *tx_beacon_cmd; - unsigned int frame_size; - - tx_beacon_cmd = &frame->u.beacon; - memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); - - tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; - tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - - frame_size = iwl4965_fill_beacon_frame(priv, - tx_beacon_cmd->frame, - iwl_bcast_addr, - sizeof(frame->u) - sizeof(*tx_beacon_cmd)); - - BUG_ON(frame_size > MAX_MPDU_SIZE); - tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); - - if ((rate == IWL_RATE_1M_PLCP) || (rate >= IWL_RATE_2M_PLCP)) - tx_beacon_cmd->tx.rate_n_flags = - iwl_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK); - else - tx_beacon_cmd->tx.rate_n_flags = - iwl_hw_set_rate_n_flags(rate, 0); - - tx_beacon_cmd->tx.tx_flags = (TX_CMD_FLG_SEQ_CTL_MSK | - TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK); - return (sizeof(*tx_beacon_cmd) + frame_size); -} - static int iwl4965_alloc_shared_mem(struct iwl_priv *priv) { priv->shared_virt = pci_alloc_consistent(priv->pci_dev, @@ -2079,39 +2002,6 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, return 0; } -int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, - enum ieee80211_ampdu_mlme_action action, - const u8 *addr, u16 tid, u16 *ssn) -{ - struct iwl_priv *priv = hw->priv; - DECLARE_MAC_BUF(mac); - - IWL_DEBUG_HT("A-MPDU action on addr %s tid %d\n", - print_mac(mac, addr), tid); - - if (!(priv->cfg->sku & IWL_SKU_N)) - return -EACCES; - - switch (action) { - case IEEE80211_AMPDU_RX_START: - IWL_DEBUG_HT("start Rx\n"); - return iwl_rx_agg_start(priv, addr, tid, *ssn); - case IEEE80211_AMPDU_RX_STOP: - IWL_DEBUG_HT("stop Rx\n"); - return iwl_rx_agg_stop(priv, addr, tid); - case IEEE80211_AMPDU_TX_START: - IWL_DEBUG_HT("start Tx\n"); - return iwl_tx_agg_start(priv, addr, tid, ssn); - case IEEE80211_AMPDU_TX_STOP: - IWL_DEBUG_HT("stop Tx\n"); - return iwl_tx_agg_stop(priv, addr, tid); - default: - IWL_DEBUG_HT("unknown\n"); - return -EINVAL; - break; - } - return 0; -} static u16 iwl4965_get_hcmd_size(u8 cmd_id, u16 len) { @@ -2240,9 +2130,9 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, bitmap = bitmap << sh; sh = 0; } - bitmap |= (1 << sh); - IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%x\n", - start, (u32)(bitmap & 0xFFFFFFFF)); + bitmap |= 1ULL << sh; + IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%llx\n", + start, (unsigned long long)bitmap); } agg->bitmap = bitmap; @@ -2368,6 +2258,40 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n"); } +static int iwl4965_calc_rssi(struct iwl_priv *priv, + struct iwl_rx_phy_res *rx_resp) +{ + /* data from PHY/DSP regarding signal strength, etc., + * contents are always there, not configurable by host. */ + struct iwl4965_rx_non_cfg_phy *ncphy = + (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy_buf; + u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL49_AGC_DB_MASK) + >> IWL49_AGC_DB_POS; + + u32 valid_antennae = + (le16_to_cpu(rx_resp->phy_flags) & IWL49_RX_PHY_FLAGS_ANTENNAE_MASK) + >> IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET; + u8 max_rssi = 0; + u32 i; + + /* Find max rssi among 3 possible receivers. + * These values are measured by the digital signal processor (DSP). + * They should stay fairly constant even as the signal strength varies, + * if the radio's automatic gain control (AGC) is working right. + * AGC value (see below) will provide the "interesting" info. */ + for (i = 0; i < 3; i++) + if (valid_antennae & (1 << i)) + max_rssi = max(ncphy->rssi_info[i << 1], max_rssi); + + IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n", + ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4], + max_rssi, agc); + + /* dBm = max_rssi dB - agc dB - constant. + * Higher AGC (higher radio gain) means lower signal. */ + return max_rssi - agc - IWL_RSSI_OFFSET; +} + /* Set up 4965-specific Rx frame reply handlers */ static void iwl4965_rx_handler_setup(struct iwl_priv *priv) @@ -2399,6 +2323,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { .chain_noise_reset = iwl4965_chain_noise_reset, .gain_computation = iwl4965_gain_computation, .rts_tx_cmd_flag = iwl4965_rts_tx_cmd_flag, + .calc_rssi = iwl4965_calc_rssi, }; static struct iwl_lib_ops iwl4965_lib = { @@ -2440,7 +2365,6 @@ static struct iwl_lib_ops iwl4965_lib = { .check_version = iwl4965_eeprom_check_version, .query_addr = iwlcore_eeprom_query_addr, }, - .set_power = iwl4965_set_power, .send_tx_power = iwl4965_send_tx_power, .update_chain_flags = iwl4965_update_chain_flags, .temperature = iwl4965_temperature_calib, @@ -2469,7 +2393,7 @@ MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); module_param_named(disable, iwl4965_mod_params.disable, int, 0444); MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); -MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])\n"); +MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); module_param_named(debug, iwl4965_mod_params.debug, int, 0444); MODULE_PARM_DESC(debug, "debug output mask"); module_param_named( diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 17d4f31c5934..c479ee211c5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h @@ -129,6 +129,13 @@ struct iwl5000_shared { __le32 padding2; } __attribute__ ((packed)); +/* calibrations defined for 5000 */ +/* defines the order in which results should be sent to the runtime uCode */ +enum iwl5000_calib { + IWL5000_CALIB_LO, + IWL5000_CALIB_TX_IQ, + IWL5000_CALIB_TX_IQ_PERD, +}; #endif /* __iwl_5000_hw_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 878d6193b232..f6003e7996af 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -25,7 +25,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/dma-mapping.h> @@ -93,6 +92,13 @@ static int iwl5000_apm_init(struct iwl_priv *priv) iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); + /* Set FH wait treshold to maximum (HW error during stress W/A) */ + iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); + + /* enable HAP INTA to move device L1a -> L0s */ + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); + iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); /* set "initialization complete" bit to move adapter @@ -139,7 +145,8 @@ static void iwl5000_apm_stop(struct iwl_priv *priv) udelay(10); - iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + /* clear "init complete" move adapter D0A* --> D0U state */ + iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); spin_unlock_irqrestore(&priv->lock, flags); } @@ -202,14 +209,14 @@ static void iwl5000_nic_config(struct iwl_priv *priv) { unsigned long flags; u16 radio_cfg; - u8 val_link; + u16 link; spin_lock_irqsave(&priv->lock, flags); - pci_read_config_byte(priv->pci_dev, PCI_LINK_CTRL, &val_link); + pci_read_config_word(priv->pci_dev, PCI_CFG_LINK_CTRL, &link); /* L1 is enabled by BIOS */ - if ((val_link & PCI_LINK_VAL_L1_EN) == PCI_LINK_VAL_L1_EN) + if ((link & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN) /* diable L0S disabled L1A enabled */ iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); else @@ -230,6 +237,16 @@ static void iwl5000_nic_config(struct iwl_priv *priv) CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); + /* W/A : NIC is stuck in a reset state after Early PCIe power off + * (PCIe power is lost before PERST# is asserted), + * causing ME FW to lose ownership and not being able to obtain it back. + */ + iwl_grab_nic_access(priv); + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, + ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->lock, flags); } @@ -428,48 +445,6 @@ static int iwl5000_send_Xtal_calib(struct iwl_priv *priv) sizeof(cal_cmd), &cal_cmd); } -static int iwl5000_send_calib_results(struct iwl_priv *priv) -{ - int ret = 0; - - struct iwl_host_cmd hcmd = { - .id = REPLY_PHY_CALIBRATION_CMD, - .meta.flags = CMD_SIZE_HUGE, - }; - - if (priv->calib_results.lo_res) { - hcmd.len = priv->calib_results.lo_res_len; - hcmd.data = priv->calib_results.lo_res; - ret = iwl_send_cmd_sync(priv, &hcmd); - - if (ret) - goto err; - } - - if (priv->calib_results.tx_iq_res) { - hcmd.len = priv->calib_results.tx_iq_res_len; - hcmd.data = priv->calib_results.tx_iq_res; - ret = iwl_send_cmd_sync(priv, &hcmd); - - if (ret) - goto err; - } - - if (priv->calib_results.tx_iq_perd_res) { - hcmd.len = priv->calib_results.tx_iq_perd_res_len; - hcmd.data = priv->calib_results.tx_iq_perd_res; - ret = iwl_send_cmd_sync(priv, &hcmd); - - if (ret) - goto err; - } - - return 0; -err: - IWL_ERROR("Error %d\n", ret); - return ret; -} - static int iwl5000_send_calib_cfg(struct iwl_priv *priv) { struct iwl5000_calib_cfg_cmd calib_cfg_cmd; @@ -494,33 +469,30 @@ static void iwl5000_rx_calib_result(struct iwl_priv *priv, struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl5000_calib_hdr *hdr = (struct iwl5000_calib_hdr *)pkt->u.raw; int len = le32_to_cpu(pkt->len) & FH_RSCSR_FRAME_SIZE_MSK; - - iwl_free_calib_results(priv); + int index; /* reduce the size of the length field itself */ len -= 4; + /* Define the order in which the results will be sent to the runtime + * uCode. iwl_send_calib_results sends them in a row according to their + * index. We sort them here */ switch (hdr->op_code) { case IWL5000_PHY_CALIBRATE_LO_CMD: - priv->calib_results.lo_res = kzalloc(len, GFP_ATOMIC); - priv->calib_results.lo_res_len = len; - memcpy(priv->calib_results.lo_res, pkt->u.raw, len); + index = IWL5000_CALIB_LO; break; case IWL5000_PHY_CALIBRATE_TX_IQ_CMD: - priv->calib_results.tx_iq_res = kzalloc(len, GFP_ATOMIC); - priv->calib_results.tx_iq_res_len = len; - memcpy(priv->calib_results.tx_iq_res, pkt->u.raw, len); + index = IWL5000_CALIB_TX_IQ; break; case IWL5000_PHY_CALIBRATE_TX_IQ_PERD_CMD: - priv->calib_results.tx_iq_perd_res = kzalloc(len, GFP_ATOMIC); - priv->calib_results.tx_iq_perd_res_len = len; - memcpy(priv->calib_results.tx_iq_perd_res, pkt->u.raw, len); + index = IWL5000_CALIB_TX_IQ_PERD; break; default: IWL_ERROR("Unknown calibration notification %d\n", hdr->op_code); return; } + iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); } static void iwl5000_rx_calib_complete(struct iwl_priv *priv, @@ -561,14 +533,11 @@ static int iwl5000_load_section(struct iwl_priv *priv, FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); - /* FIME: write the MSB of the phy_addr in CTRL1 - * iwl_write_direct32(priv, - IWL_FH_TFDIB_CTRL1_REG(IWL_FH_SRVC_CHNL), - ((phy_addr & MSB_MSK) - << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_count); - */ iwl_write_direct32(priv, - FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), byte_cnt); + FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), + (iwl_get_dma_hi_address(phy_addr) + << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); + iwl_write_direct32(priv, FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | @@ -818,7 +787,7 @@ static int iwl5000_alive_notify(struct iwl_priv *priv) iwl5000_send_Xtal_calib(priv); if (priv->ucode_type == UCODE_RT) - iwl5000_send_calib_results(priv); + iwl_send_calib_results(priv); return 0; } @@ -924,8 +893,8 @@ static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; if (txq_id != IWL_CMD_QUEUE_NUM) { - sta = txq->cmd[txq->q.write_ptr].cmd.tx.sta_id; - sec_ctl = txq->cmd[txq->q.write_ptr].cmd.tx.sec_ctl; + sta = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; + sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; switch (sec_ctl & TX_CMD_SEC_MSK) { case TX_CMD_SEC_CCM: @@ -964,7 +933,7 @@ static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, u8 sta = 0; if (txq_id != IWL_CMD_QUEUE_NUM) - sta = txq->cmd[txq->q.read_ptr].cmd.tx.sta_id; + sta = txq->cmd[txq->q.read_ptr]->cmd.tx.sta_id; shared_data->queues_byte_cnt_tbls[txq_id].tfd_offset[txq->q.read_ptr]. val = cpu_to_le16(1 | (sta << 12)); @@ -1131,7 +1100,7 @@ static void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask) static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) { - return le32_to_cpup((__le32*)&tx_resp->status + + return le32_to_cpup((__le32 *)&tx_resp->status + tx_resp->frame_count) & MAX_SN; } @@ -1228,9 +1197,9 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, bitmap = bitmap << sh; sh = 0; } - bitmap |= (1 << sh); - IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%x\n", - start, (u32)(bitmap & 0xFFFFFFFF)); + bitmap |= 1ULL << sh; + IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%llx\n", + start, (unsigned long long)bitmap); } agg->bitmap = bitmap; @@ -1444,6 +1413,44 @@ static void iwl5000_temperature(struct iwl_priv *priv) priv->temperature = le32_to_cpu(priv->statistics.general.temperature); } +/* Calc max signal level (dBm) among 3 possible receivers */ +static int iwl5000_calc_rssi(struct iwl_priv *priv, + struct iwl_rx_phy_res *rx_resp) +{ + /* data from PHY/DSP regarding signal strength, etc., + * contents are always there, not configurable by host + */ + struct iwl5000_non_cfg_phy *ncphy = + (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf; + u32 val, rssi_a, rssi_b, rssi_c, max_rssi; + u8 agc; + + val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]); + agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS; + + /* Find max rssi among 3 possible receivers. + * These values are measured by the digital signal processor (DSP). + * They should stay fairly constant even as the signal strength varies, + * if the radio's automatic gain control (AGC) is working right. + * AGC value (see below) will provide the "interesting" info. + */ + val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]); + rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS; + rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS; + val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]); + rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS; + + max_rssi = max_t(u32, rssi_a, rssi_b); + max_rssi = max_t(u32, max_rssi, rssi_c); + + IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n", + rssi_a, rssi_b, rssi_c, max_rssi, agc); + + /* dBm = max_rssi dB - agc dB - constant. + * Higher AGC (higher radio gain) means lower signal. */ + return max_rssi - agc - IWL_RSSI_OFFSET; +} + static struct iwl_hcmd_ops iwl5000_hcmd = { .rxon_assoc = iwl5000_send_rxon_assoc, }; @@ -1454,6 +1461,7 @@ static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { .gain_computation = iwl5000_gain_computation, .chain_noise_reset = iwl5000_chain_noise_reset, .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, + .calc_rssi = iwl5000_calc_rssi, }; static struct iwl_lib_ops iwl5000_lib = { @@ -1474,6 +1482,7 @@ static struct iwl_lib_ops iwl5000_lib = { .alive_notify = iwl5000_alive_notify, .send_tx_power = iwl5000_send_tx_power, .temperature = iwl5000_temperature, + .update_chain_flags = iwl4965_update_chain_flags, .apm_ops = { .init = iwl5000_apm_init, .reset = iwl5000_apm_reset, @@ -1560,6 +1569,8 @@ struct iwl_cfg iwl5350_agn_cfg = { .mod_params = &iwl50_mod_params, }; +MODULE_FIRMWARE("iwlwifi-5000" IWL5000_UCODE_API ".ucode"); + module_param_named(disable50, iwl50_mod_params.disable, int, 0444); MODULE_PARM_DESC(disable50, "manually disable the 50XX radio (default 0 [radio on])"); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 3ccb84aa5dbc..93944de923ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -35,14 +35,12 @@ #include <linux/workqueue.h> -#include "../net/mac80211/rate.h" - #include "iwl-dev.h" #include "iwl-sta.h" #include "iwl-core.h" #include "iwl-helpers.h" -#define RS_NAME "iwl-4965-rs" +#define RS_NAME "iwl-agn-rs" #define NUM_TRY_BEFORE_ANT_TOGGLE 1 #define IWL_NUMBER_TRY 1 @@ -77,9 +75,9 @@ static const u8 ant_toggle_lookup[] = { }; /** - * struct iwl4965_rate_scale_data -- tx success history for one rate + * struct iwl_rate_scale_data -- tx success history for one rate */ -struct iwl4965_rate_scale_data { +struct iwl_rate_scale_data { u64 data; /* bitmap of successful frames */ s32 success_counter; /* number of frames successful */ s32 success_ratio; /* per-cent * 128 */ @@ -89,12 +87,12 @@ struct iwl4965_rate_scale_data { }; /** - * struct iwl4965_scale_tbl_info -- tx params and success history for all rates + * struct iwl_scale_tbl_info -- tx params and success history for all rates * - * There are two of these in struct iwl4965_lq_sta, + * There are two of these in struct iwl_lq_sta, * one for "active", and one for "search". */ -struct iwl4965_scale_tbl_info { +struct iwl_scale_tbl_info { enum iwl_table_type lq_type; u8 ant_type; u8 is_SGI; /* 1 = short guard interval */ @@ -103,10 +101,10 @@ struct iwl4965_scale_tbl_info { u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ u32 current_rate; /* rate_n_flags, uCode API format */ - struct iwl4965_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ + struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ }; -struct iwl4965_traffic_load { +struct iwl_traffic_load { unsigned long time_stamp; /* age of the oldest statistics */ u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time * slice */ @@ -118,11 +116,11 @@ struct iwl4965_traffic_load { }; /** - * struct iwl4965_lq_sta -- driver's rate scaling private structure + * struct iwl_lq_sta -- driver's rate scaling private structure * * Pointer to this gets passed back and forth between driver and mac80211. */ -struct iwl4965_lq_sta { +struct iwl_lq_sta { u8 active_tbl; /* index of active table, range 0-1 */ u8 enable_counter; /* indicates HT mode */ u8 stay_in_tbl; /* 1: disallow, 0: allow search for new mode */ @@ -153,8 +151,8 @@ struct iwl4965_lq_sta { u16 active_rate_basic; struct iwl_link_quality_cmd lq; - struct iwl4965_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ - struct iwl4965_traffic_load load[TID_MAX_LOAD_COUNT]; + struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ + struct iwl_traffic_load load[TID_MAX_LOAD_COUNT]; u8 tx_agg_tid_en; #ifdef CONFIG_MAC80211_DEBUGFS struct dentry *rs_sta_dbgfs_scale_table_file; @@ -163,23 +161,25 @@ struct iwl4965_lq_sta { u32 dbg_fixed_rate; #endif struct iwl_priv *drv; + + /* used to be in sta_info */ + int last_txrate_idx; }; static void rs_rate_scale_perform(struct iwl_priv *priv, - struct net_device *dev, struct ieee80211_hdr *hdr, - struct sta_info *sta); + struct ieee80211_sta *sta, + struct iwl_lq_sta *lq_sta); static void rs_fill_link_cmd(const struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_sta, - u32 rate_n_flags); + struct iwl_lq_sta *lq_sta, u32 rate_n_flags); #ifdef CONFIG_MAC80211_DEBUGFS -static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta, - u32 *rate_n_flags, int index); +static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, + u32 *rate_n_flags, int index); #else -static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta, - u32 *rate_n_flags, int index) +static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, + u32 *rate_n_flags, int index) {} #endif @@ -234,7 +234,7 @@ static inline u8 rs_extract_rate(u32 rate_n_flags) return (u8)(rate_n_flags & 0xFF); } -static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window) +static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) { window->data = 0; window->success_counter = 0; @@ -246,14 +246,14 @@ static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window) static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type) { - return ((ant_type & valid_antenna) == ant_type); + return (ant_type & valid_antenna) == ant_type; } /* * removes the old data from the statistics. All data that is older than * TID_MAX_TIME_DIFF, will be deleted. */ -static void rs_tl_rm_old_stats(struct iwl4965_traffic_load *tl, u32 curr_time) +static void rs_tl_rm_old_stats(struct iwl_traffic_load *tl, u32 curr_time) { /* The oldest age we want to keep */ u32 oldest_time = curr_time - TID_MAX_TIME_DIFF; @@ -274,13 +274,13 @@ static void rs_tl_rm_old_stats(struct iwl4965_traffic_load *tl, u32 curr_time) * increment traffic load value for tid and also remove * any old values if passed the certain time period */ -static u8 rs_tl_add_packet(struct iwl4965_lq_sta *lq_data, +static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, struct ieee80211_hdr *hdr) { u32 curr_time = jiffies_to_msecs(jiffies); u32 time_diff; s32 index; - struct iwl4965_traffic_load *tl = NULL; + struct iwl_traffic_load *tl = NULL; __le16 fc = hdr->frame_control; u8 tid; @@ -325,12 +325,12 @@ static u8 rs_tl_add_packet(struct iwl4965_lq_sta *lq_data, /* get the traffic load value for tid */ -static u32 rs_tl_get_load(struct iwl4965_lq_sta *lq_data, u8 tid) +static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid) { u32 curr_time = jiffies_to_msecs(jiffies); u32 time_diff; s32 index; - struct iwl4965_traffic_load *tl = NULL; + struct iwl_traffic_load *tl = NULL; if (tid >= TID_MAX_LOAD_COUNT) return 0; @@ -354,18 +354,12 @@ static u32 rs_tl_get_load(struct iwl4965_lq_sta *lq_data, u8 tid) } static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_data, u8 tid, - struct sta_info *sta) + struct iwl_lq_sta *lq_data, u8 tid, + struct ieee80211_sta *sta) { - unsigned long state; DECLARE_MAC_BUF(mac); - spin_lock_bh(&sta->lock); - state = sta->ampdu_mlme.tid_state_tx[tid]; - spin_unlock_bh(&sta->lock); - - if (state == HT_AGG_STATE_IDLE && - rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { + if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { IWL_DEBUG_HT("Starting Tx agg: STA: %s tid: %d\n", print_mac(mac, sta->addr), tid); ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid); @@ -373,8 +367,8 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, } static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, - struct iwl4965_lq_sta *lq_data, - struct sta_info *sta) + struct iwl_lq_sta *lq_data, + struct ieee80211_sta *sta) { if ((tid < TID_MAX_LOAD_COUNT)) rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); @@ -385,9 +379,9 @@ static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, static inline int get_num_of_ant_from_rate(u32 rate_n_flags) { - return (!!(rate_n_flags & RATE_MCS_ANT_A_MSK) + - !!(rate_n_flags & RATE_MCS_ANT_B_MSK) + - !!(rate_n_flags & RATE_MCS_ANT_C_MSK)); + return !!(rate_n_flags & RATE_MCS_ANT_A_MSK) + + !!(rate_n_flags & RATE_MCS_ANT_B_MSK) + + !!(rate_n_flags & RATE_MCS_ANT_C_MSK); } /** @@ -397,11 +391,11 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags) * at this rate. window->data contains the bitmask of successful * packets. */ -static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows, +static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, int scale_index, s32 tpt, int retries, int successes) { - struct iwl4965_rate_scale_data *window = NULL; + struct iwl_rate_scale_data *window = NULL; static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); s32 fail_count; @@ -437,7 +431,7 @@ static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows, /* Shift bitmap by one frame (throw away oldest history), * OR in "1", and increment "success" if this * frame was successful. */ - window->data <<= 1;; + window->data <<= 1; if (successes > 0) { window->success_counter++; window->data |= 0x1; @@ -473,7 +467,7 @@ static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows, * Fill uCode API rate_n_flags field, based on "search" or "active" table. */ /* FIXME:RS:remove this function and put the flags statically in the table */ -static u32 rate_n_flags_from_tbl(struct iwl4965_scale_tbl_info *tbl, +static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl, int index, u8 use_green) { u32 rate_n_flags = 0; @@ -530,7 +524,7 @@ static u32 rate_n_flags_from_tbl(struct iwl4965_scale_tbl_info *tbl, */ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, enum ieee80211_band band, - struct iwl4965_scale_tbl_info *tbl, + struct iwl_scale_tbl_info *tbl, int *rate_idx) { u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK); @@ -591,7 +585,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, /* switch to another antenna/antennas and return 1 */ /* if no other valid antenna found, return 0 */ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, - struct iwl4965_scale_tbl_info *tbl) + struct iwl_scale_tbl_info *tbl) { u8 new_ant_type; @@ -621,9 +615,9 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, #if 0 static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf) { - return ((conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) && + return (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) && priv->current_ht_config.is_green_field && - !priv->current_ht_config.non_GF_STA_present); + !priv->current_ht_config.non_GF_STA_present; } #endif static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf) @@ -638,9 +632,9 @@ static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf * basic available rates. * */ -static u16 rs_get_supported_rates(struct iwl4965_lq_sta *lq_sta, - struct ieee80211_hdr *hdr, - enum iwl_table_type rate_type) +static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta, + struct ieee80211_hdr *hdr, + enum iwl_table_type rate_type) { if (hdr && is_multicast_ether_addr(hdr->addr1) && lq_sta->active_rate_basic) @@ -714,9 +708,9 @@ static u16 rs_get_adjacent_rate(struct iwl_priv *priv, u8 index, u16 rate_mask, return (high << 8) | low; } -static u32 rs_get_lower_rate(struct iwl4965_lq_sta *lq_sta, - struct iwl4965_scale_tbl_info *tbl, u8 scale_index, - u8 ht_possible) +static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl, + u8 scale_index, u8 ht_possible) { s32 low; u16 rate_mask; @@ -774,25 +768,24 @@ out: /* * mac80211 sends us Tx status */ -static void rs_tx_status(void *priv_rate, struct net_device *dev, +static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { int status; u8 retries; int rs_index, index = 0; - struct iwl4965_lq_sta *lq_sta; + struct iwl_lq_sta *lq_sta; struct iwl_link_quality_cmd *table; - struct sta_info *sta; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct iwl_priv *priv = (struct iwl_priv *)priv_rate; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_hw *hw = local_to_hw(local); + struct iwl_priv *priv = (struct iwl_priv *)priv_r; + struct ieee80211_hw *hw = priv->hw; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct iwl4965_rate_scale_data *window = NULL; - struct iwl4965_rate_scale_data *search_win = NULL; + struct iwl_rate_scale_data *window = NULL; + struct iwl_rate_scale_data *search_win = NULL; u32 tx_rate; - struct iwl4965_scale_tbl_info tbl_type; - struct iwl4965_scale_tbl_info *curr_tbl, *search_tbl; + struct iwl_scale_tbl_info tbl_type; + struct iwl_scale_tbl_info *curr_tbl, *search_tbl; u8 active_index = 0; __le16 fc = hdr->frame_control; s32 tpt = 0; @@ -812,17 +805,9 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, if (retries > 15) retries = 15; - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); + lq_sta = (struct iwl_lq_sta *)priv_sta; - if (!sta || !sta->rate_ctrl_priv) - goto out; - - - lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; - - if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && + if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && !lq_sta->ibss_sta_added) goto out; @@ -831,10 +816,8 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, curr_tbl = &(lq_sta->lq_info[active_index]); search_tbl = &(lq_sta->lq_info[(1 - active_index)]); - window = (struct iwl4965_rate_scale_data *) - &(curr_tbl->win[0]); - search_win = (struct iwl4965_rate_scale_data *) - &(search_tbl->win[0]); + window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]); + search_win = (struct iwl_rate_scale_data *)&(search_tbl->win[0]); /* * Ignore this Tx frame response if its initial rate doesn't match @@ -968,9 +951,8 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, } /* See if there's a better rate or modulation mode to try. */ - rs_rate_scale_perform(priv, dev, hdr, sta); + rs_rate_scale_perform(priv, hdr, sta, lq_sta); out: - rcu_read_unlock(); return; } @@ -983,7 +965,7 @@ out: * searching for a new mode. */ static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy, - struct iwl4965_lq_sta *lq_sta) + struct iwl_lq_sta *lq_sta) { IWL_DEBUG_RATE("we are staying in the same table\n"); lq_sta->stay_in_tbl = 1; /* only place this gets set */ @@ -1004,8 +986,8 @@ static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy, /* * Find correct throughput table for given mode of modulation */ -static void rs_set_expected_tpt_table(struct iwl4965_lq_sta *lq_sta, - struct iwl4965_scale_tbl_info *tbl) +static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl) { if (is_legacy(tbl->lq_type)) { if (!is_a_band(tbl->lq_type)) @@ -1050,12 +1032,12 @@ static void rs_set_expected_tpt_table(struct iwl4965_lq_sta *lq_sta, * bit rate will typically need to increase, but not if performance was bad. */ static s32 rs_get_best_rate(struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_sta, - struct iwl4965_scale_tbl_info *tbl, /* "search" */ + struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl, /* "search" */ u16 rate_mask, s8 index) { /* "active" values */ - struct iwl4965_scale_tbl_info *active_tbl = + struct iwl_scale_tbl_info *active_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); s32 active_sr = active_tbl->win[index].success_ratio; s32 active_tpt = active_tbl->expected_tpt[index]; @@ -1131,6 +1113,7 @@ static s32 rs_get_best_rate(struct iwl_priv *priv, /* Higher rate not available, use the original */ } else { + new_rate = rate; break; } } @@ -1143,10 +1126,10 @@ static s32 rs_get_best_rate(struct iwl_priv *priv, * Set up search table for MIMO */ static int rs_switch_to_mimo2(struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_sta, + struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, - struct sta_info *sta, - struct iwl4965_scale_tbl_info *tbl, int index) + struct ieee80211_sta *sta, + struct iwl_scale_tbl_info *tbl, int index) { u16 rate_mask; s32 rate; @@ -1156,7 +1139,8 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, !sta->ht_info.ht_supported) return -1; - if (priv->current_ht_config.tx_mimo_ps_mode == IWL_MIMO_PS_STATIC) + if (((sta->ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2) + == WLAN_HT_CAP_SM_PS_STATIC) return -1; /* Need both Tx chains/antennas to support MIMO */ @@ -1210,10 +1194,10 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, * Set up search table for SISO */ static int rs_switch_to_siso(struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_sta, + struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, - struct sta_info *sta, - struct iwl4965_scale_tbl_info *tbl, int index) + struct ieee80211_sta *sta, + struct iwl_scale_tbl_info *tbl, int index) { u16 rate_mask; u8 is_green = lq_sta->is_green; @@ -1270,29 +1254,36 @@ static int rs_switch_to_siso(struct iwl_priv *priv, * Try to switch to new modulation mode from legacy */ static int rs_move_legacy_other(struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_sta, + struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, - struct sta_info *sta, + struct ieee80211_sta *sta, int index) { - struct iwl4965_scale_tbl_info *tbl = - &(lq_sta->lq_info[lq_sta->active_tbl]); - struct iwl4965_scale_tbl_info *search_tbl = - &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); - struct iwl4965_rate_scale_data *window = &(tbl->win[index]); - u32 sz = (sizeof(struct iwl4965_scale_tbl_info) - - (sizeof(struct iwl4965_rate_scale_data) * IWL_RATE_COUNT)); + struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); + struct iwl_scale_tbl_info *search_tbl = + &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); + struct iwl_rate_scale_data *window = &(tbl->win[index]); + u32 sz = (sizeof(struct iwl_scale_tbl_info) - + (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action = tbl->action; u8 valid_tx_ant = priv->hw_params.valid_tx_ant; + u8 tx_chains_num = priv->hw_params.tx_chains_num; int ret = 0; for (; ;) { switch (tbl->action) { - case IWL_LEGACY_SWITCH_ANTENNA: + case IWL_LEGACY_SWITCH_ANTENNA1: + case IWL_LEGACY_SWITCH_ANTENNA2: IWL_DEBUG_RATE("LQ: Legacy toggle Antenna\n"); lq_sta->action_counter++; + if ((tbl->action == IWL_LEGACY_SWITCH_ANTENNA1 && + tx_chains_num <= 1) || + (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2 && + tx_chains_num <= 2)) + break; + /* Don't change antenna if success has been great */ if (window->success_ratio >= IWL_RS_GOOD_RATIO) break; @@ -1302,7 +1293,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, if (rs_toggle_antenna(valid_tx_ant, &search_tbl->current_rate, search_tbl)) { - lq_sta->search_better_tbl = 1; + rs_set_expected_tpt_table(lq_sta, search_tbl); goto out; } break; @@ -1315,43 +1306,54 @@ static int rs_move_legacy_other(struct iwl_priv *priv, ret = rs_switch_to_siso(priv, lq_sta, conf, sta, search_tbl, index); if (!ret) { - lq_sta->search_better_tbl = 1; lq_sta->action_counter = 0; goto out; } break; - case IWL_LEGACY_SWITCH_MIMO2: + case IWL_LEGACY_SWITCH_MIMO2_AB: + case IWL_LEGACY_SWITCH_MIMO2_AC: + case IWL_LEGACY_SWITCH_MIMO2_BC: IWL_DEBUG_RATE("LQ: Legacy switch to MIMO2\n"); /* Set up search table to try MIMO */ memcpy(search_tbl, tbl, sz); search_tbl->is_SGI = 0; - search_tbl->ant_type = ANT_AB;/*FIXME:RS*/ - /*FIXME:RS:need to check ant validity*/ + + if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AB) + search_tbl->ant_type = ANT_AB; + else if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AC) + search_tbl->ant_type = ANT_AC; + else + search_tbl->ant_type = ANT_BC; + + if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) + break; + ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta, search_tbl, index); if (!ret) { - lq_sta->search_better_tbl = 1; lq_sta->action_counter = 0; goto out; } break; } tbl->action++; - if (tbl->action > IWL_LEGACY_SWITCH_MIMO2) - tbl->action = IWL_LEGACY_SWITCH_ANTENNA; + if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC) + tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; if (tbl->action == start_action) break; } + search_tbl->lq_type = LQ_NONE; return 0; - out: +out: + lq_sta->search_better_tbl = 1; tbl->action++; - if (tbl->action > IWL_LEGACY_SWITCH_MIMO2) - tbl->action = IWL_LEGACY_SWITCH_ANTENNA; + if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC) + tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; return 0; } @@ -1360,49 +1362,64 @@ static int rs_move_legacy_other(struct iwl_priv *priv, * Try to switch to new modulation mode from SISO */ static int rs_move_siso_to_other(struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_sta, + struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, - struct sta_info *sta, - int index) + struct ieee80211_sta *sta, int index) { u8 is_green = lq_sta->is_green; - struct iwl4965_scale_tbl_info *tbl = - &(lq_sta->lq_info[lq_sta->active_tbl]); - struct iwl4965_scale_tbl_info *search_tbl = - &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); - struct iwl4965_rate_scale_data *window = &(tbl->win[index]); - u32 sz = (sizeof(struct iwl4965_scale_tbl_info) - - (sizeof(struct iwl4965_rate_scale_data) * IWL_RATE_COUNT)); + struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); + struct iwl_scale_tbl_info *search_tbl = + &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); + struct iwl_rate_scale_data *window = &(tbl->win[index]); + u32 sz = (sizeof(struct iwl_scale_tbl_info) - + (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action = tbl->action; u8 valid_tx_ant = priv->hw_params.valid_tx_ant; + u8 tx_chains_num = priv->hw_params.tx_chains_num; int ret; for (;;) { lq_sta->action_counter++; switch (tbl->action) { - case IWL_SISO_SWITCH_ANTENNA: + case IWL_SISO_SWITCH_ANTENNA1: + case IWL_SISO_SWITCH_ANTENNA2: IWL_DEBUG_RATE("LQ: SISO toggle Antenna\n"); + + if ((tbl->action == IWL_SISO_SWITCH_ANTENNA1 && + tx_chains_num <= 1) || + (tbl->action == IWL_SISO_SWITCH_ANTENNA2 && + tx_chains_num <= 2)) + break; + if (window->success_ratio >= IWL_RS_GOOD_RATIO) break; memcpy(search_tbl, tbl, sz); if (rs_toggle_antenna(valid_tx_ant, - &search_tbl->current_rate, search_tbl)) { - lq_sta->search_better_tbl = 1; + &search_tbl->current_rate, search_tbl)) goto out; - } break; - case IWL_SISO_SWITCH_MIMO2: + case IWL_SISO_SWITCH_MIMO2_AB: + case IWL_SISO_SWITCH_MIMO2_AC: + case IWL_SISO_SWITCH_MIMO2_BC: IWL_DEBUG_RATE("LQ: SISO switch to MIMO2\n"); memcpy(search_tbl, tbl, sz); search_tbl->is_SGI = 0; - search_tbl->ant_type = ANT_AB; /*FIXME:RS*/ + + if (tbl->action == IWL_SISO_SWITCH_MIMO2_AB) + search_tbl->ant_type = ANT_AB; + else if (tbl->action == IWL_SISO_SWITCH_MIMO2_AC) + search_tbl->ant_type = ANT_AC; + else + search_tbl->ant_type = ANT_BC; + + if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) + break; + ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta, search_tbl, index); - if (!ret) { - lq_sta->search_better_tbl = 1; + if (!ret) goto out; - } break; case IWL_SISO_SWITCH_GI: if (!tbl->is_fat && @@ -1432,22 +1449,23 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, } search_tbl->current_rate = rate_n_flags_from_tbl( search_tbl, index, is_green); - lq_sta->search_better_tbl = 1; goto out; } tbl->action++; if (tbl->action > IWL_SISO_SWITCH_GI) - tbl->action = IWL_SISO_SWITCH_ANTENNA; + tbl->action = IWL_SISO_SWITCH_ANTENNA1; if (tbl->action == start_action) break; } + search_tbl->lq_type = LQ_NONE; return 0; out: + lq_sta->search_better_tbl = 1; tbl->action++; if (tbl->action > IWL_SISO_SWITCH_GI) - tbl->action = IWL_SISO_SWITCH_ANTENNA; + tbl->action = IWL_SISO_SWITCH_ANTENNA1; return 0; } @@ -1455,47 +1473,66 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, * Try to switch to new modulation mode from MIMO */ static int rs_move_mimo_to_other(struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_sta, + struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, - struct sta_info *sta, - int index) + struct ieee80211_sta *sta, int index) { s8 is_green = lq_sta->is_green; - struct iwl4965_scale_tbl_info *tbl = - &(lq_sta->lq_info[lq_sta->active_tbl]); - struct iwl4965_scale_tbl_info *search_tbl = - &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); - u32 sz = (sizeof(struct iwl4965_scale_tbl_info) - - (sizeof(struct iwl4965_rate_scale_data) * IWL_RATE_COUNT)); + struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); + struct iwl_scale_tbl_info *search_tbl = + &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); + struct iwl_rate_scale_data *window = &(tbl->win[index]); + u32 sz = (sizeof(struct iwl_scale_tbl_info) - + (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action = tbl->action; - /*u8 valid_tx_ant = priv->hw_params.valid_tx_ant;*/ + u8 valid_tx_ant = priv->hw_params.valid_tx_ant; + u8 tx_chains_num = priv->hw_params.tx_chains_num; int ret; for (;;) { lq_sta->action_counter++; switch (tbl->action) { - case IWL_MIMO_SWITCH_ANTENNA_A: - case IWL_MIMO_SWITCH_ANTENNA_B: + case IWL_MIMO2_SWITCH_ANTENNA1: + case IWL_MIMO2_SWITCH_ANTENNA2: + IWL_DEBUG_RATE("LQ: MIMO toggle Antennas\n"); + + if (tx_chains_num <= 2) + break; + + if (window->success_ratio >= IWL_RS_GOOD_RATIO) + break; + + memcpy(search_tbl, tbl, sz); + if (rs_toggle_antenna(valid_tx_ant, + &search_tbl->current_rate, search_tbl)) + goto out; + break; + case IWL_MIMO2_SWITCH_SISO_A: + case IWL_MIMO2_SWITCH_SISO_B: + case IWL_MIMO2_SWITCH_SISO_C: IWL_DEBUG_RATE("LQ: MIMO2 switch to SISO\n"); /* Set up new search table for SISO */ memcpy(search_tbl, tbl, sz); - /*FIXME:RS:need to check ant validity + C*/ - if (tbl->action == IWL_MIMO_SWITCH_ANTENNA_A) + if (tbl->action == IWL_MIMO2_SWITCH_SISO_A) search_tbl->ant_type = ANT_A; - else + else if (tbl->action == IWL_MIMO2_SWITCH_SISO_B) search_tbl->ant_type = ANT_B; + else + search_tbl->ant_type = ANT_C; + + if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) + break; ret = rs_switch_to_siso(priv, lq_sta, conf, sta, search_tbl, index); - if (!ret) { - lq_sta->search_better_tbl = 1; + if (!ret) goto out; - } + break; - case IWL_MIMO_SWITCH_GI: + case IWL_MIMO2_SWITCH_GI: if (!tbl->is_fat && !(priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ)) @@ -1524,23 +1561,23 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, } search_tbl->current_rate = rate_n_flags_from_tbl( search_tbl, index, is_green); - lq_sta->search_better_tbl = 1; goto out; } tbl->action++; - if (tbl->action > IWL_MIMO_SWITCH_GI) - tbl->action = IWL_MIMO_SWITCH_ANTENNA_A; + if (tbl->action > IWL_MIMO2_SWITCH_GI) + tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; if (tbl->action == start_action) break; } - + search_tbl->lq_type = LQ_NONE; return 0; out: + lq_sta->search_better_tbl = 1; tbl->action++; - if (tbl->action > IWL_MIMO_SWITCH_GI) - tbl->action = IWL_MIMO_SWITCH_ANTENNA_A; + if (tbl->action > IWL_MIMO2_SWITCH_GI) + tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; return 0; } @@ -1552,9 +1589,9 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, * 2) # times calling this function * 3) elapsed time in this mode (not used, for now) */ -static void rs_stay_in_table(struct iwl4965_lq_sta *lq_sta) +static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) { - struct iwl4965_scale_tbl_info *tbl; + struct iwl_scale_tbl_info *tbl; int i; int active_tbl; int flush_interval_passed = 0; @@ -1631,18 +1668,17 @@ static void rs_stay_in_table(struct iwl4965_lq_sta *lq_sta) * Do rate scaling and search for new modulation mode. */ static void rs_rate_scale_perform(struct iwl_priv *priv, - struct net_device *dev, struct ieee80211_hdr *hdr, - struct sta_info *sta) + struct ieee80211_sta *sta, + struct iwl_lq_sta *lq_sta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_hw *hw = local_to_hw(local); + struct ieee80211_hw *hw = priv->hw; struct ieee80211_conf *conf = &hw->conf; int low = IWL_RATE_INVALID; int high = IWL_RATE_INVALID; int index; int i; - struct iwl4965_rate_scale_data *window = NULL; + struct iwl_rate_scale_data *window = NULL; int current_tpt = IWL_INVALID_VALUE; int low_tpt = IWL_INVALID_VALUE; int high_tpt = IWL_INVALID_VALUE; @@ -1651,8 +1687,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, __le16 fc; u16 rate_mask; u8 update_lq = 0; - struct iwl4965_lq_sta *lq_sta; - struct iwl4965_scale_tbl_info *tbl, *tbl1; + struct iwl_scale_tbl_info *tbl, *tbl1; u16 rate_scale_index_msk = 0; u32 rate; u8 is_green = 0; @@ -1672,10 +1707,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, return; } - if (!sta || !sta->rate_ctrl_priv) + if (!sta || !lq_sta) return; - lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; + lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; tid = rs_tl_add_packet(lq_sta, hdr); @@ -1693,7 +1728,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, is_green = lq_sta->is_green; /* current tx rate */ - index = sta->last_txrate_idx; + index = lq_sta->last_txrate_idx; IWL_DEBUG_RATE("Rate scale index %d for type %d\n", index, tbl->lq_type); @@ -1754,19 +1789,13 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, rs_stay_in_table(lq_sta); goto out; + } /* Else we have enough samples; calculate estimate of * actual average throughput */ - } else { - /*FIXME:RS remove this else if we don't get this error*/ - if (window->average_tpt != ((window->success_ratio * - tbl->expected_tpt[index] + 64) / 128)) { - IWL_ERROR("expected_tpt should have been calculated" - " by now\n"); - window->average_tpt = ((window->success_ratio * - tbl->expected_tpt[index] + 64) / 128); - } - } + + BUG_ON(window->average_tpt != ((window->success_ratio * + tbl->expected_tpt[index] + 64) / 128)); /* If we are searching for better modulation mode, check success. */ if (lq_sta->search_better_tbl) { @@ -1776,7 +1805,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, * continuing to use the setup that we've been trying. */ if (window->average_tpt > lq_sta->last_tpt) { - IWL_DEBUG_RATE("LQ: SWITCHING TO CURRENT TABLE " + IWL_DEBUG_RATE("LQ: SWITCHING TO NEW TABLE " "suc=%d cur-tpt=%d old-tpt=%d\n", window->success_ratio, window->average_tpt, @@ -2012,15 +2041,7 @@ lq_update: out: tbl->current_rate = rate_n_flags_from_tbl(tbl, index, is_green); i = index; - sta->last_txrate_idx = i; - - /* sta->txrate_idx is an index to A mode rates which start - * at IWL_FIRST_OFDM_RATE - */ - if (lq_sta->band == IEEE80211_BAND_5GHZ) - sta->txrate_idx = i - IWL_FIRST_OFDM_RATE; - else - sta->txrate_idx = i; + lq_sta->last_txrate_idx = i; return; } @@ -2028,10 +2049,10 @@ out: static void rs_initialize_lq(struct iwl_priv *priv, struct ieee80211_conf *conf, - struct sta_info *sta) + struct ieee80211_sta *sta, + struct iwl_lq_sta *lq_sta) { - struct iwl4965_lq_sta *lq_sta; - struct iwl4965_scale_tbl_info *tbl; + struct iwl_scale_tbl_info *tbl; int rate_idx; int i; u32 rate; @@ -2039,14 +2060,13 @@ static void rs_initialize_lq(struct iwl_priv *priv, u8 active_tbl = 0; u8 valid_tx_ant; - if (!sta || !sta->rate_ctrl_priv) + if (!sta || !lq_sta) goto out; - lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; - i = sta->last_txrate_idx; + i = lq_sta->last_txrate_idx; if ((lq_sta->lq.sta_id == 0xff) && - (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)) + (priv->iw_mode == NL80211_IFTYPE_ADHOC)) goto out; valid_tx_ant = priv->hw_params.valid_tx_ant; @@ -2083,40 +2103,33 @@ static void rs_initialize_lq(struct iwl_priv *priv, return; } -static void rs_get_rate(void *priv_rate, struct net_device *dev, - struct ieee80211_supported_band *sband, - struct sk_buff *skb, - struct rate_selection *sel) +static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb, struct rate_selection *sel) { int i; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_conf *conf = &local->hw.conf; + struct iwl_priv *priv = (struct iwl_priv *)priv_r; + struct ieee80211_conf *conf = &priv->hw->conf; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct sta_info *sta; __le16 fc; - struct iwl_priv *priv = (struct iwl_priv *)priv_rate; - struct iwl4965_lq_sta *lq_sta; + struct iwl_lq_sta *lq_sta; IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); - /* Send management frames and broadcast/multicast data using lowest * rate. */ fc = hdr->frame_control; if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || - !sta || !sta->rate_ctrl_priv) { - sel->rate_idx = rate_lowest_index(local, sband, sta); - goto out; + !sta || !priv_sta) { + sel->rate_idx = rate_lowest_index(sband, sta); + return; } - lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; - i = sta->last_txrate_idx; + lq_sta = (struct iwl_lq_sta *)priv_sta; + i = lq_sta->last_txrate_idx; - if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && + if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && !lq_sta->ibss_sta_added) { u8 sta_id = iwl_find_station(priv, hdr->addr1); DECLARE_MAC_BUF(mac); @@ -2131,32 +2144,31 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, lq_sta->lq.sta_id = sta_id; lq_sta->lq.rs_table[0].rate_n_flags = 0; lq_sta->ibss_sta_added = 1; - rs_initialize_lq(priv, conf, sta); + rs_initialize_lq(priv, conf, sta, lq_sta); } } if ((i < 0) || (i > IWL_RATE_COUNT)) { - sel->rate_idx = rate_lowest_index(local, sband, sta); - goto out; + sel->rate_idx = rate_lowest_index(sband, sta); + return; } if (sband->band == IEEE80211_BAND_5GHZ) i -= IWL_FIRST_OFDM_RATE; sel->rate_idx = i; -out: - rcu_read_unlock(); } -static void *rs_alloc_sta(void *priv_rate, gfp_t gfp) +static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, + gfp_t gfp) { - struct iwl4965_lq_sta *lq_sta; + struct iwl_lq_sta *lq_sta; struct iwl_priv *priv; int i, j; priv = (struct iwl_priv *)priv_rate; IWL_DEBUG_RATE("create station rate scale window\n"); - lq_sta = kzalloc(sizeof(struct iwl4965_lq_sta), gfp); + lq_sta = kzalloc(sizeof(struct iwl_lq_sta), gfp); if (lq_sta == NULL) return NULL; @@ -2165,38 +2177,33 @@ static void *rs_alloc_sta(void *priv_rate, gfp_t gfp) for (j = 0; j < LQ_SIZE; j++) for (i = 0; i < IWL_RATE_COUNT; i++) - rs_rate_scale_clear_window(&(lq_sta->lq_info[j].win[i])); + rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); return lq_sta; } -static void rs_rate_init(void *priv_rate, void *priv_sta, - struct ieee80211_local *local, - struct sta_info *sta) +static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta) { int i, j; - struct ieee80211_conf *conf = &local->hw.conf; - struct ieee80211_supported_band *sband; - struct iwl_priv *priv = (struct iwl_priv *)priv_rate; - struct iwl4965_lq_sta *lq_sta = priv_sta; - - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + struct iwl_priv *priv = (struct iwl_priv *)priv_r; + struct ieee80211_conf *conf = &priv->hw->conf; + struct iwl_lq_sta *lq_sta = priv_sta; lq_sta->flush_timer = 0; lq_sta->supp_rates = sta->supp_rates[sband->band]; - sta->txrate_idx = 3; for (j = 0; j < LQ_SIZE; j++) for (i = 0; i < IWL_RATE_COUNT; i++) - rs_rate_scale_clear_window(&(lq_sta->lq_info[j].win[i])); + rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); - IWL_DEBUG_RATE("LQ: *** rate scale global init ***\n"); + IWL_DEBUG_RATE("LQ: *** rate scale station global init ***\n"); /* TODO: what is a good starting rate for STA? About middle? Maybe not * the lowest or the highest rate.. Could consider using RSSI from * previous packets? Need to have IEEE 802.1X auth succeed immediately * after assoc.. */ lq_sta->ibss_sta_added = 0; - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode == NL80211_IFTYPE_AP) { u8 sta_id = iwl_find_station(priv, sta->addr); DECLARE_MAC_BUF(mac); @@ -2219,15 +2226,14 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, } /* Find highest tx rate supported by hardware and destination station */ + lq_sta->last_txrate_idx = 3; for (i = 0; i < sband->n_bitrates; i++) if (sta->supp_rates[sband->band] & BIT(i)) - sta->txrate_idx = i; + lq_sta->last_txrate_idx = i; - sta->last_txrate_idx = sta->txrate_idx; - /* WTF is with this bogus comment? A doesn't have cck rates */ - /* For MODE_IEEE80211A, cck rates are at end of rate table */ - if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) - sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; + /* For MODE_IEEE80211A, skip over cck rates in global rate table */ + if (sband->band == IEEE80211_BAND_5GHZ) + lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; lq_sta->is_dup = 0; lq_sta->is_green = rs_use_green(priv, conf); @@ -2267,14 +2273,13 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; lq_sta->drv = priv; - rs_initialize_lq(priv, conf, sta); + rs_initialize_lq(priv, conf, sta, lq_sta); } static void rs_fill_link_cmd(const struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_sta, - u32 new_rate) + struct iwl_lq_sta *lq_sta, u32 new_rate) { - struct iwl4965_scale_tbl_info tbl_type; + struct iwl_scale_tbl_info tbl_type; int index = 0; int rate_idx; int repeat_rate = 0; @@ -2390,9 +2395,9 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv, lq_cmd->agg_params.agg_time_limit = cpu_to_le16(4000); } -static void *rs_alloc(struct ieee80211_local *local) +static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) { - return local->hw.priv; + return hw->priv; } /* rate scale requires free function to be implemented */ static void rs_free(void *priv_rate) @@ -2402,6 +2407,7 @@ static void rs_free(void *priv_rate) static void rs_clear(void *priv_rate) { +#ifdef CONFIG_IWLWIFI_DEBUG struct iwl_priv *priv = (struct iwl_priv *) priv_rate; IWL_DEBUG_RATE("enter\n"); @@ -2409,14 +2415,15 @@ static void rs_clear(void *priv_rate) /* TODO - add rate scale state reset */ IWL_DEBUG_RATE("leave\n"); +#endif /* CONFIG_IWLWIFI_DEBUG */ } -static void rs_free_sta(void *priv_rate, void *priv_sta) +static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, + void *priv_sta) { - struct iwl4965_lq_sta *lq_sta = priv_sta; - struct iwl_priv *priv; + struct iwl_lq_sta *lq_sta = priv_sta; + struct iwl_priv *priv = priv_r; - priv = (struct iwl_priv *)priv_rate; IWL_DEBUG_RATE("enter\n"); kfree(lq_sta); IWL_DEBUG_RATE("leave\n"); @@ -2429,8 +2436,8 @@ static int open_file_generic(struct inode *inode, struct file *file) file->private_data = inode->i_private; return 0; } -static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta, - u32 *rate_n_flags, int index) +static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, + u32 *rate_n_flags, int index) { struct iwl_priv *priv; @@ -2453,7 +2460,7 @@ static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta, static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl4965_lq_sta *lq_sta = file->private_data; + struct iwl_lq_sta *lq_sta = file->private_data; struct iwl_priv *priv; char buf[64]; int buf_size; @@ -2493,7 +2500,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, int desc = 0; int i = 0; - struct iwl4965_lq_sta *lq_sta = file->private_data; + struct iwl_lq_sta *lq_sta = file->private_data; desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id); desc += sprintf(buff+desc, "failed=%d success=%d rate=0%X\n", @@ -2541,7 +2548,7 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file, int desc = 0; int i, j; - struct iwl4965_lq_sta *lq_sta = file->private_data; + struct iwl_lq_sta *lq_sta = file->private_data; for (i = 0; i < LQ_SIZE; i++) { desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%d DUP=%d\n" "rate=0x%X\n", @@ -2570,7 +2577,7 @@ static const struct file_operations rs_sta_dbgfs_stats_table_ops = { static void rs_add_debugfs(void *priv, void *priv_sta, struct dentry *dir) { - struct iwl4965_lq_sta *lq_sta = priv_sta; + struct iwl_lq_sta *lq_sta = priv_sta; lq_sta->rs_sta_dbgfs_scale_table_file = debugfs_create_file("rate_scale_table", 0600, dir, lq_sta, &rs_sta_dbgfs_scale_table_ops); @@ -2585,7 +2592,7 @@ static void rs_add_debugfs(void *priv, void *priv_sta, static void rs_remove_debugfs(void *priv, void *priv_sta) { - struct iwl4965_lq_sta *lq_sta = priv_sta; + struct iwl_lq_sta *lq_sta = priv_sta; debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file); debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file); @@ -2609,104 +2616,12 @@ static struct rate_control_ops rs_ops = { #endif }; -int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) -{ - struct ieee80211_local *local = hw_to_local(hw); - struct iwl_priv *priv = hw->priv; - struct iwl4965_lq_sta *lq_sta; - struct sta_info *sta; - int cnt = 0, i; - u32 samples = 0, success = 0, good = 0; - unsigned long now = jiffies; - u32 max_time = 0; - u8 lq_type, antenna; - - rcu_read_lock(); - - sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); - if (!sta || !sta->rate_ctrl_priv) { - if (sta) - IWL_DEBUG_RATE("leave - no private rate data!\n"); - else - IWL_DEBUG_RATE("leave - no station!\n"); - rcu_read_unlock(); - return sprintf(buf, "station %d not found\n", sta_id); - } - - lq_sta = (void *)sta->rate_ctrl_priv; - - lq_type = lq_sta->lq_info[lq_sta->active_tbl].lq_type; - antenna = lq_sta->lq_info[lq_sta->active_tbl].ant_type; - - if (is_legacy(lq_type)) - i = IWL_RATE_54M_INDEX; - else - i = IWL_RATE_60M_INDEX; - while (1) { - u64 mask; - int j; - int active = lq_sta->active_tbl; - - cnt += - sprintf(&buf[cnt], " %2dMbs: ", iwl_rates[i].ieee / 2); - - mask = (1ULL << (IWL_RATE_MAX_WINDOW - 1)); - for (j = 0; j < IWL_RATE_MAX_WINDOW; j++, mask >>= 1) - buf[cnt++] = - (lq_sta->lq_info[active].win[i].data & mask) - ? '1' : '0'; - - samples += lq_sta->lq_info[active].win[i].counter; - good += lq_sta->lq_info[active].win[i].success_counter; - success += lq_sta->lq_info[active].win[i].success_counter * - iwl_rates[i].ieee; - - if (lq_sta->lq_info[active].win[i].stamp) { - int delta = - jiffies_to_msecs(now - - lq_sta->lq_info[active].win[i].stamp); - - if (delta > max_time) - max_time = delta; - - cnt += sprintf(&buf[cnt], "%5dms\n", delta); - } else - buf[cnt++] = '\n'; - - j = iwl4965_get_prev_ieee_rate(i); - if (j == i) - break; - i = j; - } - - /* - * Display the average rate of all samples taken. - * NOTE: We multiply # of samples by 2 since the IEEE measurement - * added from iwl_rates is actually 2X the rate. - */ - if (samples) - cnt += sprintf(&buf[cnt], - "\nAverage rate is %3d.%02dMbs over last %4dms\n" - "%3d%% success (%d good packets over %d tries)\n", - success / (2 * samples), (success * 5 / samples) % 10, - max_time, good * 100 / samples, good, samples); - else - cnt += sprintf(&buf[cnt], "\nAverage rate: 0Mbs\n"); - - cnt += sprintf(&buf[cnt], "\nrate scale type %d antenna %d " - "active_search %d rate index %d\n", lq_type, antenna, - lq_sta->search_better_tbl, sta->last_txrate_idx); - - rcu_read_unlock(); - return cnt; -} - -int iwl4965_rate_control_register(void) +int iwlagn_rate_control_register(void) { return ieee80211_rate_control_register(&rs_ops); } -void iwl4965_rate_control_unregister(void) +void iwlagn_rate_control_unregister(void) { ieee80211_rate_control_unregister(&rs_ops); } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 9b9972885aa5..d148d73635eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -24,8 +24,8 @@ * *****************************************************************************/ -#ifndef __iwl_4965_rs_h__ -#define __iwl_4965_rs_h__ +#ifndef __iwl_agn_rs_h__ +#define __iwl_agn_rs_h__ #include "iwl-dev.h" @@ -88,7 +88,7 @@ enum { #define IWL_RATE_5M_MASK (1 << IWL_RATE_5M_INDEX) #define IWL_RATE_11M_MASK (1 << IWL_RATE_11M_INDEX) -/* 4965 uCode API values for legacy bit rates, both OFDM and CCK */ +/* uCode API values for legacy bit rates, both OFDM and CCK */ enum { IWL_RATE_6M_PLCP = 13, IWL_RATE_9M_PLCP = 15, @@ -107,7 +107,7 @@ enum { /*FIXME:RS:add IWL_RATE_LEGACY_INVM_PLCP = 0,*/ }; -/* 4965 uCode API values for OFDM high-throughput (HT) bit rates */ +/* uCode API values for OFDM high-throughput (HT) bit rates */ enum { IWL_RATE_SISO_6M_PLCP = 0, IWL_RATE_SISO_12M_PLCP = 1, @@ -206,21 +206,28 @@ enum { #define IWL_RATE_DECREASE_TH 1920 /* 15% */ /* possible actions when in legacy mode */ -#define IWL_LEGACY_SWITCH_ANTENNA 0 -#define IWL_LEGACY_SWITCH_SISO 1 -#define IWL_LEGACY_SWITCH_MIMO2 2 +#define IWL_LEGACY_SWITCH_ANTENNA1 0 +#define IWL_LEGACY_SWITCH_ANTENNA2 1 +#define IWL_LEGACY_SWITCH_SISO 2 +#define IWL_LEGACY_SWITCH_MIMO2_AB 3 +#define IWL_LEGACY_SWITCH_MIMO2_AC 4 +#define IWL_LEGACY_SWITCH_MIMO2_BC 5 /* possible actions when in siso mode */ -#define IWL_SISO_SWITCH_ANTENNA 0 -#define IWL_SISO_SWITCH_MIMO2 1 -#define IWL_SISO_SWITCH_GI 2 +#define IWL_SISO_SWITCH_ANTENNA1 0 +#define IWL_SISO_SWITCH_ANTENNA2 1 +#define IWL_SISO_SWITCH_MIMO2_AB 2 +#define IWL_SISO_SWITCH_MIMO2_AC 3 +#define IWL_SISO_SWITCH_MIMO2_BC 4 +#define IWL_SISO_SWITCH_GI 5 /* possible actions when in mimo mode */ -#define IWL_MIMO_SWITCH_ANTENNA_A 0 -#define IWL_MIMO_SWITCH_ANTENNA_B 1 -#define IWL_MIMO_SWITCH_GI 2 - -/*FIXME:RS:separate MIMO2/3 transitions*/ +#define IWL_MIMO2_SWITCH_ANTENNA1 0 +#define IWL_MIMO2_SWITCH_ANTENNA2 1 +#define IWL_MIMO2_SWITCH_SISO_A 2 +#define IWL_MIMO2_SWITCH_SISO_B 3 +#define IWL_MIMO2_SWITCH_SISO_C 4 +#define IWL_MIMO2_SWITCH_GI 5 /*FIXME:RS:add posible acctions for MIMO3*/ @@ -287,15 +294,6 @@ static inline u8 iwl4965_get_prev_ieee_rate(u8 rate_index) } /** - * iwl4965_fill_rs_info - Fill an output text buffer with the rate representation - * - * NOTE: This is provided as a quick mechanism for a user to visualize - * the performance of the rate control algorithm and is not meant to be - * parsed software. - */ -extern int iwl4965_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id); - -/** * iwl4965_rate_control_register - Register the rate control algorithm callbacks * * Since the rate control algorithm is hardware specific, there is no need @@ -305,7 +303,7 @@ extern int iwl4965_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id); * ieee80211_register_hw * */ -extern int iwl4965_rate_control_register(void); +extern int iwlagn_rate_control_register(void); /** * iwl4965_rate_control_unregister - Unregister the rate control callbacks @@ -313,6 +311,6 @@ extern int iwl4965_rate_control_register(void); * This should be called after calling ieee80211_unregister_hw, but before * the driver is unloaded. */ -extern void iwl4965_rate_control_unregister(void); +extern void iwlagn_rate_control_unregister(void); -#endif +#endif /* __iwl_agn__rs__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 71f5da3fe5c4..24a1aeb6448f 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -29,7 +29,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/dma-mapping.h> @@ -65,7 +64,7 @@ * NOTE: DRV_NAME is defined in iwlwifi.h for use by iwl-debug.h and printk */ -#define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link 4965AGN driver for Linux" +#define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link AGN driver for Linux" #ifdef CONFIG_IWLWIFI_DEBUG #define VD "d" @@ -73,7 +72,7 @@ #define VD #endif -#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT +#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT #define VS "s" #else #define VS @@ -86,6 +85,7 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_VERSION(DRV_VERSION); MODULE_AUTHOR(DRV_COPYRIGHT); MODULE_LICENSE("GPL"); +MODULE_ALIAS("iwl4965"); /*************** STATION TABLE MANAGEMENT **** * mac80211 should be examined to determine if sta_info is duplicating @@ -181,14 +181,14 @@ static int iwl4965_check_rxon_cmd(struct iwl_rxon_cmd *rxon) } /** - * iwl4965_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed + * iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed * @priv: staging_rxon is compared to active_rxon * * If the RXON structure is changing enough to require a new tune, * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. */ -static int iwl4965_full_rxon_required(struct iwl_priv *priv) +static int iwl_full_rxon_required(struct iwl_priv *priv) { /* These items are only settable from the full RXON command */ @@ -207,7 +207,6 @@ static int iwl4965_full_rxon_required(struct iwl_priv *priv) priv->active_rxon.ofdm_ht_single_stream_basic_rates) || (priv->staging_rxon.ofdm_ht_dual_stream_basic_rates != priv->active_rxon.ofdm_ht_dual_stream_basic_rates) || - (priv->staging_rxon.rx_chain != priv->active_rxon.rx_chain) || (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id)) return 1; @@ -263,7 +262,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) /* If we don't need to send a full RXON, we can use * iwl4965_rxon_assoc_cmd which is used to reconfigure filter * and other flags for the current radio configuration. */ - if (!iwl4965_full_rxon_required(priv)) { + if (!iwl_full_rxon_required(priv)) { ret = iwl_send_rxon_assoc(priv); if (ret) { IWL_ERROR("Error setting RXON_ASSOC (%d)\n", ret); @@ -338,7 +337,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) /* If we have set the ASSOC_MSK and we are in BSS mode then * add the IWL_AP_ID to the station rate table */ if (new_assoc) { - if (priv->iw_mode == IEEE80211_IF_TYPE_STA) { + if (priv->iw_mode == NL80211_IFTYPE_STATION) { ret = iwl_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1); if (ret == IWL_INVALID_STATION) { @@ -444,14 +443,13 @@ static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame) list_add(&frame->list, &priv->free_frames); } -unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv, - struct ieee80211_hdr *hdr, - const u8 *dest, int left) +static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv, + struct ieee80211_hdr *hdr, + const u8 *dest, int left) { - if (!iwl_is_associated(priv) || !priv->ibss_beacon || - ((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) && - (priv->iw_mode != IEEE80211_IF_TYPE_AP))) + ((priv->iw_mode != NL80211_IFTYPE_ADHOC) && + (priv->iw_mode != NL80211_IFTYPE_AP))) return 0; if (priv->ibss_beacon->len > left) @@ -487,6 +485,38 @@ static u8 iwl4965_rate_get_lowest_plcp(struct iwl_priv *priv) return IWL_RATE_6M_PLCP; } +static unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, + struct iwl_frame *frame, u8 rate) +{ + struct iwl_tx_beacon_cmd *tx_beacon_cmd; + unsigned int frame_size; + + tx_beacon_cmd = &frame->u.beacon; + memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); + + tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; + tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; + + frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame, + iwl_bcast_addr, + sizeof(frame->u) - sizeof(*tx_beacon_cmd)); + + BUG_ON(frame_size > MAX_MPDU_SIZE); + tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); + + if ((rate == IWL_RATE_1M_PLCP) || (rate >= IWL_RATE_2M_PLCP)) + tx_beacon_cmd->tx.rate_n_flags = + iwl_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK); + else + tx_beacon_cmd->tx.rate_n_flags = + iwl_hw_set_rate_n_flags(rate, 0); + + tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK | + TX_CMD_FLG_TSF_MSK | + TX_CMD_FLG_STA_RATE_MSK; + + return sizeof(*tx_beacon_cmd) + frame_size; +} static int iwl4965_send_beacon_cmd(struct iwl_priv *priv) { struct iwl_frame *frame; @@ -534,8 +564,6 @@ static void iwl4965_ht_conf(struct iwl_priv *priv, if (!iwl_conf->is_ht) return; - priv->ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2); - if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20) iwl_conf->sgf |= HT_SHORT_GI_20MHZ; if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40) @@ -556,8 +584,8 @@ static void iwl4965_ht_conf(struct iwl_priv *priv, iwl_conf->supported_chan_width = 0; } - iwl_conf->tx_mimo_ps_mode = - (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2); + iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); + memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16); iwl_conf->control_channel = ht_bss_conf->primary_channel; @@ -608,7 +636,6 @@ static void iwl_activate_qos(struct iwl_priv *priv, u8 force) } #define MAX_UCODE_BEACON_INTERVAL 4096 -#define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA) static __le16 iwl4965_adjust_beacon_interval(u16 beacon_val) { @@ -638,14 +665,14 @@ static void iwl4965_setup_rxon_timing(struct iwl_priv *priv) priv->rxon_timing.timestamp.dw[0] = cpu_to_le32(priv->timestamp & 0xFFFFFFFF); - priv->rxon_timing.listen_interval = INTEL_CONN_LISTEN_INTERVAL; + priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval); tsf = priv->timestamp; beacon_int = priv->beacon_int; spin_unlock_irqrestore(&priv->lock, flags); - if (priv->iw_mode == IEEE80211_IF_TYPE_STA) { + if (priv->iw_mode == NL80211_IFTYPE_STATION) { if (beacon_int == 0) { priv->rxon_timing.beacon_interval = cpu_to_le16(100); priv->rxon_timing.beacon_init_val = cpu_to_le32(102400); @@ -694,7 +721,7 @@ static void iwl_set_flags_for_band(struct iwl_priv *priv, else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; @@ -713,23 +740,23 @@ static void iwl4965_connection_init_rx_config(struct iwl_priv *priv) memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon)); switch (priv->iw_mode) { - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP; break; - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS; priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; break; - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS; priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK; priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; break; - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_MONITOR: priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER; priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK | RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK; @@ -758,7 +785,7 @@ static void iwl4965_connection_init_rx_config(struct iwl_priv *priv) * in some case A channels are all non IBSS * in this case force B/G channel */ - if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && + if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && !(is_channel_ibss(ch_info))) ch_info = &priv->channel_info[0]; @@ -853,7 +880,7 @@ static void iwl4965_set_rate(struct iwl_priv *priv) (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; } -#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT +#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT #include "iwl-spectrum.h" @@ -1057,7 +1084,7 @@ static void iwl4965_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) static void iwl4965_rx_spectrum_measure_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { -#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT +#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; struct iwl4965_spectrum_notification *report = &(pkt->u.spectrum_notif); @@ -1155,7 +1182,7 @@ static void iwl4965_rx_beacon_notif(struct iwl_priv *priv, le32_to_cpu(beacon->low_tsf), rate); #endif - if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && + if ((priv->iw_mode == NL80211_IFTYPE_AP) && (!test_bit(STATUS_EXIT_PENDING, &priv->status))) queue_work(priv->workqueue, &priv->beacon_update); } @@ -1231,6 +1258,37 @@ static void iwl4965_rx_card_state_notif(struct iwl_priv *priv, wake_up_interruptible(&priv->wait_command_queue); } +int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) +{ + int ret; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + ret = iwl_grab_nic_access(priv); + if (ret) + goto err; + + if (src == IWL_PWR_SRC_VAUX) { + u32 val; + ret = pci_read_config_dword(priv->pci_dev, PCI_CFG_POWER_SOURCE, + &val); + + if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT) + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_PWR_SRC_VAUX, + ~APMG_PS_CTRL_MSK_PWR_SRC); + } else { + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, + ~APMG_PS_CTRL_MSK_PWR_SRC); + } + + iwl_release_nic_access(priv); +err: + spin_unlock_irqrestore(&priv->lock, flags); + return ret; +} + /** * iwl4965_setup_rx_handlers - Initialize Rx handler callbacks * @@ -2129,7 +2187,10 @@ static void __iwl4965_down(struct iwl_priv *priv) udelay(5); /* FIXME: apm_ops.suspend(priv) */ - priv->cfg->ops->lib->apm_ops.reset(priv); + if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status)) + priv->cfg->ops->lib->apm_ops.stop(priv); + else + priv->cfg->ops->lib->apm_ops.reset(priv); priv->cfg->ops->lib->free_shared_mem(priv); exit: @@ -2170,17 +2231,16 @@ static int __iwl4965_up(struct iwl_priv *priv) } /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(priv, CSR_GP_CNTRL) & - CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) + if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) clear_bit(STATUS_RF_KILL_HW, &priv->status); else set_bit(STATUS_RF_KILL_HW, &priv->status); - if (!test_bit(STATUS_IN_SUSPEND, &priv->status) && - iwl_is_rfkill(priv)) { + if (iwl_is_rfkill(priv)) { + iwl4965_enable_interrupts(priv); IWL_WARNING("Radio disabled by %s RF Kill switch\n", test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW"); - return -ENODEV; + return 0; } iwl_write32(priv, CSR_INT, 0xFFFFFFFF); @@ -2216,11 +2276,6 @@ static int __iwl4965_up(struct iwl_priv *priv) memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr, priv->ucode_data.len); - /* We return success when we resume from suspend and rf_kill is on. */ - if (test_bit(STATUS_RF_KILL_HW, &priv->status) || - test_bit(STATUS_RF_KILL_SW, &priv->status)) - return 0; - for (i = 0; i < MAX_HW_RESTARTS; i++) { iwl_clear_stations_table(priv); @@ -2333,7 +2388,7 @@ static void iwl4965_bg_set_monitor(struct work_struct *work) mutex_lock(&priv->mutex); - ret = iwl4965_set_mode(priv, IEEE80211_IF_TYPE_MNTR); + ret = iwl4965_set_mode(priv, NL80211_IFTYPE_MONITOR); if (ret) { if (ret == -EAGAIN) @@ -2414,8 +2469,8 @@ static void iwl4965_post_associate(struct iwl_priv *priv) DECLARE_MAC_BUF(mac); unsigned long flags; - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { - IWL_ERROR("%s Should not be called in AP mode\n", __FUNCTION__); + if (priv->iw_mode == NL80211_IFTYPE_AP) { + IWL_ERROR("%s Should not be called in AP mode\n", __func__); return; } @@ -2431,6 +2486,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv) if (!priv->vif || !priv->is_open) return; + iwl_power_cancel_timeout(priv); iwl_scan_cancel_timeout(priv, 200); conf = ieee80211_get_hw_conf(priv->hw); @@ -2448,8 +2504,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv) priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - if (priv->current_ht_config.is_ht) - iwl_set_rxon_ht(priv, &priv->current_ht_config); + iwl_set_rxon_ht(priv, &priv->current_ht_config); iwl_set_rxon_chain(priv); priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); @@ -2468,7 +2523,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv) else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } @@ -2476,10 +2531,10 @@ static void iwl4965_post_associate(struct iwl_priv *priv) iwl4965_commit_rxon(priv); switch (priv->iw_mode) { - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: break; - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: /* assume default assoc id */ priv->assoc_id = 1; @@ -2491,48 +2546,27 @@ static void iwl4965_post_associate(struct iwl_priv *priv) default: IWL_ERROR("%s Should not be called in %d mode\n", - __FUNCTION__, priv->iw_mode); + __func__, priv->iw_mode); break; } - /* Enable Rx differential gain and sensitivity calibrations */ - iwl_chain_noise_reset(priv); - priv->start_calib = 1; - - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) priv->assoc_station_added = 1; spin_lock_irqsave(&priv->lock, flags); iwl_activate_qos(priv, 0); spin_unlock_irqrestore(&priv->lock, flags); - iwl_power_update_mode(priv, 0); - /* we have just associated, don't start scan too early */ - priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; -} - -static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); - -static void iwl_bg_scan_completed(struct work_struct *work) -{ - struct iwl_priv *priv = - container_of(work, struct iwl_priv, scan_completed); - - IWL_DEBUG_SCAN("SCAN complete scan\n"); + /* the chain noise calibration will enabled PM upon completion + * If chain noise has already been run, then we need to enable + * power management here */ + if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE) + iwl_power_enable_management(priv); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - if (test_bit(STATUS_CONF_PENDING, &priv->status)) - iwl4965_mac_config(priv->hw, ieee80211_get_hw_conf(priv->hw)); - - ieee80211_scan_completed(priv->hw); + /* Enable Rx differential gain and sensitivity calibrations */ + iwl_chain_noise_reset(priv); + priv->start_calib = 1; - /* Since setting the TXPOWER may have been deferred while - * performing the scan, fire one off */ - mutex_lock(&priv->mutex); - iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); - mutex_unlock(&priv->mutex); } /***************************************************************************** @@ -2547,6 +2581,7 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw) { struct iwl_priv *priv = hw->priv; int ret; + u16 pci_cmd; IWL_DEBUG_MAC80211("enter\n"); @@ -2557,6 +2592,13 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw) pci_restore_state(priv->pci_dev); pci_enable_msi(priv->pci_dev); + /* enable interrupts if needed: hw bug w/a */ + pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); + if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { + pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; + pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd); + } + ret = request_irq(priv->pci_dev->irq, iwl4965_isr, IRQF_SHARED, DRV_NAME, priv); if (ret) { @@ -2589,6 +2631,9 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw) if (ret) goto out_release_irq; + if (iwl_is_rfkill(priv)) + goto out; + IWL_DEBUG_INFO("Start UP work done.\n"); if (test_bit(STATUS_IN_SUSPEND, &priv->status)) @@ -2608,6 +2653,7 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw) } } +out: priv->is_open = 1; IWL_DEBUG_MAC80211("leave\n"); return 0; @@ -2659,13 +2705,7 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct iwl_priv *priv = hw->priv; - IWL_DEBUG_MAC80211("enter\n"); - - if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { - IWL_DEBUG_MAC80211("leave - monitor\n"); - dev_kfree_skb_any(skb); - return 0; - } + IWL_DEBUG_MACDUMP("enter\n"); IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); @@ -2673,7 +2713,7 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (iwl_tx_skb(priv, skb)) dev_kfree_skb_any(skb); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MACDUMP("leave\n"); return 0; } @@ -2731,8 +2771,6 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value); - priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP); - if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) { IWL_DEBUG_MAC80211("leave - RF-KILL - waiting for uCode\n"); goto out; @@ -2750,7 +2788,6 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co if (unlikely(!priv->cfg->mod_params->disable_hw_scan && test_bit(STATUS_SCANNING, &priv->status))) { IWL_DEBUG_MAC80211("leave - scanning\n"); - set_bit(STATUS_CONF_PENDING, &priv->status); mutex_unlock(&priv->mutex); return 0; } @@ -2763,7 +2800,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co goto out; } - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS && + if (priv->iw_mode == NL80211_IFTYPE_ADHOC && !is_channel_ibss(ch_info)) { IWL_ERROR("channel %d in band %d not IBSS channel\n", conf->channel->hw_value, conf->channel->band); @@ -2773,6 +2810,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co spin_lock_irqsave(&priv->lock, flags); + /* if we are switching from ht to 2.4 clear flags * from any ht related info since 2.4 does not * support ht */ @@ -2783,7 +2821,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co ) priv->staging_rxon.flags = 0; - iwl_set_rxon_channel(priv, conf->channel->band, channel); + iwl_set_rxon_channel(priv, conf->channel); iwl_set_flags_for_band(priv, conf->channel->band); @@ -2812,6 +2850,13 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co goto out; } + if (conf->flags & IEEE80211_CONF_PS) + ret = iwl_power_set_user_mode(priv, IWL_POWER_INDEX_3); + else + ret = iwl_power_set_user_mode(priv, IWL_POWER_MODE_CAM); + if (ret) + IWL_DEBUG_MAC80211("Error setting power level\n"); + IWL_DEBUG_MAC80211("TX Power old=%d new=%d\n", priv->tx_power_user_lmt, conf->power_level); @@ -2828,7 +2873,6 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co IWL_DEBUG_MAC80211("leave\n"); out: - clear_bit(STATUS_CONF_PENDING, &priv->status); mutex_unlock(&priv->mutex); return ret; } @@ -2877,7 +2921,7 @@ static void iwl4965_config_ap(struct iwl_priv *priv) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } @@ -2916,7 +2960,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, return 0; } - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS && + if (priv->iw_mode == NL80211_IFTYPE_ADHOC && conf->changed & IEEE80211_IFCC_BEACON) { struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); if (!beacon) @@ -2926,7 +2970,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, return rc; } - if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && + if ((priv->iw_mode == NL80211_IFTYPE_AP) && (!conf->ssid_len)) { IWL_DEBUG_MAC80211 ("Leaving in AP mode because HostAPD is not ready.\n"); @@ -2949,7 +2993,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { */ - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode == NL80211_IFTYPE_AP) { if (!conf->bssid) { conf->bssid = priv->mac_addr; memcpy(priv->bssid, priv->mac_addr, ETH_ALEN); @@ -2984,11 +3028,11 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, * to verify) - jpk */ memcpy(priv->bssid, conf->bssid, ETH_ALEN); - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) + if (priv->iw_mode == NL80211_IFTYPE_AP) iwl4965_config_ap(priv); else { rc = iwl4965_commit_rxon(priv); - if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc) + if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) iwl_rxon_add_station( priv, priv->active_rxon.bssid_addr, 1); } @@ -3024,7 +3068,7 @@ static void iwl4965_configure_filter(struct ieee80211_hw *hw, if (changed_flags & (*total_flags) & FIF_OTHER_BSS) { IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n", - IEEE80211_IF_TYPE_MNTR, + NL80211_IFTYPE_MONITOR, changed_flags, *total_flags); /* queue work 'cuz mac80211 is holding a lock which * prevents us from issuing (synchronous) f/w cmds */ @@ -3102,8 +3146,13 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, if (bss_conf->assoc) { priv->assoc_id = bss_conf->aid; priv->beacon_int = bss_conf->beacon_int; + priv->power_data.dtim_period = bss_conf->dtim_period; priv->timestamp = bss_conf->timestamp; priv->assoc_capability = bss_conf->assoc_capability; + + /* we have just associated, don't start scan too early + * leave time for EAPOL exchange to complete + */ priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; mutex_lock(&priv->mutex); @@ -3120,11 +3169,11 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, } -static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) +static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len) { - int rc = 0; unsigned long flags; struct iwl_priv *priv = hw->priv; + int ret; IWL_DEBUG_MAC80211("enter\n"); @@ -3132,41 +3181,47 @@ static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) spin_lock_irqsave(&priv->lock, flags); if (!iwl_is_ready_rf(priv)) { - rc = -EIO; + ret = -EIO; IWL_DEBUG_MAC80211("leave - not ready or exit pending\n"); goto out_unlock; } - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { /* APs don't scan */ - rc = -EIO; + if (priv->iw_mode == NL80211_IFTYPE_AP) { /* APs don't scan */ + ret = -EIO; IWL_ERROR("ERROR: APs don't scan\n"); goto out_unlock; } - /* we don't schedule scan within next_scan_jiffies period */ + /* We don't schedule scan within next_scan_jiffies period. + * Avoid scanning during possible EAPOL exchange, return + * success immediately. + */ if (priv->next_scan_jiffies && - time_after(priv->next_scan_jiffies, jiffies)) { - rc = -EAGAIN; + time_after(priv->next_scan_jiffies, jiffies)) { + IWL_DEBUG_SCAN("scan rejected: within next scan period\n"); + queue_work(priv->workqueue, &priv->scan_completed); + ret = 0; goto out_unlock; } + /* if we just finished scan ask for delay */ - if (priv->last_scan_jiffies && time_after(priv->last_scan_jiffies + - IWL_DELAY_NEXT_SCAN, jiffies)) { - rc = -EAGAIN; + if (iwl_is_associated(priv) && priv->last_scan_jiffies && + time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, jiffies)) { + IWL_DEBUG_SCAN("scan rejected: within previous scan period\n"); + queue_work(priv->workqueue, &priv->scan_completed); + ret = 0; goto out_unlock; } - if (len) { - IWL_DEBUG_SCAN("direct scan for %s [%d]\n ", - iwl_escape_essid(ssid, len), (int)len); + if (ssid_len) { priv->one_direct_scan = 1; - priv->direct_ssid_len = (u8) - min((u8) len, (u8) IW_ESSID_MAX_SIZE); + priv->direct_ssid_len = min_t(u8, ssid_len, IW_ESSID_MAX_SIZE); memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len); - } else + } else { priv->one_direct_scan = 0; + } - rc = iwl_scan_initiate(priv); + ret = iwl_scan_initiate(priv); IWL_DEBUG_MAC80211("leave\n"); @@ -3174,7 +3229,7 @@ out_unlock: spin_unlock_irqrestore(&priv->lock, flags); mutex_unlock(&priv->mutex); - return rc; + return ret; } static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw, @@ -3263,7 +3318,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, * in 1X mode. * In legacy wep mode, we use another host command to the uCode */ if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id && - priv->iw_mode != IEEE80211_IF_TYPE_AP) { + priv->iw_mode != NL80211_IFTYPE_AP) { if (cmd == SET_KEY) is_default_wep_key = !priv->key_mapping_key; else @@ -3334,7 +3389,7 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; priv->qos_data.qos_active = 1; - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) + if (priv->iw_mode == NL80211_IFTYPE_AP) iwl_activate_qos(priv, 1); else if (priv->assoc_id && iwl_is_associated(priv)) iwl_activate_qos(priv, 0); @@ -3345,6 +3400,39 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, return 0; } +static int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn) +{ + struct iwl_priv *priv = hw->priv; + DECLARE_MAC_BUF(mac); + + IWL_DEBUG_HT("A-MPDU action on addr %s tid %d\n", + print_mac(mac, sta->addr), tid); + + if (!(priv->cfg->sku & IWL_SKU_N)) + return -EACCES; + + switch (action) { + case IEEE80211_AMPDU_RX_START: + IWL_DEBUG_HT("start Rx\n"); + return iwl_rx_agg_start(priv, sta->addr, tid, *ssn); + case IEEE80211_AMPDU_RX_STOP: + IWL_DEBUG_HT("stop Rx\n"); + return iwl_rx_agg_stop(priv, sta->addr, tid); + case IEEE80211_AMPDU_TX_START: + IWL_DEBUG_HT("start Tx\n"); + return iwl_tx_agg_start(priv, sta->addr, tid, ssn); + case IEEE80211_AMPDU_TX_STOP: + IWL_DEBUG_HT("stop Tx\n"); + return iwl_tx_agg_stop(priv, sta->addr, tid); + default: + IWL_DEBUG_HT("unknown\n"); + return -EINVAL; + break; + } + return 0; +} static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw, struct ieee80211_tx_queue_stats *stats) { @@ -3419,7 +3507,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) priv->beacon_int = priv->hw->conf.beacon_int; priv->timestamp = 0; - if ((priv->iw_mode == IEEE80211_IF_TYPE_STA)) + if ((priv->iw_mode == NL80211_IFTYPE_STATION)) priv->beacon_int = 0; spin_unlock_irqrestore(&priv->lock, flags); @@ -3433,7 +3521,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) /* we are restarting association process * clear RXON_FILTER_ASSOC_MSK bit */ - if (priv->iw_mode != IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode != NL80211_IFTYPE_AP) { iwl_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl4965_commit_rxon(priv); @@ -3442,7 +3530,17 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) iwl_power_update_mode(priv, 0); /* Per mac80211.h: This is only used in IBSS mode... */ - if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) { + if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { + + /* switch to CAM during association period. + * the ucode will block any association/authentication + * frome during assiciation period if it can not hear + * the AP because of PM. the timer enable PM back is + * association do not complete + */ + if (priv->hw->conf.channel->flags & (IEEE80211_CHAN_PASSIVE_SCAN | + IEEE80211_CHAN_RADAR)) + iwl_power_disable_management(priv, 3000); IWL_DEBUG_MAC80211("leave - not in IBSS\n"); mutex_unlock(&priv->mutex); @@ -3471,7 +3569,7 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk return -EIO; } - if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) { + if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { IWL_DEBUG_MAC80211("leave - not IBSS\n"); mutex_unlock(&priv->mutex); return -EIO; @@ -3486,7 +3584,7 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk priv->assoc_id = 0; timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; - priv->timestamp = le64_to_cpu(timestamp) + (priv->beacon_int * 1000); + priv->timestamp = le64_to_cpu(timestamp); IWL_DEBUG_MAC80211("leave\n"); spin_unlock_irqrestore(&priv->lock, flags); @@ -3528,11 +3626,11 @@ static ssize_t store_debug_level(struct device *d, const char *buf, size_t count) { struct iwl_priv *priv = d->driver_data; - char *p = (char *)buf; - u32 val; + unsigned long val; + int ret; - val = simple_strtoul(p, &p, 0); - if (p == buf) + ret = strict_strtoul(buf, 0, &val); + if (ret) printk(KERN_INFO DRV_NAME ": %s is not in hex or decimal form.\n", buf); else @@ -3592,15 +3690,6 @@ static ssize_t show_temperature(struct device *d, static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); -static ssize_t show_rs_window(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct iwl_priv *priv = d->driver_data; - return iwl4965_fill_rs_info(priv->hw, buf, IWL_AP_ID); -} -static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL); - static ssize_t show_tx_power(struct device *d, struct device_attribute *attr, char *buf) { @@ -3613,11 +3702,11 @@ static ssize_t store_tx_power(struct device *d, const char *buf, size_t count) { struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; - char *p = (char *)buf; - u32 val; + unsigned long val; + int ret; - val = simple_strtoul(p, &p, 10); - if (p == buf) + ret = strict_strtoul(buf, 10, &val); + if (ret) printk(KERN_INFO DRV_NAME ": %s is not in decimal form.\n", buf); else @@ -3641,7 +3730,12 @@ static ssize_t store_flags(struct device *d, const char *buf, size_t count) { struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; - u32 flags = simple_strtoul(buf, NULL, 0); + unsigned long val; + u32 flags; + int ret = strict_strtoul(buf, 0, &val); + if (ret) + return ret; + flags = (u32)val; mutex_lock(&priv->mutex); if (le32_to_cpu(priv->staging_rxon.flags) != flags) { @@ -3649,8 +3743,7 @@ static ssize_t store_flags(struct device *d, if (iwl_scan_cancel_timeout(priv, 100)) IWL_WARNING("Could not cancel scan.\n"); else { - IWL_DEBUG_INFO("Committing rxon.flags = 0x%04X\n", - flags); + IWL_DEBUG_INFO("Commit rxon.flags = 0x%04X\n", flags); priv->staging_rxon.flags = cpu_to_le32(flags); iwl4965_commit_rxon(priv); } @@ -3676,7 +3769,12 @@ static ssize_t store_filter_flags(struct device *d, const char *buf, size_t count) { struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; - u32 filter_flags = simple_strtoul(buf, NULL, 0); + unsigned long val; + u32 filter_flags; + int ret = strict_strtoul(buf, 0, &val); + if (ret) + return ret; + filter_flags = (u32)val; mutex_lock(&priv->mutex); if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) { @@ -3699,7 +3797,7 @@ static ssize_t store_filter_flags(struct device *d, static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, store_filter_flags); -#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT +#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT static ssize_t show_measurement(struct device *d, struct device_attribute *attr, char *buf) @@ -3707,7 +3805,7 @@ static ssize_t show_measurement(struct device *d, struct iwl_priv *priv = dev_get_drvdata(d); struct iwl4965_spectrum_notification measure_report; u32 size = sizeof(measure_report), len = 0, ofs = 0; - u8 *data = (u8 *) & measure_report; + u8 *data = (u8 *)&measure_report; unsigned long flags; spin_lock_irqsave(&priv->lock, flags); @@ -3770,17 +3868,19 @@ static ssize_t store_measurement(struct device *d, static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR, show_measurement, store_measurement); -#endif /* CONFIG_IWL4965_SPECTRUM_MEASUREMENT */ +#endif /* CONFIG_IWLAGN_SPECTRUM_MEASUREMENT */ static ssize_t store_retry_rate(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { struct iwl_priv *priv = dev_get_drvdata(d); + long val; + int ret = strict_strtol(buf, 10, &val); + if (!ret) + return ret; - priv->retry_rate = simple_strtoul(buf, NULL, 0); - if (priv->retry_rate <= 0) - priv->retry_rate = 1; + priv->retry_rate = (val > 0) ? val : 1; return count; } @@ -3800,77 +3900,58 @@ static ssize_t store_power_level(struct device *d, const char *buf, size_t count) { struct iwl_priv *priv = dev_get_drvdata(d); - int rc; - int mode; + int ret; + unsigned long mode; + - mode = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); if (!iwl_is_ready(priv)) { - rc = -EAGAIN; + ret = -EAGAIN; goto out; } - rc = iwl_power_set_user_mode(priv, mode); - if (rc) { + ret = strict_strtoul(buf, 10, &mode); + if (ret) + goto out; + + ret = iwl_power_set_user_mode(priv, mode); + if (ret) { IWL_DEBUG_MAC80211("failed setting power mode.\n"); goto out; } - rc = count; + ret = count; out: mutex_unlock(&priv->mutex); - return rc; + return ret; } -#define MAX_WX_STRING 80 - -/* Values are in microsecond */ -static const s32 timeout_duration[] = { - 350000, - 250000, - 75000, - 37000, - 25000, -}; -static const s32 period_duration[] = { - 400000, - 700000, - 1000000, - 1000000, - 1000000 -}; - static ssize_t show_power_level(struct device *d, struct device_attribute *attr, char *buf) { struct iwl_priv *priv = dev_get_drvdata(d); + int mode = priv->power_data.user_power_setting; + int system = priv->power_data.system_power_setting; int level = priv->power_data.power_mode; char *p = buf; - p += sprintf(p, "%d ", level); - switch (level) { - case IWL_POWER_MODE_CAM: - case IWL_POWER_AC: - p += sprintf(p, "(AC)"); + switch (system) { + case IWL_POWER_SYS_AUTO: + p += sprintf(p, "SYSTEM:auto"); break; - case IWL_POWER_BATTERY: - p += sprintf(p, "(BATTERY)"); + case IWL_POWER_SYS_AC: + p += sprintf(p, "SYSTEM:ac"); + break; + case IWL_POWER_SYS_BATTERY: + p += sprintf(p, "SYSTEM:battery"); break; - default: - p += sprintf(p, - "(Timeout %dms, Period %dms)", - timeout_duration[level - 1] / 1000, - period_duration[level - 1] / 1000); } -/* - if (!(priv->power_mode & IWL_POWER_ENABLED)) - p += sprintf(p, " OFF\n"); - else - p += sprintf(p, " \n"); -*/ - p += sprintf(p, " \n"); - return (p - buf + 1); + + p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO)?"fixed":"auto"); + p += sprintf(p, "\tINDEX:%d", level); + p += sprintf(p, "\n"); + return p - buf + 1; } static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level, @@ -3945,7 +4026,7 @@ static ssize_t show_statistics(struct device *d, struct iwl_priv *priv = dev_get_drvdata(d); u32 size = sizeof(struct iwl_notif_statistics); u32 len = 0, ofs = 0; - u8 *data = (u8 *) & priv->statistics; + u8 *data = (u8 *)&priv->statistics; int rc = 0; if (!iwl_is_alive(priv)) @@ -4010,9 +4091,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); - /* FIXME : remove when resolved PENDING */ - INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); iwl_setup_scan_deferred_work(priv); + iwl_setup_power_deferred_work(priv); if (priv->cfg->ops->lib->setup_deferred_work) priv->cfg->ops->lib->setup_deferred_work(priv); @@ -4032,6 +4112,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) cancel_delayed_work_sync(&priv->init_alive_start); cancel_delayed_work(&priv->scan_check); + cancel_delayed_work_sync(&priv->set_power_save); cancel_delayed_work(&priv->alive_start); cancel_work_sync(&priv->beacon_update); del_timer_sync(&priv->statistics_periodic); @@ -4041,12 +4122,11 @@ static struct attribute *iwl4965_sysfs_entries[] = { &dev_attr_channels.attr, &dev_attr_flags.attr, &dev_attr_filter_flags.attr, -#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT +#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT &dev_attr_measurement.attr, #endif &dev_attr_power_level.attr, &dev_attr_retry_rate.attr, - &dev_attr_rs_window.attr, &dev_attr_statistics.attr, &dev_attr_status.attr, &dev_attr_temperature.attr, @@ -4081,7 +4161,7 @@ static struct ieee80211_ops iwl4965_hw_ops = { .reset_tsf = iwl4965_mac_reset_tsf, .bss_info_changed = iwl4965_bss_info_changed, .ampdu_action = iwl4965_mac_ampdu_action, - .hw_scan = iwl4965_mac_hw_scan + .hw_scan = iwl_mac_hw_scan }; static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -4135,13 +4215,13 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e pci_set_master(pdev); - err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); if (!err) - err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); if (err) { - err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (!err) - err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); /* both attempts failed: */ if (err) { printk(KERN_WARNING "%s: No suitable DMA available.\n", @@ -4156,9 +4236,6 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e pci_set_drvdata(pdev, priv); - /* We disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state */ - pci_write_config_byte(pdev, 0x41, 0x00); /*********************** * 3. Read REV register @@ -4178,6 +4255,10 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e ": Detected Intel Wireless WiFi Link %s REV=0x%X\n", priv->cfg->name, priv->hw_rev); + /* We disable the RETRY_TIMEOUT register (0x41) to keep + * PCI Tx retries from interfering with C3 CPU state */ + pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); + /* amp init */ err = priv->cfg->ops->lib->apm_ops.init(priv); if (err < 0) { @@ -4303,15 +4384,18 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) iwl_dbgfs_unregister(priv); sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group); + /* ieee80211_unregister_hw call wil cause iwl4965_mac_stop to + * to be called and iwl4965_down since we are removing the device + * we need to set STATUS_EXIT_PENDING bit. + */ + set_bit(STATUS_EXIT_PENDING, &priv->status); if (priv->mac80211_registered) { ieee80211_unregister_hw(priv->hw); priv->mac80211_registered = 0; + } else { + iwl4965_down(priv); } - set_bit(STATUS_EXIT_PENDING, &priv->status); - - iwl4965_down(priv); - /* make sure we flush any pending irq or * tasklet for the driver */ @@ -4394,8 +4478,10 @@ static int iwl4965_pci_resume(struct pci_dev *pdev) /* Hardware specific file defines the PCI IDs table for that hardware module */ static struct pci_device_id iwl_hw_card_ids[] = { +#ifdef CONFIG_IWL4965 {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, +#endif /* CONFIG_IWL4965 */ #ifdef CONFIG_IWL5000 {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bg_cfg)}, {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bg_cfg)}, @@ -4407,7 +4493,10 @@ static struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)}, {IWL_PCI_DEVICE(0x4236, PCI_ANY_ID, iwl5300_agn_cfg)}, {IWL_PCI_DEVICE(0x4237, PCI_ANY_ID, iwl5100_agn_cfg)}, - {IWL_PCI_DEVICE(0x423A, PCI_ANY_ID, iwl5350_agn_cfg)}, +/* 5350 WiFi/WiMax */ + {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, + {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, + {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, #endif /* CONFIG_IWL5000 */ {0} }; @@ -4431,7 +4520,7 @@ static int __init iwl4965_init(void) printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); - ret = iwl4965_rate_control_register(); + ret = iwlagn_rate_control_register(); if (ret) { IWL_ERROR("Unable to register rate control algorithm: %d\n", ret); return ret; @@ -4446,14 +4535,14 @@ static int __init iwl4965_init(void) return ret; error_register: - iwl4965_rate_control_unregister(); + iwlagn_rate_control_unregister(); return ret; } static void __exit iwl4965_exit(void) { pci_unregister_driver(&iwl_driver); - iwl4965_rate_control_unregister(); + iwlagn_rate_control_unregister(); } module_exit(iwl4965_exit); diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index ef49440bd7f6..72fbf47229db 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c @@ -66,6 +66,66 @@ #include "iwl-core.h" #include "iwl-calib.h" +/***************************************************************************** + * INIT calibrations framework + *****************************************************************************/ + + int iwl_send_calib_results(struct iwl_priv *priv) +{ + int ret = 0; + int i = 0; + + struct iwl_host_cmd hcmd = { + .id = REPLY_PHY_CALIBRATION_CMD, + .meta.flags = CMD_SIZE_HUGE, + }; + + for (i = 0; i < IWL_CALIB_MAX; i++) + if (priv->calib_results[i].buf) { + hcmd.len = priv->calib_results[i].buf_len; + hcmd.data = priv->calib_results[i].buf; + ret = iwl_send_cmd_sync(priv, &hcmd); + if (ret) + goto err; + } + + return 0; +err: + IWL_ERROR("Error %d iteration %d\n", ret, i); + return ret; +} +EXPORT_SYMBOL(iwl_send_calib_results); + +int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len) +{ + if (res->buf_len != len) { + kfree(res->buf); + res->buf = kzalloc(len, GFP_ATOMIC); + } + if (unlikely(res->buf == NULL)) + return -ENOMEM; + + res->buf_len = len; + memcpy(res->buf, buf, len); + return 0; +} +EXPORT_SYMBOL(iwl_calib_set); + +void iwl_calib_free_results(struct iwl_priv *priv) +{ + int i; + + for (i = 0; i < IWL_CALIB_MAX; i++) { + kfree(priv->calib_results[i].buf); + priv->calib_results[i].buf = NULL; + priv->calib_results[i].buf_len = 0; + } +} + +/***************************************************************************** + * RUNTIME calibrations framework + *****************************************************************************/ + /* "false alarms" are signals that our DSP tries to lock onto, * but then determines that they are either noise, or transmissions * from a distant wireless network (also "noise", really) that get @@ -748,13 +808,11 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, } } + /* Save for use within RXON, TX, SCAN commands, etc. */ + priv->chain_noise_data.active_chains = active_chains; IWL_DEBUG_CALIB("active_chains (bitwise) = 0x%x\n", active_chains); - /* Save for use within RXON, TX, SCAN commands, etc. */ - /*priv->valid_antenna = active_chains;*/ - /*FIXME: should be reflected in RX chains in RXON */ - /* Analyze noise for rx balance */ average_noise[0] = ((data->chain_noise_a)/CAL_NUM_OF_BEACONS); average_noise[1] = ((data->chain_noise_b)/CAL_NUM_OF_BEACONS); @@ -779,6 +837,15 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, priv->cfg->ops->utils->gain_computation(priv, average_noise, min_average_noise_antenna_i, min_average_noise); + + /* Some power changes may have been made during the calibration. + * Update and commit the RXON + */ + if (priv->cfg->ops->lib->update_chain_flags) + priv->cfg->ops->lib->update_chain_flags(priv); + + data->state = IWL_CHAIN_NOISE_DONE; + iwl_power_enable_management(priv); } EXPORT_SYMBOL(iwl_chain_noise_calibration); diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index e9bb1de0ce3f..8d04e966ad48 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -163,6 +163,13 @@ enum { /* iwl_cmd_header flags value */ #define IWL_CMD_FAILED_MSK 0x40 +#define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f) +#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8) +#define SEQ_TO_INDEX(s) ((s) & 0xff) +#define INDEX_TO_SEQ(i) ((i) & 0xff) +#define SEQ_HUGE_FRAME __constant_cpu_to_le16(0x4000) +#define SEQ_RX_FRAME __constant_cpu_to_le16(0x8000) + /** * struct iwl_cmd_header * @@ -171,7 +178,7 @@ enum { */ struct iwl_cmd_header { u8 cmd; /* Command ID: REPLY_RXON, etc. */ - u8 flags; /* IWL_CMD_* */ + u8 flags; /* 0:5 reserved, 6 abort, 7 internal */ /* * The driver sets up the sequence number to values of its chosing. * uCode does not use this value, but passes it back to the driver @@ -187,11 +194,12 @@ struct iwl_cmd_header { * * The Linux driver uses the following format: * - * 0:7 index/position within Tx queue - * 8:13 Tx queue selection - * 14:14 driver sets this to indicate command is in the 'huge' - * storage at the end of the command buffers, i.e. scan cmd - * 15:15 uCode sets this in uCode-originated response/notification + * 0:7 tfd index - position within TX queue + * 8:12 TX queue id + * 13 reserved + * 14 huge - driver sets this to indicate command is in the + * 'huge' storage at the end of the command buffers + * 15 unsolicited RX or uCode-originated notification */ __le16 sequence; @@ -666,8 +674,7 @@ struct iwl4965_rxon_assoc_cmd { __le16 reserved; } __attribute__ ((packed)); - - +#define IWL_CONN_MAX_LISTEN_INTERVAL 10 /* * REPLY_RXON_TIMING = 0x14 (command, has simple generic response) @@ -1076,10 +1083,12 @@ struct iwl4965_rx_frame { } __attribute__ ((packed)); /* Fixed (non-configurable) rx data from phy */ -#define RX_PHY_FLAGS_ANTENNAE_OFFSET (4) -#define RX_PHY_FLAGS_ANTENNAE_MASK (0x70) -#define IWL_AGC_DB_MASK (0x3f80) /* MASK(7,13) */ -#define IWL_AGC_DB_POS (7) + +#define IWL49_RX_RES_PHY_CNT 14 +#define IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET (4) +#define IWL49_RX_PHY_FLAGS_ANTENNAE_MASK (0x70) +#define IWL49_AGC_DB_MASK (0x3f80) /* MASK(7,13) */ +#define IWL49_AGC_DB_POS (7) struct iwl4965_rx_non_cfg_phy { __le16 ant_selection; /* ant A bit 4, ant B bit 5, ant C bit 6 */ __le16 agc_info; /* agc code 0:6, agc dB 7:13, reserved 14:15 */ @@ -1087,12 +1096,30 @@ struct iwl4965_rx_non_cfg_phy { u8 pad[0]; } __attribute__ ((packed)); + +#define IWL50_RX_RES_PHY_CNT 8 +#define IWL50_RX_RES_AGC_IDX 1 +#define IWL50_RX_RES_RSSI_AB_IDX 2 +#define IWL50_RX_RES_RSSI_C_IDX 3 +#define IWL50_OFDM_AGC_MSK 0xfe00 +#define IWL50_OFDM_AGC_BIT_POS 9 +#define IWL50_OFDM_RSSI_A_MSK 0x00ff +#define IWL50_OFDM_RSSI_A_BIT_POS 0 +#define IWL50_OFDM_RSSI_B_MSK 0xff0000 +#define IWL50_OFDM_RSSI_B_BIT_POS 16 +#define IWL50_OFDM_RSSI_C_MSK 0x00ff +#define IWL50_OFDM_RSSI_C_BIT_POS 0 + +struct iwl5000_non_cfg_phy { + __le32 non_cfg_phy[IWL50_RX_RES_PHY_CNT]; /* upto 8 phy entries */ +} __attribute__ ((packed)); + + /* * REPLY_RX = 0xc3 (response only, not a command) * Used only for legacy (non 11n) frames. */ -#define RX_RES_PHY_CNT 14 -struct iwl4965_rx_phy_res { +struct iwl_rx_phy_res { u8 non_cfg_phy_cnt; /* non configurable DSP phy data byte count */ u8 cfg_phy_cnt; /* configurable DSP phy data byte count */ u8 stat_id; /* configurable DSP phy data set ID */ @@ -1101,8 +1128,7 @@ struct iwl4965_rx_phy_res { __le32 beacon_time_stamp; /* beacon at on-air rise */ __le16 phy_flags; /* general phy flags: band, modulation, ... */ __le16 channel; /* channel number */ - __le16 non_cfg_phy[RX_RES_PHY_CNT]; /* upto 14 phy entries */ - __le32 reserved2; + u8 non_cfg_phy_buf[32]; /* for various implementations of non_cfg_phy */ __le32 rate_n_flags; /* RATE_MCS_* */ __le16 byte_count; /* frame's byte-count */ __le16 reserved3; @@ -1993,7 +2019,7 @@ struct iwl4965_spectrum_notification { *****************************************************************************/ /** - * struct iwl4965_powertable_cmd - Power Table Command + * struct iwl_powertable_cmd - Power Table Command * @flags: See below: * * POWER_TABLE_CMD = 0x77 (command, has simple generic response) @@ -2008,8 +2034,8 @@ struct iwl4965_spectrum_notification { * bit 2 - '0' PM have to walk up every DTIM * '1' PM could sleep over DTIM till listen Interval. * PCI power managed - * bit 3 - '0' (PCI_LINK_CTRL & 0x1) - * '1' !(PCI_LINK_CTRL & 0x1) + * bit 3 - '0' (PCI_CFG_LINK_CTRL & 0x1) + * '1' !(PCI_CFG_LINK_CTRL & 0x1) * Force sleep Modes * bit 31/30- '00' use both mac/xtal sleeps * '01' force Mac sleep @@ -2027,7 +2053,7 @@ struct iwl4965_spectrum_notification { #define IWL_POWER_PCI_PM_MSK __constant_cpu_to_le16(1 << 3) #define IWL_POWER_FAST_PD __constant_cpu_to_le16(1 << 4) -struct iwl4965_powertable_cmd { +struct iwl_powertable_cmd { __le16 flags; u8 keep_alive_seconds; u8 debug_flags; @@ -2324,7 +2350,7 @@ struct iwl4965_beacon_notif { /* * REPLY_TX_BEACON = 0x91 (command, has simple generic response) */ -struct iwl4965_tx_beacon_cmd { +struct iwl_tx_beacon_cmd { struct iwl_tx_cmd tx; __le16 tim_idx; u8 tim_size; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index a44188bf4459..4c312c55f90c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -28,7 +28,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <net/mac80211.h> struct iwl_priv; /* FIXME: remove */ @@ -307,14 +306,14 @@ void iwl_reset_qos(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); priv->qos_data.qos_active = 0; - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) { + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) { if (priv->qos_data.qos_enable) priv->qos_data.qos_active = 1; if (!(priv->active_rate & 0xfff0)) { cw_min = 31; is_legacy = 1; } - } else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + } else if (priv->iw_mode == NL80211_IFTYPE_AP) { if (priv->qos_data.qos_enable) priv->qos_data.qos_active = 1; } else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) { @@ -383,8 +382,8 @@ void iwl_reset_qos(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_reset_qos); -#define MAX_BIT_RATE_40_MHZ 0x96; /* 150 Mbps */ -#define MAX_BIT_RATE_20_MHZ 0x48; /* 72 Mbps */ +#define MAX_BIT_RATE_40_MHZ 0x96 /* 150 Mbps */ +#define MAX_BIT_RATE_20_MHZ 0x48 /* 72 Mbps */ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, struct ieee80211_ht_info *ht_info, enum ieee80211_band band) @@ -400,8 +399,8 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, ht_info->cap |= (u16)IEEE80211_HT_CAP_GRN_FLD; ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_20; - ht_info->cap |= (u16)(IEEE80211_HT_CAP_MIMO_PS & - (IWL_MIMO_PS_NONE << 2)); + ht_info->cap |= (u16)(IEEE80211_HT_CAP_SM_PS & + (WLAN_HT_CAP_SM_PS_DISABLED << 2)); max_bit_rate = MAX_BIT_RATE_20_MHZ; if (priv->hw_params.fat_channel & BIT(band)) { @@ -593,12 +592,11 @@ static void iwlcore_free_geos(struct iwl_priv *priv) clear_bit(STATUS_GEO_CONFIGURED, &priv->status); } -static u8 is_single_rx_stream(struct iwl_priv *priv) +static bool is_single_rx_stream(struct iwl_priv *priv) { return !priv->current_ht_config.is_ht || ((priv->current_ht_config.supp_mcs_set[1] == 0) && - (priv->current_ht_config.supp_mcs_set[2] == 0)) || - priv->ps_mode == IWL_MIMO_PS_STATIC; + (priv->current_ht_config.supp_mcs_set[2] == 0)); } static u8 iwl_is_channel_extension(struct iwl_priv *priv, @@ -648,8 +646,14 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) struct iwl_rxon_cmd *rxon = &priv->staging_rxon; u32 val; - if (!ht_info->is_ht) + if (!ht_info->is_ht) { + rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | + RXON_FLG_CHANNEL_MODE_PURE_40_MSK | + RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | + RXON_FLG_FAT_PROT_MSK | + RXON_FLG_HT_PROT_MSK); return; + } /* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */ if (iwl_is_fat_tx_allowed(priv, NULL)) @@ -699,39 +703,63 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) } EXPORT_SYMBOL(iwl_set_rxon_ht); -/* - * Determine how many receiver/antenna chains to use. +#define IWL_NUM_RX_CHAINS_MULTIPLE 3 +#define IWL_NUM_RX_CHAINS_SINGLE 2 +#define IWL_NUM_IDLE_CHAINS_DUAL 2 +#define IWL_NUM_IDLE_CHAINS_SINGLE 1 + +/* Determine how many receiver/antenna chains to use. * More provides better reception via diversity. Fewer saves power. * MIMO (dual stream) requires at least 2, but works better with 3. * This does not determine *which* chains to use, just how many. */ -static int iwlcore_get_rx_chain_counter(struct iwl_priv *priv, - u8 *idle_state, u8 *rx_state) +static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) { - u8 is_single = is_single_rx_stream(priv); - u8 is_cam = test_bit(STATUS_POWER_PMI, &priv->status) ? 0 : 1; + bool is_single = is_single_rx_stream(priv); + bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); /* # of Rx chains to use when expecting MIMO. */ - if (is_single || (!is_cam && (priv->ps_mode == IWL_MIMO_PS_STATIC))) - *rx_state = 2; + if (is_single || (!is_cam && (priv->current_ht_config.sm_ps == + WLAN_HT_CAP_SM_PS_STATIC))) + return IWL_NUM_RX_CHAINS_SINGLE; else - *rx_state = 3; + return IWL_NUM_RX_CHAINS_MULTIPLE; +} +static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) +{ + int idle_cnt; + bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); /* # Rx chains when idling and maybe trying to save power */ - switch (priv->ps_mode) { - case IWL_MIMO_PS_STATIC: - case IWL_MIMO_PS_DYNAMIC: - *idle_state = (is_cam) ? 2 : 1; + switch (priv->current_ht_config.sm_ps) { + case WLAN_HT_CAP_SM_PS_STATIC: + case WLAN_HT_CAP_SM_PS_DYNAMIC: + idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL : + IWL_NUM_IDLE_CHAINS_SINGLE; break; - case IWL_MIMO_PS_NONE: - *idle_state = (is_cam) ? *rx_state : 1; + case WLAN_HT_CAP_SM_PS_DISABLED: + idle_cnt = (is_cam) ? active_cnt : IWL_NUM_IDLE_CHAINS_SINGLE; break; + case WLAN_HT_CAP_SM_PS_INVALID: default: - *idle_state = 1; + IWL_ERROR("invalide mimo ps mode %d\n", + priv->current_ht_config.sm_ps); + WARN_ON(1); + idle_cnt = -1; break; } + return idle_cnt; +} - return 0; +/* up to 4 chains */ +static u8 iwl_count_chain_bitmap(u32 chain_bitmap) +{ + u8 res; + res = (chain_bitmap & BIT(0)) >> 0; + res += (chain_bitmap & BIT(1)) >> 1; + res += (chain_bitmap & BIT(2)) >> 2; + res += (chain_bitmap & BIT(4)) >> 4; + return res; } /** @@ -742,39 +770,59 @@ static int iwlcore_get_rx_chain_counter(struct iwl_priv *priv, */ void iwl_set_rxon_chain(struct iwl_priv *priv) { - u8 is_single = is_single_rx_stream(priv); - u8 idle_state, rx_state; - - priv->staging_rxon.rx_chain = 0; - rx_state = idle_state = 3; + bool is_single = is_single_rx_stream(priv); + bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); + u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt; + u32 active_chains; + u16 rx_chain; /* Tell uCode which antennas are actually connected. * Before first association, we assume all antennas are connected. * Just after first association, iwl_chain_noise_calibration() * checks which antennas actually *are* connected. */ - priv->staging_rxon.rx_chain |= - cpu_to_le16(priv->hw_params.valid_rx_ant << - RXON_RX_CHAIN_VALID_POS); + if (priv->chain_noise_data.active_chains) + active_chains = priv->chain_noise_data.active_chains; + else + active_chains = priv->hw_params.valid_rx_ant; + + rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS; /* How many receivers should we use? */ - iwlcore_get_rx_chain_counter(priv, &idle_state, &rx_state); - priv->staging_rxon.rx_chain |= - cpu_to_le16(rx_state << RXON_RX_CHAIN_MIMO_CNT_POS); - priv->staging_rxon.rx_chain |= - cpu_to_le16(idle_state << RXON_RX_CHAIN_CNT_POS); - - if (!is_single && (rx_state >= 2) && - !test_bit(STATUS_POWER_PMI, &priv->status)) + active_rx_cnt = iwl_get_active_rx_chain_count(priv); + idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt); + + + /* correct rx chain count according hw settings + * and chain noise calibration + */ + valid_rx_cnt = iwl_count_chain_bitmap(active_chains); + if (valid_rx_cnt < active_rx_cnt) + active_rx_cnt = valid_rx_cnt; + + if (valid_rx_cnt < idle_rx_cnt) + idle_rx_cnt = valid_rx_cnt; + + rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS; + rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; + + priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain); + + if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam) priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; else priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; - IWL_DEBUG_ASSOC("rx chain %X\n", priv->staging_rxon.rx_chain); + IWL_DEBUG_ASSOC("rx_chain=0x%X active=%d idle=%d\n", + priv->staging_rxon.rx_chain, + active_rx_cnt, idle_rx_cnt); + + WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 || + active_rx_cnt < idle_rx_cnt); } EXPORT_SYMBOL(iwl_set_rxon_chain); /** - * iwlcore_set_rxon_channel - Set the phymode and channel values in staging RXON + * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz * @channel: Any channel valid for the requested phymode @@ -783,10 +831,11 @@ EXPORT_SYMBOL(iwl_set_rxon_chain); * NOTE: Does not commit to the hardware; it sets appropriate bit fields * in the staging RXON flag structure based on the phymode */ -int iwl_set_rxon_channel(struct iwl_priv *priv, - enum ieee80211_band band, - u16 channel) +int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) { + enum ieee80211_band band = ch->band; + u16 channel = ieee80211_frequency_to_channel(ch->center_freq); + if (!iwl_get_channel_info(priv, band, channel)) { IWL_DEBUG_INFO("Could not set channel to %d [%d]\n", channel, band); @@ -815,12 +864,15 @@ int iwl_setup_mac(struct iwl_priv *priv) { int ret; struct ieee80211_hw *hw = priv->hw; - hw->rate_control_algorithm = "iwl-4965-rs"; + hw->rate_control_algorithm = "iwl-agn-rs"; /* Tell mac80211 our characteristics */ - hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE | - IEEE80211_HW_SIGNAL_DBM | + hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; /* queues to support 11n aggregation */ @@ -828,6 +880,7 @@ int iwl_setup_mac(struct iwl_priv *priv) hw->ampdu_queues = priv->cfg->mod_params->num_of_ampdu_queues; hw->conf.beacon_int = 100; + hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = @@ -877,7 +930,6 @@ int iwl_init_drv(struct iwl_priv *priv) spin_lock_init(&priv->power_data.lock); spin_lock_init(&priv->sta_lock); spin_lock_init(&priv->hcmd_lock); - spin_lock_init(&priv->lq_mngr.lock); INIT_LIST_HEAD(&priv->free_frames); @@ -891,10 +943,10 @@ int iwl_init_drv(struct iwl_priv *priv) priv->ieee_rates = NULL; priv->band = IEEE80211_BAND_2GHZ; - priv->iw_mode = IEEE80211_IF_TYPE_STA; + priv->iw_mode = NL80211_IFTYPE_STATION; priv->use_ant_b_for_management_frame = 1; /* start with ant B */ - priv->ps_mode = IWL_MIMO_PS_NONE; + priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED; /* Choose which receivers/antennas to use */ iwl_set_rxon_chain(priv); @@ -908,8 +960,6 @@ int iwl_init_drv(struct iwl_priv *priv) priv->qos_data.qos_active = 0; priv->qos_data.qos_cap.val = 0; - iwl_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6); - priv->rates_mask = IWL_RATES_MASK; /* If power management is turned on, default to AC mode */ priv->power_mode = IWL_POWER_AC; @@ -936,22 +986,6 @@ err: } EXPORT_SYMBOL(iwl_init_drv); -void iwl_free_calib_results(struct iwl_priv *priv) -{ - kfree(priv->calib_results.lo_res); - priv->calib_results.lo_res = NULL; - priv->calib_results.lo_res_len = 0; - - kfree(priv->calib_results.tx_iq_res); - priv->calib_results.tx_iq_res = NULL; - priv->calib_results.tx_iq_res_len = 0; - - kfree(priv->calib_results.tx_iq_perd_res); - priv->calib_results.tx_iq_perd_res = NULL; - priv->calib_results.tx_iq_perd_res_len = 0; -} -EXPORT_SYMBOL(iwl_free_calib_results); - int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) { int ret = 0; @@ -979,10 +1013,9 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) } EXPORT_SYMBOL(iwl_set_tx_power); - void iwl_uninit_drv(struct iwl_priv *priv) { - iwl_free_calib_results(priv); + iwl_calib_free_results(priv); iwlcore_free_geos(priv); iwl_free_channel_map(priv); kfree(priv->scan); @@ -1136,7 +1169,6 @@ int iwl_verify_ucode(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_verify_ucode); - static const char *desc_lookup(int i) { switch (i) { @@ -1217,9 +1249,9 @@ EXPORT_SYMBOL(iwl_dump_nic_error_log); /** * iwl_print_event_log - Dump error event log to syslog * - * NOTE: Must be called with iwl4965_grab_nic_access() already obtained! + * NOTE: Must be called with iwl_grab_nic_access() already obtained! */ -void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, +static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, u32 num_events, u32 mode) { u32 i; @@ -1260,8 +1292,6 @@ void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, } } } -EXPORT_SYMBOL(iwl_print_event_log); - void iwl_dump_nic_event_log(struct iwl_priv *priv) { @@ -1377,7 +1407,7 @@ void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv) iwl_scan_cancel(priv); /* FIXME: This is a workaround for AP */ - if (priv->iw_mode != IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode != NL80211_IFTYPE_AP) { spin_lock_irqsave(&priv->lock, flags); iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_SW_BIT_RFKILL); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index db66114f1e56..288b6a800e03 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -95,6 +95,8 @@ struct iwl_hcmd_utils_ops { void (*chain_noise_reset)(struct iwl_priv *priv); void (*rts_tx_cmd_flag)(struct ieee80211_tx_info *info, __le32 *tx_flags); + int (*calc_rssi)(struct iwl_priv *priv, + struct iwl_rx_phy_res *rx_resp); }; struct iwl_lib_ops { @@ -139,7 +141,6 @@ struct iwl_lib_ops { int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src); } apm_ops; /* power */ - int (*set_power)(struct iwl_priv *priv, void *cmd); int (*send_tx_power) (struct iwl_priv *priv); void (*update_chain_flags)(struct iwl_priv *priv); void (*temperature) (struct iwl_priv *priv); @@ -183,14 +184,10 @@ struct iwl_cfg { struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, struct ieee80211_ops *hw_ops); void iwl_hw_detect(struct iwl_priv *priv); - void iwl_clear_stations_table(struct iwl_priv *priv); -void iwl_free_calib_results(struct iwl_priv *priv); void iwl_reset_qos(struct iwl_priv *priv); void iwl_set_rxon_chain(struct iwl_priv *priv); -int iwl_set_rxon_channel(struct iwl_priv *priv, - enum ieee80211_band band, - u16 channel); +int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info); u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv, struct ieee80211_ht_info *sta_ht_inf); @@ -217,7 +214,6 @@ void iwl_rx_replenish(struct iwl_priv *priv); int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); int iwl_rx_agg_start(struct iwl_priv *priv, const u8 *addr, int tid, u16 ssn); int iwl_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid); -/* FIXME: remove when TX is moved to iwl core */ int iwl_rx_queue_restock(struct iwl_priv *priv); int iwl_rx_queue_space(const struct iwl_rx_queue *q); void iwl_rx_allocate(struct iwl_priv *priv); @@ -236,11 +232,7 @@ void iwl_rx_statistics(struct iwl_priv *priv, ******************************************************/ int iwl_txq_ctx_reset(struct iwl_priv *priv); int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); -/* FIXME: remove when free Tx is fully merged into iwlcore */ -int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); void iwl_hw_txq_ctx_free(struct iwl_priv *priv); -int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd, - dma_addr_t addr, u16 len); int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); @@ -255,6 +247,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); * RF -Kill - here and not in iwl-rfkill.h to be available when * RF-kill subsystem is not compiled. ****************************************************/ +void iwl_rf_kill(struct iwl_priv *priv); void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv); int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv); @@ -285,11 +278,17 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) void iwl_init_scan_params(struct iwl_priv *priv); int iwl_scan_cancel(struct iwl_priv *priv); int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); -const char *iwl_escape_essid(const char *essid, u8 essid_len); int iwl_scan_initiate(struct iwl_priv *priv); void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); void iwl_setup_scan_deferred_work(struct iwl_priv *priv); +/******************************************************************************* + * Calibrations - implemented in iwl-calib.c + ******************************************************************************/ +int iwl_send_calib_results(struct iwl_priv *priv); +int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); +void iwl_calib_free_results(struct iwl_priv *priv); + /***************************************************** * S e n d i n g H o s t C o m m a n d s * *****************************************************/ @@ -311,8 +310,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); /***************************************************** * Error Handling Debugging ******************************************************/ -void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, - u32 num_events, u32 mode); void iwl_dump_nic_error_log(struct iwl_priv *priv); void iwl_dump_nic_event_log(struct iwl_priv *priv); @@ -336,8 +333,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv); #define STATUS_SCAN_HW 15 #define STATUS_POWER_PMI 16 #define STATUS_FW_ERROR 17 -#define STATUS_CONF_PENDING 18 -#define STATUS_MODE_PENDING 19 +#define STATUS_MODE_PENDING 18 static inline int iwl_is_ready(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 545ed692d889..662edf4f8d22 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -64,7 +64,7 @@ #define CSR_BASE (0x000) #define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */ -#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */ +#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */ #define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */ #define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */ #define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/ @@ -104,6 +104,7 @@ * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step */ #define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) +#define CSR_DBG_HPET_MEM_REG (CSR_BASE+0x240) /* Bits for CSR_HW_IF_CONFIG_REG */ #define CSR49_HW_IF_CONFIG_REG_BIT_4965_R (0x00000010) @@ -118,7 +119,12 @@ #define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000) #define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000) -#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) +#define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000) +#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) +#define CSR_HW_IF_CONFIG_REG_BIT_PCI_OWN_SEM (0x00400000) +#define CSR_HW_IF_CONFIG_REG_BIT_ME_OWN (0x02000000) +#define CSR_HW_IF_CONFIG_REG_BIT_WAKE_ME (0x08000000) + /* interrupt flags in INTA, set by uCode or hardware (e.g. dma), * acknowledged (reset) by host writing "1" to flagged bits. */ @@ -236,6 +242,8 @@ #define CSR39_ANA_PLL_CFG_VAL (0x01000000) #define CSR50_ANA_PLL_CFG_VAL (0x00880300) +/* HPET MEM debug */ +#define CSR_DBG_HPET_MEM_REG_VAL (0xFFFF0000) /*=== HBUS (Host-side Bus) ===*/ #define HBUS_BASE (0x400) /* diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 58384805a494..e548d67f87fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -33,12 +33,12 @@ #define IWL_DEBUG(level, fmt, args...) \ do { if (priv->debug_level & (level)) \ dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) + in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) #define IWL_DEBUG_LIMIT(level, fmt, args...) \ do { if ((priv->debug_level & (level)) && net_ratelimit()) \ dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) + in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) #ifdef CONFIG_IWLWIFI_DEBUGFS struct iwl_debugfs { @@ -68,12 +68,8 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv); #endif #else -static inline void IWL_DEBUG(int level, const char *fmt, ...) -{ -} -static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...) -{ -} +#define IWL_DEBUG(level, fmt, args...) +#define IWL_DEBUG_LIMIT(level, fmt, args...) #endif /* CONFIG_IWLWIFI_DEBUG */ @@ -114,11 +110,12 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) * */ -#define IWL_DL_INFO (1 << 0) -#define IWL_DL_MAC80211 (1 << 1) -#define IWL_DL_HOST_COMMAND (1 << 2) -#define IWL_DL_STATE (1 << 3) - +#define IWL_DL_INFO (1 << 0) +#define IWL_DL_MAC80211 (1 << 1) +#define IWL_DL_HCMD (1 << 2) +#define IWL_DL_STATE (1 << 3) +#define IWL_DL_MACDUMP (1 << 4) +#define IWL_DL_HCMD_DUMP (1 << 5) #define IWL_DL_RADIO (1 << 7) #define IWL_DL_POWER (1 << 8) #define IWL_DL_TEMP (1 << 9) @@ -158,6 +155,7 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DEBUG_INFO(f, a...) IWL_DEBUG(IWL_DL_INFO, f, ## a) #define IWL_DEBUG_MAC80211(f, a...) IWL_DEBUG(IWL_DL_MAC80211, f, ## a) +#define IWL_DEBUG_MACDUMP(f, a...) IWL_DEBUG(IWL_DL_MACDUMP, f, ## a) #define IWL_DEBUG_TEMP(f, a...) IWL_DEBUG(IWL_DL_TEMP, f, ## a) #define IWL_DEBUG_SCAN(f, a...) IWL_DEBUG(IWL_DL_SCAN, f, ## a) #define IWL_DEBUG_RX(f, a...) IWL_DEBUG(IWL_DL_RX, f, ## a) @@ -165,7 +163,8 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DEBUG_ISR(f, a...) IWL_DEBUG(IWL_DL_ISR, f, ## a) #define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a) #define IWL_DEBUG_WEP(f, a...) IWL_DEBUG(IWL_DL_WEP, f, ## a) -#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HOST_COMMAND, f, ## a) +#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HCMD, f, ## a) +#define IWL_DEBUG_HC_DUMP(f, a...) IWL_DEBUG(IWL_DL_HCMD_DUMP, f, ## a) #define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a) #define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a) #define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index ed948dc59b3d..20db0eb636a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -231,7 +231,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, DECLARE_MAC_BUF(mac); buf = kmalloc(bufsz, GFP_KERNEL); - if(!buf) + if (!buf) return -ENOMEM; pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n", @@ -364,16 +364,19 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) { struct iwl_debugfs *dbgfs; struct dentry *phyd = priv->hw->wiphy->debugfsdir; + int ret = 0; dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL); if (!dbgfs) { + ret = -ENOMEM; goto err; } priv->dbgfs = dbgfs; dbgfs->name = name; dbgfs->dir_drv = debugfs_create_dir(name, phyd); - if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)){ + if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)) { + ret = -ENOENT; goto err; } @@ -394,7 +397,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) err: IWL_ERROR("Can't open the debugfs directory\n"); iwl_dbgfs_unregister(priv); - return -ENOENT; + return ret; } EXPORT_SYMBOL(iwl_dbgfs_register); @@ -404,7 +407,7 @@ EXPORT_SYMBOL(iwl_dbgfs_register); */ void iwl_dbgfs_unregister(struct iwl_priv *priv) { - if (!(priv->dbgfs)) + if (!priv->dbgfs) return; DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_eeprom); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 4d789e353e3a..c018121085e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -36,7 +36,7 @@ #include <linux/kernel.h> #include <net/ieee80211_radiotap.h> -#define DRV_NAME "iwl4965" +#define DRV_NAME "iwlagn" #include "iwl-rfkill.h" #include "iwl-eeprom.h" #include "iwl-4965-hw.h" @@ -45,6 +45,7 @@ #include "iwl-debug.h" #include "iwl-led.h" #include "iwl-power.h" +#include "iwl-agn-rs.h" /* configuration for the iwl4965 */ extern struct iwl_cfg iwl4965_agn_cfg; @@ -134,8 +135,7 @@ struct iwl_tx_info { struct iwl_tx_queue { struct iwl_queue q; struct iwl_tfd_frame *bd; - struct iwl_cmd *cmd; - dma_addr_t dma_addr_cmd; + struct iwl_cmd *cmd[TFD_TX_CMD_SLOTS]; struct iwl_tx_info *txb; int need_update; int sched_retry; @@ -191,7 +191,6 @@ struct iwl4965_clip_group { const s8 clip_powers[IWL_MAX_RATES]; }; -#include "iwl-4965-rs.h" #define IWL_TX_FIFO_AC0 0 #define IWL_TX_FIFO_AC1 1 @@ -219,19 +218,13 @@ enum iwl_pwr_src { struct iwl_frame { union { struct ieee80211_hdr frame; - struct iwl4965_tx_beacon_cmd beacon; + struct iwl_tx_beacon_cmd beacon; u8 raw[IEEE80211_FRAME_LEN]; u8 cmd[360]; } u; struct list_head list; }; -#define SEQ_TO_QUEUE(x) ((x >> 8) & 0xbf) -#define QUEUE_TO_SEQ(x) ((x & 0xbf) << 8) -#define SEQ_TO_INDEX(x) ((u8)(x & 0xff)) -#define INDEX_TO_SEQ(x) ((u8)(x & 0xff)) -#define SEQ_HUGE_FRAME (0x4000) -#define SEQ_RX_FRAME __constant_cpu_to_le16(0x8000) #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) @@ -283,10 +276,9 @@ struct iwl_cmd { u32 val32; struct iwl4965_bt_cmd bt; struct iwl4965_rxon_time_cmd rxon_time; - struct iwl4965_powertable_cmd powertable; + struct iwl_powertable_cmd powertable; struct iwl_qosparam_cmd qosparam; struct iwl_tx_cmd tx; - struct iwl4965_tx_beacon_cmd tx_beacon; struct iwl4965_rxon_assoc_cmd rxon_assoc; struct iwl_rem_sta_cmd rm_sta; u8 *indirect; @@ -414,7 +406,7 @@ struct iwl_ht_info { /* self configuration data */ u8 is_ht; u8 supported_chan_width; - u16 tx_mimo_ps_mode; + u8 sm_ps; u8 is_green_field; u8 sgf; /* HT_SHORT_GI_* short guard interval */ u8 max_amsdu_size; @@ -573,49 +565,31 @@ struct iwl_hw_params { #define IWL_RX_STATS(x) (&x->u.rx_frame.stats) #define IWL_RX_DATA(x) (IWL_RX_HDR(x)->payload) - /****************************************************************************** * - * Functions implemented in iwl-base.c which are forward declared here - * for use by iwl-*.c + * Functions implemented in core module which are forward declared here + * for use by iwl-[4-5].c * - *****************************************************************************/ -struct iwl_addsta_cmd; -extern int iwl_send_add_sta(struct iwl_priv *priv, - struct iwl_addsta_cmd *sta, u8 flags); -u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap, - u8 flags, struct ieee80211_ht_info *ht_info); -extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv, - struct ieee80211_hdr *hdr, - const u8 *dest, int left); -extern void iwl4965_update_chain_flags(struct iwl_priv *priv); -int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src); - -extern const u8 iwl_bcast_addr[ETH_ALEN]; - -/****************************************************************************** - * - * Functions implemented in iwl-[34]*.c which are forward declared here - * for use by iwl-base.c - * - * NOTE: The implementation of these functions are hardware specific - * which is why they are in the hardware specific files (vs. iwl-base.c) + * NOTE: The implementation of these functions are not hardware specific + * which is why they are in the core module files. * * Naming convention -- - * iwl4965_ <-- Its part of iwlwifi (should be changed to iwl4965_) - * iwl4965_hw_ <-- Hardware specific (implemented in iwl-XXXX.c by all HW) + * iwl_ <-- Is part of iwlwifi * iwlXXXX_ <-- Hardware specific (implemented in iwl-XXXX.c for XXXX) * iwl4965_bg_ <-- Called from work queue context * iwl4965_mac_ <-- mac80211 callback * ****************************************************************************/ +struct iwl_addsta_cmd; +extern int iwl_send_add_sta(struct iwl_priv *priv, + struct iwl_addsta_cmd *sta, u8 flags); +extern u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, + int is_ap, u8 flags, struct ieee80211_ht_info *ht_info); +extern void iwl4965_update_chain_flags(struct iwl_priv *priv); +extern int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src); +extern const u8 iwl_bcast_addr[ETH_ALEN]; extern int iwl_rxq_stop(struct iwl_priv *priv); extern void iwl_txq_ctx_stop(struct iwl_priv *priv); -extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, - struct iwl_frame *frame, u8 rate); -extern void iwl4965_disable_events(struct iwl_priv *priv); - -extern int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel); extern int iwl_queue_space(const struct iwl_queue *q); static inline int iwl_queue_used(const struct iwl_queue *q, int i) { @@ -638,16 +612,6 @@ static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge) struct iwl_priv; -/* - * Forward declare iwl-4965.c functions for iwl-base.c - */ -extern void iwl4965_rf_kill_ct_config(struct iwl_priv *priv); - -int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, - enum ieee80211_ampdu_mlme_action action, - const u8 *addr, u16 tid, u16 *ssn); -int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id, - u8 tid, int txq_id); /* Structures, enum, and defines specific to the 4965 */ @@ -662,11 +626,6 @@ struct iwl_kw { #define IWL_CHANNEL_WIDTH_20MHZ 0 #define IWL_CHANNEL_WIDTH_40MHZ 1 -#define IWL_MIMO_PS_STATIC 0 -#define IWL_MIMO_PS_NONE 3 -#define IWL_MIMO_PS_DYNAMIC 1 -#define IWL_MIMO_PS_INVALID 2 - #define IWL_OPERATION_MODE_AUTO 0 #define IWL_OPERATION_MODE_HT_ONLY 1 #define IWL_OPERATION_MODE_MIXED 2 @@ -677,18 +636,6 @@ struct iwl_kw { #define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000 -struct iwl4965_lq_mngr { - spinlock_t lock; - s32 max_window_size; - s32 *expected_tpt; - u8 *next_higher_rate; - u8 *next_lower_rate; - unsigned long stamp; - unsigned long stamp_last; - u32 flush_time; - u32 tx_packets; -}; - /* Sensitivity and chain noise calibration */ #define INTERFERENCE_DATA_AVAILABLE __constant_cpu_to_le32(1) #define INITIALIZATION_VALUE 0xFFFF @@ -733,8 +680,9 @@ enum iwl4965_false_alarm_state { enum iwl4965_chain_noise_state { IWL_CHAIN_NOISE_ALIVE = 0, /* must be 0 */ - IWL_CHAIN_NOISE_ACCUMULATE = 1, - IWL_CHAIN_NOISE_CALIBRATED = 2, + IWL_CHAIN_NOISE_ACCUMULATE, + IWL_CHAIN_NOISE_CALIBRATED, + IWL_CHAIN_NOISE_DONE, }; enum iwl4965_calib_enabled_state { @@ -751,13 +699,10 @@ struct statistics_general_data { u32 beacon_energy_c; }; -struct iwl_calib_results { - void *tx_iq_res; - void *tx_iq_perd_res; - void *lo_res; - u32 tx_iq_res_len; - u32 tx_iq_perd_res_len; - u32 lo_res_len; +/* Opaque calibration results */ +struct iwl_calib_result { + void *buf; + size_t buf_len; }; enum ucode_type { @@ -795,33 +740,32 @@ struct iwl_sensitivity_data { /* Chain noise (differential Rx gain) calib data */ struct iwl_chain_noise_data { - u8 state; - u16 beacon_count; + u32 active_chains; u32 chain_noise_a; u32 chain_noise_b; u32 chain_noise_c; u32 chain_signal_a; u32 chain_signal_b; u32 chain_signal_c; + u16 beacon_count; u8 disconn_array[NUM_RX_CHAINS]; u8 delta_gain_code[NUM_RX_CHAINS]; u8 radio_write; + u8 state; }; #define EEPROM_SEM_TIMEOUT 10 /* milliseconds */ #define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ -#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT - enum { MEASUREMENT_READY = (1 << 0), MEASUREMENT_ACTIVE = (1 << 1), }; -#endif #define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */ +#define IWL_CALIB_MAX 3 struct iwl_priv { @@ -837,14 +781,13 @@ struct iwl_priv { enum ieee80211_band band; int alloc_rxb_skb; - bool add_radiotap; void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; -#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT +#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT /* spectrum measurement report caching */ struct iwl4965_spectrum_notification measure_report; u8 measurement_status; @@ -866,7 +809,7 @@ struct iwl_priv { s32 last_temperature; /* init calibration results */ - struct iwl_calib_results calib_results; + struct iwl_calib_result calib_results[IWL_CALIB_MAX]; /* Scan related variables */ unsigned long last_scan_jiffies; @@ -948,9 +891,6 @@ struct iwl_priv { u8 last_phy_res[100]; /* Rate scaling data */ - struct iwl4965_lq_mngr lq_mngr; - - /* Rate scaling data */ s8 data_retry_limit; u8 retry_rate; @@ -1014,7 +954,7 @@ struct iwl_priv { u8 *eeprom; struct iwl_eeprom_calib_info *calib_info; - enum ieee80211_if_types iw_mode; + enum nl80211_iftype iw_mode; struct sk_buff *ibss_beacon; @@ -1034,7 +974,6 @@ struct iwl_priv { * hardware */ u16 assoc_id; u16 assoc_capability; - u8 ps_mode; struct iwl_qos_info qos_data; @@ -1056,6 +995,7 @@ struct iwl_priv { struct tasklet_struct irq_tasklet; + struct delayed_work set_power_save; struct delayed_work init_alive_start; struct delayed_work alive_start; struct delayed_work scan_check; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 4a08a1b50979..37155755efc5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -63,7 +63,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <net/mac80211.h> @@ -146,7 +145,7 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) { u32 gp = iwl_read32(priv, CSR_EEPROM_GP); if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { - IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp); + IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp); return -ENOENT; } return 0; @@ -227,7 +226,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv); if (ret < 0) { - IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp); + IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp); ret = -ENOENT; goto err; } @@ -254,7 +253,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) } if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) { - IWL_ERROR("Time out reading EEPROM[%d]", addr); + IWL_ERROR("Time out reading EEPROM[%d]\n", addr); ret = -ETIMEDOUT; goto done; } @@ -273,8 +272,7 @@ EXPORT_SYMBOL(iwl_eeprom_init); void iwl_eeprom_free(struct iwl_priv *priv) { - if(priv->eeprom) - kfree(priv->eeprom); + kfree(priv->eeprom); priv->eeprom = NULL; } EXPORT_SYMBOL(iwl_eeprom_free); diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 944642450d3d..a72efdf6d1dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -247,8 +247,8 @@ #define FH_RCSR_CHNL0_RX_CONFIG_RBDBC_SIZE_MSK (0x00F00000) /* bits 20-23 */ #define FH_RCSR_CHNL0_RX_CONFIG_DMA_CHNL_EN_MSK (0xC0000000) /* bits 30-31*/ -#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT (20) -#define FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_BITSHIFT (4) +#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS (20) +#define FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS (4) #define RX_RB_TIMEOUT (0x10) #define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL (0x00000000) @@ -260,8 +260,9 @@ #define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_12K (0x00020000) #define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_16K (0x00030000) -#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000) -#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000) +#define FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY (0x00000004) +#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000) +#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000) /** @@ -287,6 +288,7 @@ #define FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000) +#define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT 28 /** * Transmit DMA Channel Control/Status Registers (TCSR) diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 8fa991b7202a..8300f3d00a06 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -28,7 +28,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <net/mac80211.h> #include "iwl-dev.h" /* FIXME: remove */ @@ -121,8 +120,18 @@ static int iwl_generic_cmd_callback(struct iwl_priv *priv, return 1; } - IWL_DEBUG_HC("back from %s (0x%08X)\n", - get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); +#ifdef CONFIG_IWLWIFI_DEBUG + switch (cmd->hdr.cmd) { + case REPLY_TX_LINK_QUALITY_CMD: + case SENSITIVITY_CMD: + IWL_DEBUG_HC_DUMP("back from %s (0x%08X)\n", + get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); + break; + default: + IWL_DEBUG_HC("back from %s (0x%08X)\n", + get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); + } +#endif /* Let iwl_tx_complete free the response skb */ return 1; @@ -228,7 +237,7 @@ cancel: * TX cmd queue. Otherwise in case the cmd comes * in later, it will possibly set an invalid * address (cmd->meta.source). */ - qcmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx]; + qcmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx]; qcmd->meta.flags &= ~CMD_WANT_SKB; } fail: diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 5bc3df432d2d..9740fcc1805e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -61,7 +61,7 @@ * */ -#define _iwl_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs)) +#define _iwl_write32(priv, ofs, val) iowrite32((val), (priv)->hw_base + (ofs)) #ifdef CONFIG_IWLWIFI_DEBUG static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv, u32 ofs, u32 val) @@ -75,7 +75,7 @@ static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv, #define iwl_write32(priv, ofs, val) _iwl_write32(priv, ofs, val) #endif -#define _iwl_read32(priv, ofs) readl((priv)->hw_base + (ofs)) +#define _iwl_read32(priv, ofs) ioread32((priv)->hw_base + (ofs)) #ifdef CONFIG_IWLWIFI_DEBUG static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs) { @@ -155,28 +155,10 @@ static inline void __iwl_clear_bit(const char *f, u32 l, static inline int _iwl_grab_nic_access(struct iwl_priv *priv) { int ret; - u32 gp_ctl; - #ifdef CONFIG_IWLWIFI_DEBUG if (atomic_read(&priv->restrict_refcnt)) return 0; #endif - if (test_bit(STATUS_RF_KILL_HW, &priv->status) || - test_bit(STATUS_RF_KILL_SW, &priv->status)) { - IWL_WARNING("WARNING: Requesting MAC access during RFKILL " - "wakes up NIC\n"); - - /* 10 msec allows time for NIC to complete its data save */ - gp_ctl = _iwl_read32(priv, CSR_GP_CNTRL); - if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) { - IWL_DEBUG_RF_KILL("Wait for complete power-down, " - "gpctl = 0x%08x\n", gp_ctl); - mdelay(10); - } else - IWL_DEBUG_RF_KILL("power-down complete, " - "gpctl = 0x%08x\n", gp_ctl); - } - /* this bit wakes up the NIC */ _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); ret = _iwl_poll_bit(priv, CSR_GP_CNTRL, diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 899d7a2567a8..4eee1b163cd2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -27,7 +27,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/dma-mapping.h> @@ -161,12 +160,32 @@ int iwl4965_led_off(struct iwl_priv *priv, int led_id) /* Set led register off */ static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id) { - IWL_DEBUG_LED("radio off\n"); + IWL_DEBUG_LED("LED Reg off\n"); iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF); return 0; } /* + * Set led register in case of disassociation according to rfkill state + */ +static int iwl_led_associate(struct iwl_priv *priv, int led_id) +{ + IWL_DEBUG_LED("Associated\n"); + priv->allow_blinking = 1; + return iwl4965_led_on_reg(priv, led_id); +} +static int iwl_led_disassociate(struct iwl_priv *priv, int led_id) +{ + priv->allow_blinking = 0; + if (iwl_is_rfkill(priv)) + iwl4965_led_off_reg(priv, led_id); + else + iwl4965_led_on_reg(priv, led_id); + + return 0; +} + +/* * brightness call back function for Tx/Rx LED */ static int iwl_led_associated(struct iwl_priv *priv, int led_id) @@ -199,16 +218,10 @@ static void iwl_led_brightness_set(struct led_classdev *led_cdev, led_type_str[led->type], brightness); switch (brightness) { case LED_FULL: - if (led->type == IWL_LED_TRG_ASSOC) - priv->allow_blinking = 1; - if (led->led_on) led->led_on(priv, IWL_LED_LINK); break; case LED_OFF: - if (led->type == IWL_LED_TRG_ASSOC) - priv->allow_blinking = 0; - if (led->led_off) led->led_off(priv, IWL_LED_LINK); break; @@ -228,12 +241,12 @@ static void iwl_led_brightness_set(struct led_classdev *led_cdev, */ static int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led, enum led_type type, u8 set_led, - const char *name, char *trigger) + char *trigger) { struct device *device = wiphy_dev(priv->hw->wiphy); int ret; - led->led_dev.name = name; + led->led_dev.name = led->name; led->led_dev.brightness_set = iwl_led_brightness_set; led->led_dev.default_trigger = trigger; @@ -268,7 +281,9 @@ static int iwl_get_blink_rate(struct iwl_priv *priv) if (tpt < 0) /* wrapparound */ tpt = -tpt; - IWL_DEBUG_LED("tpt %lld current_tpt %lld\n", tpt, current_tpt); + IWL_DEBUG_LED("tpt %lld current_tpt %llu\n", + (long long)tpt, + (unsigned long long)current_tpt); priv->led_tpt = current_tpt; if (!priv->allow_blinking) @@ -282,12 +297,6 @@ static int iwl_get_blink_rate(struct iwl_priv *priv) return i; } -static inline int is_rf_kill(struct iwl_priv *priv) -{ - return test_bit(STATUS_RF_KILL_HW, &priv->status) || - test_bit(STATUS_RF_KILL_SW, &priv->status); -} - /* * this function called from handler. Since setting Led command can * happen very frequent we postpone led command to be called from @@ -301,7 +310,7 @@ void iwl_leds_background(struct iwl_priv *priv) priv->last_blink_time = 0; return; } - if (is_rf_kill(priv)) { + if (iwl_is_rfkill(priv)) { priv->last_blink_time = 0; return; } @@ -335,7 +344,6 @@ EXPORT_SYMBOL(iwl_leds_background); int iwl_leds_register(struct iwl_priv *priv) { char *trigger; - char name[32]; int ret; priv->last_blink_rate = 0; @@ -344,7 +352,8 @@ int iwl_leds_register(struct iwl_priv *priv) priv->allow_blinking = 0; trigger = ieee80211_get_radio_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:radio", + snprintf(priv->led[IWL_LED_TRG_RADIO].name, + sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s:radio", wiphy_name(priv->hw->wiphy)); priv->led[IWL_LED_TRG_RADIO].led_on = iwl4965_led_on_reg; @@ -352,31 +361,33 @@ int iwl_leds_register(struct iwl_priv *priv) priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RADIO], - IWL_LED_TRG_RADIO, 1, name, trigger); + IWL_LED_TRG_RADIO, 1, trigger); if (ret) goto exit_fail; trigger = ieee80211_get_assoc_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:assoc", + snprintf(priv->led[IWL_LED_TRG_ASSOC].name, + sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s:assoc", wiphy_name(priv->hw->wiphy)); ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_ASSOC], - IWL_LED_TRG_ASSOC, 0, name, trigger); + IWL_LED_TRG_ASSOC, 0, trigger); /* for assoc always turn led on */ - priv->led[IWL_LED_TRG_ASSOC].led_on = iwl4965_led_on_reg; - priv->led[IWL_LED_TRG_ASSOC].led_off = iwl4965_led_on_reg; + priv->led[IWL_LED_TRG_ASSOC].led_on = iwl_led_associate; + priv->led[IWL_LED_TRG_ASSOC].led_off = iwl_led_disassociate; priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; if (ret) goto exit_fail; trigger = ieee80211_get_rx_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:RX", wiphy_name(priv->hw->wiphy)); - + snprintf(priv->led[IWL_LED_TRG_RX].name, + sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s:RX", + wiphy_name(priv->hw->wiphy)); ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RX], - IWL_LED_TRG_RX, 0, name, trigger); + IWL_LED_TRG_RX, 0, trigger); priv->led[IWL_LED_TRG_RX].led_on = iwl_led_associated; priv->led[IWL_LED_TRG_RX].led_off = iwl_led_associated; @@ -386,9 +397,12 @@ int iwl_leds_register(struct iwl_priv *priv) goto exit_fail; trigger = ieee80211_get_tx_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:TX", wiphy_name(priv->hw->wiphy)); + snprintf(priv->led[IWL_LED_TRG_TX].name, + sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s:TX", + wiphy_name(priv->hw->wiphy)); + ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_TX], - IWL_LED_TRG_TX, 0, name, trigger); + IWL_LED_TRG_TX, 0, trigger); priv->led[IWL_LED_TRG_TX].led_on = iwl_led_associated; priv->led[IWL_LED_TRG_TX].led_off = iwl_led_associated; diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 1980ae5a7e82..588c9ad20e83 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -52,6 +52,7 @@ enum led_type { struct iwl_led { struct iwl_priv *priv; struct led_classdev led_dev; + char name[32]; int (*led_on) (struct iwl_priv *priv, int led_id); int (*led_off) (struct iwl_priv *priv, int led_id); diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 2e71803e09ba..60a03d2d2d0e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -29,7 +29,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <net/mac80211.h> @@ -82,7 +81,7 @@ /* default power management (not Tx power) table values */ /* for tim 0-10 */ -static struct iwl_power_vec_entry range_0[IWL_POWER_AC] = { +static struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = { {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, @@ -93,7 +92,7 @@ static struct iwl_power_vec_entry range_0[IWL_POWER_AC] = { /* for tim = 3-10 */ -static struct iwl_power_vec_entry range_1[IWL_POWER_AC] = { +static struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = { {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0}, @@ -103,7 +102,7 @@ static struct iwl_power_vec_entry range_1[IWL_POWER_AC] = { }; /* for tim > 11 */ -static struct iwl_power_vec_entry range_2[IWL_POWER_AC] = { +static struct iwl_power_vec_entry range_2[IWL_POWER_MAX] = { {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, @@ -112,12 +111,19 @@ static struct iwl_power_vec_entry range_2[IWL_POWER_AC] = { {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} }; +/* set card power command */ +static int iwl_set_power(struct iwl_priv *priv, void *cmd) +{ + return iwl_send_cmd_pdu_async(priv, POWER_TABLE_CMD, + sizeof(struct iwl_powertable_cmd), + cmd, NULL); +} /* decide the right power level according to association status * and battery status */ static u16 iwl_get_auto_power_mode(struct iwl_priv *priv) { - u16 mode = priv->power_data.user_power_setting; + u16 mode; switch (priv->power_data.user_power_setting) { case IWL_POWER_AUTO: @@ -129,12 +135,16 @@ static u16 iwl_get_auto_power_mode(struct iwl_priv *priv) else mode = IWL_POWER_ON_AC_DISASSOC; break; + /* FIXME: remove battery and ac from here */ case IWL_POWER_BATTERY: mode = IWL_POWER_INDEX_3; break; case IWL_POWER_AC: mode = IWL_POWER_MODE_CAM; break; + default: + mode = priv->power_data.user_power_setting; + break; } return mode; } @@ -142,9 +152,10 @@ static u16 iwl_get_auto_power_mode(struct iwl_priv *priv) /* initialize to default */ static int iwl_power_init_handle(struct iwl_priv *priv) { - int ret = 0, i; struct iwl_power_mgr *pow_data; - int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_AC; + int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX; + struct iwl_powertable_cmd *cmd; + int i; u16 pci_pm; IWL_DEBUG_POWER("Initialize power \n"); @@ -157,30 +168,24 @@ static int iwl_power_init_handle(struct iwl_priv *priv) memcpy(&pow_data->pwr_range_1[0], &range_1[0], size); memcpy(&pow_data->pwr_range_2[0], &range_2[0], size); - ret = pci_read_config_word(priv->pci_dev, - PCI_LINK_CTRL, &pci_pm); - if (ret != 0) - return 0; - else { - struct iwl4965_powertable_cmd *cmd; + pci_read_config_word(priv->pci_dev, PCI_CFG_LINK_CTRL, &pci_pm); - IWL_DEBUG_POWER("adjust power command flags\n"); + IWL_DEBUG_POWER("adjust power command flags\n"); - for (i = 0; i < IWL_POWER_AC; i++) { - cmd = &pow_data->pwr_range_0[i].cmd; + for (i = 0; i < IWL_POWER_MAX; i++) { + cmd = &pow_data->pwr_range_0[i].cmd; - if (pci_pm & 0x1) - cmd->flags &= ~IWL_POWER_PCI_PM_MSK; - else - cmd->flags |= IWL_POWER_PCI_PM_MSK; - } + if (pci_pm & PCI_CFG_LINK_CTRL_VAL_L0S_EN) + cmd->flags &= ~IWL_POWER_PCI_PM_MSK; + else + cmd->flags |= IWL_POWER_PCI_PM_MSK; } - return ret; + return 0; } /* adjust power command according to dtim period and power level*/ static int iwl_update_power_command(struct iwl_priv *priv, - struct iwl4965_powertable_cmd *cmd, + struct iwl_powertable_cmd *cmd, u16 mode) { int ret = 0, i; @@ -204,7 +209,7 @@ static int iwl_update_power_command(struct iwl_priv *priv, range = &pow_data->pwr_range_2[0]; period = pow_data->dtim_period; - memcpy(cmd, &range[mode].cmd, sizeof(struct iwl4965_powertable_cmd)); + memcpy(cmd, &range[mode].cmd, sizeof(struct iwl_powertable_cmd)); if (period == 0) { period = 1; @@ -245,42 +250,52 @@ static int iwl_update_power_command(struct iwl_priv *priv, /* - * calucaute the final power mode index + * compute the final power mode index */ -int iwl_power_update_mode(struct iwl_priv *priv, u8 refresh) +int iwl_power_update_mode(struct iwl_priv *priv, bool force) { struct iwl_power_mgr *setting = &(priv->power_data); int ret = 0; u16 uninitialized_var(final_mode); - /* If on battery, set to 3, - * if plugged into AC power, set to CAM ("continuously aware mode"), - * else user level */ + /* Don't update the RX chain when chain noise calibration is running */ + if (priv->chain_noise_data.state != IWL_CHAIN_NOISE_DONE && + priv->chain_noise_data.state != IWL_CHAIN_NOISE_ALIVE) { + IWL_DEBUG_POWER("Cannot update the power, chain noise " + "calibration running: %d\n", + priv->chain_noise_data.state); + return -EAGAIN; + } + + /* If on battery, set to 3, + * if plugged into AC power, set to CAM ("continuously aware mode"), + * else user level */ switch (setting->system_power_setting) { - case IWL_POWER_AUTO: + case IWL_POWER_SYS_AUTO: final_mode = iwl_get_auto_power_mode(priv); break; - case IWL_POWER_BATTERY: + case IWL_POWER_SYS_BATTERY: final_mode = IWL_POWER_INDEX_3; break; - case IWL_POWER_AC: + case IWL_POWER_SYS_AC: final_mode = IWL_POWER_MODE_CAM; break; default: - final_mode = setting->system_power_setting; + final_mode = IWL_POWER_INDEX_3; + WARN_ON(1); } if (setting->critical_power_setting > final_mode) final_mode = setting->critical_power_setting; /* driver only support CAM for non STA network */ - if (priv->iw_mode != IEEE80211_IF_TYPE_STA) + if (priv->iw_mode != NL80211_IFTYPE_STATION) final_mode = IWL_POWER_MODE_CAM; if (!iwl_is_rfkill(priv) && !setting->power_disabled && - ((setting->power_mode != final_mode) || refresh)) { - struct iwl4965_powertable_cmd cmd; + ((setting->power_mode != final_mode) || force)) { + struct iwl_powertable_cmd cmd; if (final_mode != IWL_POWER_MODE_CAM) set_bit(STATUS_POWER_PMI, &priv->status); @@ -291,8 +306,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, u8 refresh) if (final_mode == IWL_POWER_INDEX_5) cmd.flags |= IWL_POWER_FAST_PD; - if (priv->cfg->ops->lib->set_power) - ret = priv->cfg->ops->lib->set_power(priv, &cmd); + ret = iwl_set_power(priv, &cmd); if (final_mode == IWL_POWER_MODE_CAM) clear_bit(STATUS_POWER_PMI, &priv->status); @@ -314,7 +328,7 @@ EXPORT_SYMBOL(iwl_power_update_mode); * this will be usefull for rate scale to disable PM during heavy * Tx/Rx activities */ -int iwl_power_disable_management(struct iwl_priv *priv) +int iwl_power_disable_management(struct iwl_priv *priv, u32 ms) { u16 prev_mode; int ret = 0; @@ -327,6 +341,11 @@ int iwl_power_disable_management(struct iwl_priv *priv) ret = iwl_power_update_mode(priv, 0); priv->power_data.power_disabled = 1; priv->power_data.user_power_setting = prev_mode; + cancel_delayed_work(&priv->set_power_save); + if (ms) + queue_delayed_work(priv->workqueue, &priv->set_power_save, + msecs_to_jiffies(ms)); + return ret; } @@ -349,35 +368,26 @@ EXPORT_SYMBOL(iwl_power_enable_management); /* set user_power_setting */ int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode) { - int ret = 0; - if (mode > IWL_POWER_LIMIT) return -EINVAL; priv->power_data.user_power_setting = mode; - ret = iwl_power_update_mode(priv, 0); - - return ret; + return iwl_power_update_mode(priv, 0); } EXPORT_SYMBOL(iwl_power_set_user_mode); - /* set system_power_setting. This should be set by over all * PM application. */ int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode) { - int ret = 0; - if (mode > IWL_POWER_LIMIT) return -EINVAL; priv->power_data.system_power_setting = mode; - ret = iwl_power_update_mode(priv, 0); - - return ret; + return iwl_power_update_mode(priv, 0); } EXPORT_SYMBOL(iwl_power_set_system_mode); @@ -388,7 +398,7 @@ void iwl_power_initialize(struct iwl_priv *priv) iwl_power_init_handle(priv); priv->power_data.user_power_setting = IWL_POWER_AUTO; priv->power_data.power_disabled = 0; - priv->power_data.system_power_setting = IWL_POWER_AUTO; + priv->power_data.system_power_setting = IWL_POWER_SYS_AUTO; priv->power_data.is_battery_active = 0; priv->power_data.power_disabled = 0; priv->power_data.critical_power_setting = 0; @@ -421,3 +431,35 @@ int iwl_power_temperature_change(struct iwl_priv *priv) return ret; } EXPORT_SYMBOL(iwl_power_temperature_change); + +static void iwl_bg_set_power_save(struct work_struct *work) +{ + struct iwl_priv *priv = container_of(work, + struct iwl_priv, set_power_save.work); + IWL_DEBUG(IWL_DL_STATE, "update power\n"); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + mutex_lock(&priv->mutex); + + /* on starting association we disable power managment + * until association, if association failed then this + * timer will expire and enable PM again. + */ + if (!iwl_is_associated(priv)) + iwl_power_enable_management(priv); + + mutex_unlock(&priv->mutex); +} +void iwl_setup_power_deferred_work(struct iwl_priv *priv) +{ + INIT_DELAYED_WORK(&priv->set_power_save, iwl_bg_set_power_save); +} +EXPORT_SYMBOL(iwl_setup_power_deferred_work); + +void iwl_power_cancel_timeout(struct iwl_priv *priv) +{ + cancel_delayed_work(&priv->set_power_save); +} +EXPORT_SYMBOL(iwl_power_cancel_timeout); diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index b066724a1c2b..df484a90ae64 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h @@ -33,12 +33,25 @@ struct iwl_priv; -#define IWL_POWER_MODE_CAM 0x00 /* Continuously Aware Mode, always on */ -#define IWL_POWER_INDEX_3 0x03 -#define IWL_POWER_INDEX_5 0x05 -#define IWL_POWER_AC 0x06 -#define IWL_POWER_BATTERY 0x07 -#define IWL_POWER_AUTO 0x08 +enum { + IWL_POWER_MODE_CAM, /* Continuously Aware Mode, always on */ + IWL_POWER_INDEX_1, + IWL_POWER_INDEX_2, + IWL_POWER_INDEX_3, + IWL_POWER_INDEX_4, + IWL_POWER_INDEX_5, + IWL_POWER_AUTO, + IWL_POWER_MAX = IWL_POWER_AUTO, + IWL_POWER_AC, + IWL_POWER_BATTERY, +}; + +enum { + IWL_POWER_SYS_AUTO, + IWL_POWER_SYS_AC, + IWL_POWER_SYS_BATTERY, +}; + #define IWL_POWER_LIMIT 0x08 #define IWL_POWER_MASK 0x0F #define IWL_POWER_ENABLED 0x10 @@ -46,27 +59,29 @@ struct iwl_priv; /* Power management (not Tx power) structures */ struct iwl_power_vec_entry { - struct iwl4965_powertable_cmd cmd; + struct iwl_powertable_cmd cmd; u8 no_dtim; }; struct iwl_power_mgr { spinlock_t lock; - struct iwl_power_vec_entry pwr_range_0[IWL_POWER_AC]; - struct iwl_power_vec_entry pwr_range_1[IWL_POWER_AC]; - struct iwl_power_vec_entry pwr_range_2[IWL_POWER_AC]; + struct iwl_power_vec_entry pwr_range_0[IWL_POWER_MAX]; + struct iwl_power_vec_entry pwr_range_1[IWL_POWER_MAX]; + struct iwl_power_vec_entry pwr_range_2[IWL_POWER_MAX]; u32 dtim_period; /* final power level that used to calculate final power command */ u8 power_mode; u8 user_power_setting; /* set by user through mac80211 or sysfs */ - u8 system_power_setting; /* set by kernel syatem tools */ + u8 system_power_setting; /* set by kernel system tools */ u8 critical_power_setting; /* set if driver over heated */ u8 is_battery_active; /* DC/AC power */ u8 power_disabled; /* flag to disable using power saving level */ }; -int iwl_power_update_mode(struct iwl_priv *priv, u8 refresh); -int iwl_power_disable_management(struct iwl_priv *priv); +void iwl_setup_power_deferred_work(struct iwl_priv *priv); +void iwl_power_cancel_timeout(struct iwl_priv *priv); +int iwl_power_update_mode(struct iwl_priv *priv, bool force); +int iwl_power_disable_management(struct iwl_priv *priv, u32 ms); int iwl_power_enable_management(struct iwl_priv *priv); int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode); int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode); diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 70d9c7568b98..ee5afd48d3af 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -84,14 +84,16 @@ #define APMG_CLK_VAL_DMA_CLK_RQT (0x00000200) #define APMG_CLK_VAL_BSM_CLK_RQT (0x00000800) -#define APMG_PS_CTRL_VAL_RESET_REQ (0x04000000) -#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) +#define APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS (0x00400000) +#define APMG_PS_CTRL_VAL_RESET_REQ (0x04000000) +#define APMG_PS_CTRL_MSK_PWR_SRC (0x03000000) +#define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000) +#define APMG_PS_CTRL_VAL_PWR_SRC_MAX (0x01000000) /* 3945 only */ +#define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x02000000) -#define APMG_PS_CTRL_MSK_PWR_SRC (0x03000000) -#define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000) -#define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x01000000) +#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) /** * BSM (Bootstrap State Machine) diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index e5e5846e9f25..5d642298f04c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -27,7 +27,6 @@ *****************************************************************************/ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <net/mac80211.h> diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index e2d9afba38a5..7cde9d76ff5d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -376,7 +376,9 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) { int ret; unsigned long flags; - unsigned int rb_size; + u32 rb_size; + const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ + const u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT why this stalls RX */ spin_lock_irqsave(&priv->lock, flags); ret = iwl_grab_nic_access(priv); @@ -398,26 +400,32 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) /* Tell device where to find RBD circular buffer in DRAM */ iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, - rxq->dma_addr >> 8); + (u32)(rxq->dma_addr >> 8)); /* Tell device where in DRAM to update its Rx status */ iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, (priv->shared_phys + priv->rb_closed_offset) >> 4); - /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */ + /* Enable Rx DMA + * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set becuase of HW bug in + * the credit mechanism in 5000 HW RX FIFO + * Direct rx interrupts to hosts + * Rx buffer size 4 or 8k + * RB timeout 0x10 + * 256 RBDs + */ iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | + FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | - rb_size | - /* 0x10 << 4 | */ - (RX_QUEUE_SIZE_LOG << - FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT)); - - /* - * iwl_write32(priv,CSR_INT_COAL_REG,0); - */ + rb_size| + (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| + (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); iwl_release_nic_access(priv); + + iwl_write32(priv, CSR_INT_COALESCING, 0x40); + spin_unlock_irqrestore(&priv->lock, flags); return 0; @@ -789,107 +797,6 @@ static inline void iwl_dbg_report_frame(struct iwl_priv *priv, } #endif -static void iwl_add_radiotap(struct iwl_priv *priv, - struct sk_buff *skb, - struct iwl4965_rx_phy_res *rx_start, - struct ieee80211_rx_status *stats, - u32 ampdu_status) -{ - s8 signal = stats->signal; - s8 noise = 0; - int rate = stats->rate_idx; - u64 tsf = stats->mactime; - __le16 antenna; - __le16 phy_flags_hw = rx_start->phy_flags; - struct iwl4965_rt_rx_hdr { - struct ieee80211_radiotap_header rt_hdr; - __le64 rt_tsf; /* TSF */ - u8 rt_flags; /* radiotap packet flags */ - u8 rt_rate; /* rate in 500kb/s */ - __le16 rt_channelMHz; /* channel in MHz */ - __le16 rt_chbitmask; /* channel bitfield */ - s8 rt_dbmsignal; /* signal in dBm, kluged to signed */ - s8 rt_dbmnoise; - u8 rt_antenna; /* antenna number */ - } __attribute__ ((packed)) *iwl4965_rt; - - /* TODO: We won't have enough headroom for HT frames. Fix it later. */ - if (skb_headroom(skb) < sizeof(*iwl4965_rt)) { - if (net_ratelimit()) - printk(KERN_ERR "not enough headroom [%d] for " - "radiotap head [%zd]\n", - skb_headroom(skb), sizeof(*iwl4965_rt)); - return; - } - - /* put radiotap header in front of 802.11 header and data */ - iwl4965_rt = (void *)skb_push(skb, sizeof(*iwl4965_rt)); - - /* initialise radiotap header */ - iwl4965_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; - iwl4965_rt->rt_hdr.it_pad = 0; - - /* total header + data */ - put_unaligned_le16(sizeof(*iwl4965_rt), &iwl4965_rt->rt_hdr.it_len); - - /* Indicate all the fields we add to the radiotap header */ - put_unaligned_le32((1 << IEEE80211_RADIOTAP_TSFT) | - (1 << IEEE80211_RADIOTAP_FLAGS) | - (1 << IEEE80211_RADIOTAP_RATE) | - (1 << IEEE80211_RADIOTAP_CHANNEL) | - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | - (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | - (1 << IEEE80211_RADIOTAP_ANTENNA), - &(iwl4965_rt->rt_hdr.it_present)); - - /* Zero the flags, we'll add to them as we go */ - iwl4965_rt->rt_flags = 0; - - put_unaligned_le64(tsf, &iwl4965_rt->rt_tsf); - - iwl4965_rt->rt_dbmsignal = signal; - iwl4965_rt->rt_dbmnoise = noise; - - /* Convert the channel frequency and set the flags */ - put_unaligned(cpu_to_le16(stats->freq), &iwl4965_rt->rt_channelMHz); - if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK)) - put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, - &iwl4965_rt->rt_chbitmask); - else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK) - put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ, - &iwl4965_rt->rt_chbitmask); - else /* 802.11g */ - put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ, - &iwl4965_rt->rt_chbitmask); - - if (rate == -1) - iwl4965_rt->rt_rate = 0; - else - iwl4965_rt->rt_rate = iwl_rates[rate].ieee; - - /* - * "antenna number" - * - * It seems that the antenna field in the phy flags value - * is actually a bitfield. This is undefined by radiotap, - * it wants an actual antenna number but I always get "7" - * for most legacy frames I receive indicating that the - * same frame was received on all three RX chains. - * - * I think this field should be removed in favour of a - * new 802.11n radiotap field "RX chains" that is defined - * as a bitmask. - */ - antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK; - iwl4965_rt->rt_antenna = le16_to_cpu(antenna) >> 4; - - /* set the preamble flag if appropriate */ - if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) - iwl4965_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; - - stats->flag |= RX_FLAG_RADIOTAP; -} - static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len) { /* 0 - mgmt, 1 - cnt, 2 - data */ @@ -1010,8 +917,8 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, struct ieee80211_rx_status *stats) { struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl4965_rx_phy_res *rx_start = (include_phy) ? - (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) : NULL; + struct iwl_rx_phy_res *rx_start = (include_phy) ? + (struct iwl_rx_phy_res *)&(pkt->u.raw[0]) : NULL; struct ieee80211_hdr *hdr; u16 len; __le32 *rx_end; @@ -1020,7 +927,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, u32 ampdu_status_legacy; if (!include_phy && priv->last_phy_res[0]) - rx_start = (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; + rx_start = (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; if (!rx_start) { IWL_ERROR("MPDU frame without a PHY data\n"); @@ -1032,8 +939,8 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, len = le16_to_cpu(rx_start->byte_count); - rx_end = (__le32 *) ((u8 *) &pkt->u.raw[0] + - sizeof(struct iwl4965_rx_phy_res) + + rx_end = (__le32 *)((u8 *) &pkt->u.raw[0] + + sizeof(struct iwl_rx_phy_res) + rx_start->cfg_phy_cnt + len); } else { @@ -1074,9 +981,6 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) return; - if (priv->add_radiotap) - iwl_add_radiotap(priv, rxb->skb, rx_start, stats, ampdu_status); - iwl_update_rx_stats(priv, le16_to_cpu(hdr->frame_control), len); ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats); priv->alloc_rxb_skb--; @@ -1084,40 +988,13 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, } /* Calc max signal level (dBm) among 3 possible receivers */ -static int iwl_calc_rssi(struct iwl_priv *priv, - struct iwl4965_rx_phy_res *rx_resp) +static inline int iwl_calc_rssi(struct iwl_priv *priv, + struct iwl_rx_phy_res *rx_resp) { - /* data from PHY/DSP regarding signal strength, etc., - * contents are always there, not configurable by host. */ - struct iwl4965_rx_non_cfg_phy *ncphy = - (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy; - u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL_AGC_DB_MASK) - >> IWL_AGC_DB_POS; - - u32 valid_antennae = - (le16_to_cpu(rx_resp->phy_flags) & RX_PHY_FLAGS_ANTENNAE_MASK) - >> RX_PHY_FLAGS_ANTENNAE_OFFSET; - u8 max_rssi = 0; - u32 i; - - /* Find max rssi among 3 possible receivers. - * These values are measured by the digital signal processor (DSP). - * They should stay fairly constant even as the signal strength varies, - * if the radio's automatic gain control (AGC) is working right. - * AGC value (see below) will provide the "interesting" info. */ - for (i = 0; i < 3; i++) - if (valid_antennae & (1 << i)) - max_rssi = max(ncphy->rssi_info[i << 1], max_rssi); - - IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n", - ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4], - max_rssi, agc); - - /* dBm = max_rssi dB - agc dB - constant. - * Higher AGC (higher radio gain) means lower signal. */ - return max_rssi - agc - IWL_RSSI_OFFSET; + return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); } + static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) { unsigned long flags; @@ -1157,10 +1034,10 @@ static int iwl_is_network_packet(struct iwl_priv *priv, /* Filter incoming packets to determine if they are targeted toward * this network, discarding packets coming from ourselves */ switch (priv->iw_mode) { - case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */ + case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */ /* packets to our IBSS update information */ return !compare_ether_addr(header->addr3, priv->bssid); - case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */ + case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */ /* packets to our IBSS update information */ return !compare_ether_addr(header->addr2, priv->bssid); default: @@ -1180,9 +1057,9 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, * this rx packet for legacy frames, * or phy data cached from REPLY_RX_PHY_CMD for HT frames. */ int include_phy = (pkt->hdr.cmd == REPLY_RX); - struct iwl4965_rx_phy_res *rx_start = (include_phy) ? - (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) : - (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; + struct iwl_rx_phy_res *rx_start = (include_phy) ? + (struct iwl_rx_phy_res *)&(pkt->u.raw[0]) : + (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; __le32 *rx_end; unsigned int len = 0; u16 fc; @@ -1198,9 +1075,11 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, if (rx_status.band == IEEE80211_BAND_5GHZ) rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; - rx_status.antenna = 0; rx_status.flag = 0; - rx_status.flag |= RX_FLAG_TSFT; + + /* TSF isn't reliable. In order to allow smooth user experience, + * this W/A doesn't propagate it to the mac80211 */ + /*rx_status.flag |= RX_FLAG_TSFT;*/ if ((unlikely(rx_start->cfg_phy_cnt > 20))) { IWL_DEBUG_DROP("dsp size out of range [0,20]: %d/n", @@ -1210,7 +1089,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, if (!include_phy) { if (priv->last_phy_res[0]) - rx_start = (struct iwl4965_rx_phy_res *) + rx_start = (struct iwl_rx_phy_res *) &priv->last_phy_res[1]; else rx_start = NULL; @@ -1227,7 +1106,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, len = le16_to_cpu(rx_start->byte_count); rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt + - sizeof(struct iwl4965_rx_phy_res) + len); + sizeof(struct iwl_rx_phy_res) + len); } else { struct iwl4965_rx_mpdu_res_start *amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; @@ -1277,8 +1156,28 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, rx_status.signal, rx_status.noise, rx_status.signal, (unsigned long long)rx_status.mactime); + /* + * "antenna number" + * + * It seems that the antenna field in the phy flags value + * is actually a bitfield. This is undefined by radiotap, + * it wants an actual antenna number but I always get "7" + * for most legacy frames I receive indicating that the + * same frame was received on all three RX chains. + * + * I think this field should be removed in favour of a + * new 802.11n radiotap field "RX chains" that is defined + * as a bitmask. + */ + rx_status.antenna = le16_to_cpu(rx_start->phy_flags & + RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4; + + /* set the preamble flag if appropriate */ + if (rx_start->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) + rx_status.flag |= RX_FLAG_SHORTPRE; + /* Take shortcut when only in monitor mode */ - if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { + if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { iwl_pass_packet_to_mac80211(priv, include_phy, rxb, &rx_status); return; @@ -1295,7 +1194,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, switch (fc & IEEE80211_FCTL_FTYPE) { case IEEE80211_FTYPE_MGMT: case IEEE80211_FTYPE_DATA: - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) + if (priv->iw_mode == NL80211_IFTYPE_AP) iwl_update_ps_mode(priv, fc & IEEE80211_FCTL_PM, header->addr2); /* fall through */ @@ -1316,6 +1215,6 @@ void iwl_rx_reply_rx_phy(struct iwl_priv *priv, struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; priv->last_phy_res[0] = 1; memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), - sizeof(struct iwl4965_rx_phy_res)); + sizeof(struct iwl_rx_phy_res)); } EXPORT_SYMBOL(iwl_rx_reply_rx_phy); diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index efc750d2fc5c..3b0bee331a33 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -88,7 +88,7 @@ static int iwl_is_empty_essid(const char *essid, int essid_len) -const char *iwl_escape_essid(const char *essid, u8 essid_len) +static const char *iwl_escape_essid(const char *essid, u8 essid_len) { static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; const char *s = essid; @@ -111,7 +111,6 @@ const char *iwl_escape_essid(const char *essid, u8 essid_len) *d = '\0'; return escaped; } -EXPORT_SYMBOL(iwl_escape_essid); /** * iwl_scan_cancel - Cancel any currently executing HW scan @@ -202,6 +201,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) clear_bit(STATUS_SCAN_HW, &priv->status); } + priv->alloc_rxb_skb--; dev_kfree_skb_any(cmd.meta.u.skb); return ret; @@ -270,6 +270,7 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv, static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { +#ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; @@ -277,6 +278,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, scan_notif->scanned_channels, scan_notif->tsf_low, scan_notif->tsf_high, scan_notif->status); +#endif /* The HW is no longer scanning */ clear_bit(STATUS_SCAN_HW, &priv->status); @@ -418,7 +420,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, else scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; - if ((scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) && n_probes) + if (n_probes) scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); scan_ch->active_dwell = cpu_to_le16(active_dwell); @@ -461,11 +463,6 @@ void iwl_init_scan_params(struct iwl_priv *priv) int iwl_scan_initiate(struct iwl_priv *priv) { - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { - IWL_ERROR("APs don't scan.\n"); - return 0; - } - if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_SCAN("Aborting scan due to not ready.\n"); return -EIO; @@ -477,8 +474,7 @@ int iwl_scan_initiate(struct iwl_priv *priv) } if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_SCAN("Scan request while abort pending. " - "Queuing.\n"); + IWL_DEBUG_SCAN("Scan request while abort pending\n"); return -EAGAIN; } @@ -707,7 +703,7 @@ static void iwl_bg_request_scan(struct work_struct *data) u16 cmd_len; enum ieee80211_band band; u8 n_probes = 2; - u8 rx_chain = 0x7; /* bitmap: ABC chains */ + u8 rx_chain = priv->hw_params.valid_rx_ant; conf = ieee80211_get_hw_conf(priv->hw); @@ -847,7 +843,7 @@ static void iwl_bg_request_scan(struct work_struct *data) /* Force use of chains B and C (0x6) for scan Rx for 4965 * Avoid A (0x1) because of its off-channel reception on A-band. - * MIMO is not used here, but value is required */ + */ if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) rx_chain = 0x6; } else { @@ -855,6 +851,7 @@ static void iwl_bg_request_scan(struct work_struct *data) goto done; } + /* MIMO is not used here, but value is required */ scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK | cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) | (rx_chain << RXON_RX_CHAIN_FORCE_SEL_POS) | @@ -866,7 +863,7 @@ static void iwl_bg_request_scan(struct work_struct *data) scan->tx_cmd.len = cpu_to_le16(cmd_len); - if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) + if (priv->iw_mode == NL80211_IFTYPE_MONITOR) scan->filter_flags = RXON_FILTER_PROMISC_MSK; scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | @@ -919,10 +916,29 @@ static void iwl_bg_abort_scan(struct work_struct *work) mutex_unlock(&priv->mutex); } +static void iwl_bg_scan_completed(struct work_struct *work) +{ + struct iwl_priv *priv = + container_of(work, struct iwl_priv, scan_completed); + + IWL_DEBUG_SCAN("SCAN complete scan\n"); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + ieee80211_scan_completed(priv->hw); + + /* Since setting the TXPOWER may have been deferred while + * performing the scan, fire one off */ + mutex_lock(&priv->mutex); + iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); + mutex_unlock(&priv->mutex); +} + + void iwl_setup_scan_deferred_work(struct iwl_priv *priv) { - /* FIXME: move here when resolved PENDING - * INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); */ + INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); INIT_WORK(&priv->request_scan, iwl_bg_request_scan); INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 6d1467d0bd9d..61797f3f8d5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -47,8 +47,8 @@ u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) unsigned long flags; DECLARE_MAC_BUF(mac); - if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) || - (priv->iw_mode == IEEE80211_IF_TYPE_AP)) + if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) || + (priv->iw_mode == NL80211_IFTYPE_AP)) start = IWL_STA_ID; if (is_broadcast_ether_addr(addr)) @@ -74,7 +74,7 @@ EXPORT_SYMBOL(iwl_find_station); int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) { - if (priv->iw_mode == IEEE80211_IF_TYPE_STA) { + if (priv->iw_mode == NL80211_IFTYPE_STATION) { return IWL_AP_ID; } else { u8 *da = ieee80211_get_DA(hdr); @@ -191,23 +191,23 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, if (!sta_ht_inf || !sta_ht_inf->ht_supported) goto done; - mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2; + mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; sta_flags = priv->stations[index].sta.station_flags; sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK); switch (mimo_ps_mode) { - case WLAN_HT_CAP_MIMO_PS_STATIC: + case WLAN_HT_CAP_SM_PS_STATIC: sta_flags |= STA_FLG_MIMO_DIS_MSK; break; - case WLAN_HT_CAP_MIMO_PS_DYNAMIC: + case WLAN_HT_CAP_SM_PS_DYNAMIC: sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK; break; - case WLAN_HT_CAP_MIMO_PS_DISABLED: + case WLAN_HT_CAP_SM_PS_DISABLED: break; default: - IWL_WARNING("Invalid MIMO PS mode %d", mimo_ps_mode); + IWL_WARNING("Invalid MIMO PS mode %d\n", mimo_ps_mode); break; } @@ -286,7 +286,7 @@ u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap, /* BCAST station and IBSS stations do not work in HT mode */ if (sta_id != priv->hw_params.bcast_sta_id && - priv->iw_mode != IEEE80211_IF_TYPE_IBSS) + priv->iw_mode != NL80211_IFTYPE_ADHOC) iwl_set_ht_add_station(priv, sta_id, ht_info); spin_unlock_irqrestore(&priv->sta_lock, flags_spin); @@ -817,13 +817,13 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, }; if ((lq->sta_id == 0xFF) && - (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)) + (priv->iw_mode == NL80211_IFTYPE_ADHOC)) return -EINVAL; if (lq->sta_id == 0xFF) lq->sta_id = IWL_AP_ID; - iwl_dump_lq_cmd(priv,lq); + iwl_dump_lq_cmd(priv, lq); if (iwl_is_associated(priv) && priv->assoc_station_added) return iwl_send_cmd(priv, &cmd); @@ -839,7 +839,7 @@ EXPORT_SYMBOL(iwl_send_lq_cmd); * for automatic fallback during transmission. * * NOTE: This sets up a default set of values. These will be replaced later - * if the driver's iwl-4965-rs rate scaling algorithm is used, instead of + * if the driver's iwl-agn-rs rate scaling algorithm is used, instead of * rc80211_simple. * * NOTE: Run REPLY_ADD_STA command to set up station table entry, before @@ -904,7 +904,7 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) if ((is_ap) && (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) && - (priv->iw_mode == IEEE80211_IF_TYPE_STA)) + (priv->iw_mode == NL80211_IFTYPE_STATION)) sta_id = iwl_add_station_flags(priv, addr, is_ap, 0, cur_ht_config); else @@ -938,11 +938,11 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) /* If we are a client station in a BSS network, use the special * AP station entry (that's the only station we communicate with) */ - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: return IWL_AP_ID; /* If we are an AP, then find the station, or use BCAST */ - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: sta_id = iwl_find_station(priv, hdr->addr1); if (sta_id != IWL_INVALID_STATION) return sta_id; @@ -950,7 +950,7 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) /* If this frame is going out to an IBSS network, find the station, * or create a new station table entry */ - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: sta_id = iwl_find_station(priv, hdr->addr1); if (sta_id != IWL_INVALID_STATION) return sta_id; @@ -968,8 +968,13 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); return priv->hw_params.bcast_sta_id; + /* If we are in monitor mode, use BCAST. This is required for + * packet injection. */ + case NL80211_IFTYPE_MONITOR: + return priv->hw_params.bcast_sta_id; + default: - IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode); + IWL_WARNING("Unknown mode of operation: %d\n", priv->iw_mode); return priv->hw_params.bcast_sta_id; } } diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 9b50b1052b09..907a53ebc6e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -63,7 +63,7 @@ static const u16 default_tid_to_tx_fifo[] = { * Does NOT advance any TFD circular buffer read/write indexes * Does NOT free the TFD itself (which is within circular buffer) */ -int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) +static int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) { struct iwl_tfd_frame *bd_tmp = (struct iwl_tfd_frame *)&txq->bd[0]; struct iwl_tfd_frame *bd = &bd_tmp[txq->q.read_ptr]; @@ -115,10 +115,8 @@ int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) } return 0; } -EXPORT_SYMBOL(iwl_hw_txq_free_tfd); - -int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, +static int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, dma_addr_t addr, u16 len) { int index, is_odd; @@ -126,7 +124,7 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, u32 num_tbs = IWL_GET_BITS(*tfd, num_tbs); /* Each TFD can point to a maximum 20 Tx buffers */ - if ((num_tbs >= MAX_NUM_OF_TBS) || (num_tbs < 0)) { + if (num_tbs >= MAX_NUM_OF_TBS) { IWL_ERROR("Error can not send more than %d chunks\n", MAX_NUM_OF_TBS); return -EINVAL; @@ -151,7 +149,6 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, return 0; } -EXPORT_SYMBOL(iwl_hw_txq_attach_buf_to_tfd); /** * iwl_txq_update_write_ptr - Send new write index to hardware @@ -208,11 +205,12 @@ EXPORT_SYMBOL(iwl_txq_update_write_ptr); * Free all buffers. * 0-fill, but do not free "txq" descriptor structure. */ -static void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq) +static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) { + struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; struct pci_dev *dev = priv->pci_dev; - int len; + int i, slots_num, len; if (q->n_bd == 0) return; @@ -227,7 +225,12 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq) len += IWL_MAX_SCAN_SIZE; /* De-alloc array of command/tx buffers */ - pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd); + slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? + TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; + for (i = 0; i < slots_num; i++) + kfree(txq->cmd[i]); + if (txq_id == IWL_CMD_QUEUE_NUM) + kfree(txq->cmd[slots_num]); /* De-alloc circular buffer of TFDs */ if (txq->q.n_bd) @@ -396,13 +399,11 @@ static int iwl_hw_tx_queue_init(struct iwl_priv *priv, /** * iwl_tx_queue_init - Allocate and initialize one tx/cmd queue */ -static int iwl_tx_queue_init(struct iwl_priv *priv, - struct iwl_tx_queue *txq, +static int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, int slots_num, u32 txq_id) { - struct pci_dev *dev = priv->pci_dev; - int len; - int rc = 0; + int i, len; + int ret; /* * Alloc buffer array for commands (Tx or other types of commands). @@ -412,20 +413,25 @@ static int iwl_tx_queue_init(struct iwl_priv *priv, * For normal Tx queues (all other queues), no super-size command * space is needed. */ - len = sizeof(struct iwl_cmd) * slots_num; - if (txq_id == IWL_CMD_QUEUE_NUM) - len += IWL_MAX_SCAN_SIZE; - txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd); - if (!txq->cmd) - return -ENOMEM; + len = sizeof(struct iwl_cmd); + for (i = 0; i <= slots_num; i++) { + if (i == slots_num) { + if (txq_id == IWL_CMD_QUEUE_NUM) + len += IWL_MAX_SCAN_SIZE; + else + continue; + } + + txq->cmd[i] = kmalloc(len, GFP_KERNEL); + if (!txq->cmd[i]) + goto err; + } /* Alloc driver data array and TFD circular buffer */ - rc = iwl_tx_queue_alloc(priv, txq, txq_id); - if (rc) { - pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd); + ret = iwl_tx_queue_alloc(priv, txq, txq_id); + if (ret) + goto err; - return -ENOMEM; - } txq->need_update = 0; /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise @@ -439,6 +445,17 @@ static int iwl_tx_queue_init(struct iwl_priv *priv, iwl_hw_tx_queue_init(priv, txq); return 0; +err: + for (i = 0; i < slots_num; i++) { + kfree(txq->cmd[i]); + txq->cmd[i] = NULL; + } + + if (txq_id == IWL_CMD_QUEUE_NUM) { + kfree(txq->cmd[slots_num]); + txq->cmd[slots_num] = NULL; + } + return -ENOMEM; } /** * iwl_hw_txq_ctx_free - Free TXQ Context @@ -451,14 +468,13 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv) /* Tx queues */ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) - iwl_tx_queue_free(priv, &priv->txq[txq_id]); + iwl_tx_queue_free(priv, txq_id); /* Keep-warm buffer */ iwl_kw_free(priv); } EXPORT_SYMBOL(iwl_hw_txq_ctx_free); - /** * iwl_txq_ctx_reset - Reset TX queue context * Destroys all DMA structures and initialise them again @@ -480,7 +496,7 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) /* Alloc keep-warm buffer */ ret = iwl_kw_alloc(priv); if (ret) { - IWL_ERROR("Keep Warm allocation failed"); + IWL_ERROR("Keep Warm allocation failed\n"); goto error_kw; } spin_lock_irqsave(&priv->lock, flags); @@ -525,6 +541,7 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) error_kw: return ret; } + /** * iwl_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory */ @@ -751,20 +768,19 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl_tfd_frame *tfd; - u32 *control_flags; - int txq_id = skb_get_queue_mapping(skb); - struct iwl_tx_queue *txq = NULL; - struct iwl_queue *q = NULL; + struct iwl_tx_queue *txq; + struct iwl_queue *q; + struct iwl_cmd *out_cmd; + struct iwl_tx_cmd *tx_cmd; + int swq_id, txq_id; dma_addr_t phys_addr; dma_addr_t txcmd_phys; dma_addr_t scratch_phys; - struct iwl_cmd *out_cmd = NULL; - struct iwl_tx_cmd *tx_cmd; u16 len, idx, len_org; u16 seq_number = 0; - u8 id, hdr_len, unicast; - u8 sta_id; __le16 fc; + u8 hdr_len, unicast; + u8 sta_id; u8 wait_write_ptr = 0; u8 tid = 0; u8 *qc = NULL; @@ -777,11 +793,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) goto drop_unlock; } - if (!priv->vif) { - IWL_DEBUG_DROP("Dropping - !priv->vif\n"); - goto drop_unlock; - } - if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) { IWL_ERROR("ERROR: No TX rate available.\n"); @@ -789,7 +800,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) } unicast = !is_multicast_ether_addr(hdr->addr1); - id = 0; fc = hdr->frame_control; @@ -804,16 +814,18 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* drop all data frame if we are not associated */ if (ieee80211_is_data(fc) && - (!iwl_is_associated(priv) || - ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id) || - !priv->assoc_station_added)) { + (priv->iw_mode != NL80211_IFTYPE_MONITOR || + !(info->flags & IEEE80211_TX_CTL_INJECTED)) && /* packet injection */ + (!iwl_is_associated(priv) || + ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id) || + !priv->assoc_station_added)) { IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n"); goto drop_unlock; } spin_unlock_irqrestore(&priv->lock, flags); - hdr_len = ieee80211_get_hdrlen(le16_to_cpu(fc)); + hdr_len = ieee80211_hdrlen(fc); /* Find (or create) index into station table for destination station */ sta_id = iwl_get_sta_id(priv, hdr); @@ -827,14 +839,16 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) IWL_DEBUG_TX("station Id %d\n", sta_id); + swq_id = skb_get_queue_mapping(skb); + txq_id = swq_id; if (ieee80211_is_data_qos(fc)) { qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & 0xf; - seq_number = priv->stations[sta_id].tid[tid].seq_number & - IEEE80211_SCTL_SEQ; - hdr->seq_ctrl = cpu_to_le16(seq_number) | - (hdr->seq_ctrl & - __constant_cpu_to_le16(IEEE80211_SCTL_FRAG)); + tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; + seq_number = priv->stations[sta_id].tid[tid].seq_number; + seq_number &= IEEE80211_SCTL_SEQ; + hdr->seq_ctrl = hdr->seq_ctrl & + __constant_cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(seq_number); seq_number += 0x10; /* aggregation is on for this <sta,tid> */ if (info->flags & IEEE80211_TX_CTL_AMPDU) @@ -851,7 +865,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Set up first empty TFD within this queue's circular TFD buffer */ tfd = &txq->bd[q->write_ptr]; memset(tfd, 0, sizeof(*tfd)); - control_flags = (u32 *) tfd; idx = get_cmd_index(q, q->write_ptr, 0); /* Set up driver data for this TFD */ @@ -859,7 +872,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) txq->txb[q->write_ptr].skb[0] = skb; /* Set up first empty entry in queue's array of Tx/cmd buffers */ - out_cmd = &txq->cmd[idx]; + out_cmd = txq->cmd[idx]; tx_cmd = &out_cmd->cmd.tx; memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd)); @@ -899,14 +912,15 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Physical address of this Tx command's header (not MAC header!), * within command buffer array. */ - txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx + - offsetof(struct iwl_cmd, hdr); + txcmd_phys = pci_map_single(priv->pci_dev, out_cmd, + sizeof(struct iwl_cmd), PCI_DMA_TODEVICE); + txcmd_phys += offsetof(struct iwl_cmd, hdr); /* Add buffer containing Tx command and MAC(!) header to TFD's * first entry */ iwl_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len); - if (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT)) + if (info->control.hw_key) iwl_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id); /* Set up TFD's 2nd entry to point directly to remainder of skb, @@ -962,16 +976,15 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (ret) return ret; - if ((iwl_queue_space(q) < q->high_mark) - && priv->mac80211_registered) { + if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { if (wait_write_ptr) { spin_lock_irqsave(&priv->lock, flags); txq->need_update = 1; iwl_txq_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->lock, flags); + } else { + ieee80211_stop_queue(priv->hw, swq_id); } - - ieee80211_stop_queue(priv->hw, skb_get_queue_mapping(skb)); } return 0; @@ -999,13 +1012,12 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; struct iwl_queue *q = &txq->q; struct iwl_tfd_frame *tfd; - u32 *control_flags; struct iwl_cmd *out_cmd; - u32 idx; - u16 fix_size; dma_addr_t phys_addr; - int ret; unsigned long flags; + int len, ret; + u32 idx; + u16 fix_size; cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); @@ -1031,10 +1043,9 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) tfd = &txq->bd[q->write_ptr]; memset(tfd, 0, sizeof(*tfd)); - control_flags = (u32 *) tfd; idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE); - out_cmd = &txq->cmd[idx]; + out_cmd = txq->cmd[idx]; out_cmd->hdr.cmd = cmd->id; memcpy(&out_cmd->meta, &cmd->meta, sizeof(cmd->meta)); @@ -1047,18 +1058,34 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) | INDEX_TO_SEQ(q->write_ptr)); if (out_cmd->meta.flags & CMD_SIZE_HUGE) - out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME); - - phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx + - offsetof(struct iwl_cmd, hdr); + out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; + len = (idx == TFD_CMD_SLOTS) ? + IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd); + phys_addr = pci_map_single(priv->pci_dev, out_cmd, len, + PCI_DMA_TODEVICE); + phys_addr += offsetof(struct iwl_cmd, hdr); iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size); - IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, " - "%d bytes at %d[%d]:%d\n", - get_cmd_string(out_cmd->hdr.cmd), - out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), - fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM); - +#ifdef CONFIG_IWLWIFI_DEBUG + switch (out_cmd->hdr.cmd) { + case REPLY_TX_LINK_QUALITY_CMD: + case SENSITIVITY_CMD: + IWL_DEBUG_HC_DUMP("Sending command %s (#%x), seq: 0x%04X, " + "%d bytes at %d[%d]:%d\n", + get_cmd_string(out_cmd->hdr.cmd), + out_cmd->hdr.cmd, + le16_to_cpu(out_cmd->hdr.sequence), fix_size, + q->write_ptr, idx, IWL_CMD_QUEUE_NUM); + break; + default: + IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, " + "%d bytes at %d[%d]:%d\n", + get_cmd_string(out_cmd->hdr.cmd), + out_cmd->hdr.cmd, + le16_to_cpu(out_cmd->hdr.sequence), fix_size, + q->write_ptr, idx, IWL_CMD_QUEUE_NUM); + } +#endif txq->need_update = 1; /* Set up entry in queue's byte count circular buffer */ @@ -1115,6 +1142,9 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) { struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; + struct iwl_tfd_frame *bd = &txq->bd[index]; + dma_addr_t dma_addr; + int is_odd, buf_len; int nfreed = 0; if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { @@ -1132,6 +1162,19 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) q->write_ptr, q->read_ptr); queue_work(priv->workqueue, &priv->restart); } + is_odd = (index/2) & 0x1; + if (is_odd) { + dma_addr = IWL_GET_BITS(bd->pa[index], tb2_addr_lo16) | + (IWL_GET_BITS(bd->pa[index], + tb2_addr_hi20) << 16); + buf_len = IWL_GET_BITS(bd->pa[index], tb2_len); + } else { + dma_addr = le32_to_cpu(bd->pa[index].tb1_addr); + buf_len = IWL_GET_BITS(bd->pa[index], tb1_len); + } + + pci_unmap_single(priv->pci_dev, dma_addr, buf_len, + PCI_DMA_TODEVICE); nfreed++; } } @@ -1150,20 +1193,19 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) u16 sequence = le16_to_cpu(pkt->hdr.sequence); int txq_id = SEQ_TO_QUEUE(sequence); int index = SEQ_TO_INDEX(sequence); - int huge = sequence & SEQ_HUGE_FRAME; int cmd_index; + bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); struct iwl_cmd *cmd; /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced * in the queue management code. */ - if (txq_id != IWL_CMD_QUEUE_NUM) - IWL_ERROR("Error wrong command queue %d command id 0x%X\n", - txq_id, pkt->hdr.cmd); - BUG_ON(txq_id != IWL_CMD_QUEUE_NUM); + if (WARN(txq_id != IWL_CMD_QUEUE_NUM, + "wrong command queue %d, command id 0x%X\n", txq_id, pkt->hdr.cmd)) + return; cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); - cmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; + cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; /* Input error checking is done when commands are added to queue. */ if (cmd->meta.flags & CMD_WANT_SKB) { @@ -1391,7 +1433,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, /* For each frame attempted in aggregation, * update driver's record of tx frame's status. */ for (i = 0; i < agg->frame_count ; i++) { - ack = bitmap & (1 << i); + ack = bitmap & (1ULL << i); successes += !!ack; IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n", ack? "ACK":"NACK", i, (agg->start_idx + i) & 0xff, @@ -1435,7 +1477,7 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); if (scd_flow >= priv->hw_params.max_txq_num) { - IWL_ERROR("BUG_ON scd_flow is bigger than number of queues"); + IWL_ERROR("BUG_ON scd_flow is bigger than number of queues\n"); return; } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 4a22d3fba75b..d15a2c997954 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -29,7 +29,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/dma-mapping.h> @@ -275,10 +274,8 @@ static int iwl3945_tx_queue_alloc(struct iwl3945_priv *priv, return 0; error: - if (txq->txb) { - kfree(txq->txb); - txq->txb = NULL; - } + kfree(txq->txb); + txq->txb = NULL; return -ENOMEM; } @@ -365,10 +362,8 @@ void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *t txq->q.n_bd, txq->bd, txq->q.dma_addr); /* De-alloc array of per-TFD driver data */ - if (txq->txb) { - kfree(txq->txb); - txq->txb = NULL; - } + kfree(txq->txb); + txq->txb = NULL; /* 0-fill queue descriptor structure */ memset(txq, 0, sizeof(*txq)); @@ -1165,7 +1160,7 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv) /* If we have set the ASSOC_MSK and we are in BSS mode then * add the IWL_AP_ID to the station rate table */ if (iwl3945_is_associated(priv) && - (priv->iw_mode == IEEE80211_IF_TYPE_STA)) + (priv->iw_mode == NL80211_IFTYPE_STATION)) if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr, 1, 0) == IWL_INVALID_STATION) { IWL_ERROR("Error adding AP address for transmit.\n"); @@ -1452,8 +1447,8 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv, { if (!iwl3945_is_associated(priv) || !priv->ibss_beacon || - ((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) && - (priv->iw_mode != IEEE80211_IF_TYPE_AP))) + ((priv->iw_mode != NL80211_IFTYPE_ADHOC) && + (priv->iw_mode != NL80211_IFTYPE_AP))) return 0; if (priv->ibss_beacon->len > left) @@ -1562,7 +1557,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv) BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE); if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { - IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp); + IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp); return -ENOENT; } @@ -1587,7 +1582,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv) } if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) { - IWL_ERROR("Time out reading EEPROM[%d]", addr); + IWL_ERROR("Time out reading EEPROM[%d]\n", addr); return -ETIMEDOUT; } e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); @@ -1751,14 +1746,14 @@ static void iwl3945_reset_qos(struct iwl3945_priv *priv) spin_lock_irqsave(&priv->lock, flags); priv->qos_data.qos_active = 0; - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) { + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) { if (priv->qos_data.qos_enable) priv->qos_data.qos_active = 1; if (!(priv->active_rate & 0xfff0)) { cw_min = 31; is_legacy = 1; } - } else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + } else if (priv->iw_mode == NL80211_IFTYPE_AP) { if (priv->qos_data.qos_enable) priv->qos_data.qos_active = 1; } else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) { @@ -2125,7 +2120,7 @@ static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv) beacon_int = priv->beacon_int; spin_unlock_irqrestore(&priv->lock, flags); - if (priv->iw_mode == IEEE80211_IF_TYPE_STA) { + if (priv->iw_mode == NL80211_IFTYPE_STATION) { if (beacon_int == 0) { priv->rxon_timing.beacon_interval = cpu_to_le16(100); priv->rxon_timing.beacon_init_val = cpu_to_le32(102400); @@ -2161,7 +2156,7 @@ static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv) static int iwl3945_scan_initiate(struct iwl3945_priv *priv) { - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode == NL80211_IFTYPE_AP) { IWL_ERROR("APs don't scan.\n"); return 0; } @@ -2223,7 +2218,7 @@ static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; @@ -2242,23 +2237,23 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv) memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon)); switch (priv->iw_mode) { - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP; break; - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS; priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; break; - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS; priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK; priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; break; - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_MONITOR: priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER; priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK | RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK; @@ -2287,7 +2282,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv) * in some case A channels are all non IBSS * in this case force B/G channel */ - if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && + if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && !(is_channel_ibss(ch_info))) ch_info = &priv->channel_info[0]; @@ -2307,7 +2302,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv) static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode) { - if (mode == IEEE80211_IF_TYPE_IBSS) { + if (mode == NL80211_IFTYPE_ADHOC) { const struct iwl3945_channel_info *ch_info; ch_info = iwl3945_get_channel_info(priv, @@ -2474,11 +2469,11 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h /* If we are a client station in a BSS network, use the special * AP station entry (that's the only station we communicate with) */ - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: return IWL_AP_ID; /* If we are an AP, then find the station, or use BCAST */ - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: sta_id = iwl3945_hw_find_station(priv, hdr->addr1); if (sta_id != IWL_INVALID_STATION) return sta_id; @@ -2486,7 +2481,7 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h /* If this frame is going out to an IBSS network, find the station, * or create a new station table entry */ - case IEEE80211_IF_TYPE_IBSS: { + case NL80211_IFTYPE_ADHOC: { DECLARE_MAC_BUF(mac); /* Create new station table entry */ @@ -2507,11 +2502,11 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h } /* If we are in monitor mode, use BCAST. This is required for * packet injection. */ - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_MONITOR: return priv->hw_setting.bcast_sta_id; default: - IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode); + IWL_WARNING("Unknown mode of operation: %d\n", priv->iw_mode); return priv->hw_setting.bcast_sta_id; } } @@ -2570,16 +2565,16 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) /* drop all data frame if we are not associated */ if (ieee80211_is_data(fc) && - (priv->iw_mode != IEEE80211_IF_TYPE_MNTR) && /* packet injection */ + (priv->iw_mode != NL80211_IFTYPE_MONITOR) && /* packet injection */ (!iwl3945_is_associated(priv) || - ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id))) { + ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) { IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n"); goto drop_unlock; } spin_unlock_irqrestore(&priv->lock, flags); - hdr_len = ieee80211_get_hdrlen(le16_to_cpu(fc)); + hdr_len = ieee80211_hdrlen(fc); /* Find (or create) index into station table for destination station */ sta_id = iwl3945_get_sta_id(priv, hdr); @@ -2595,7 +2590,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) if (ieee80211_is_data_qos(fc)) { qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & 0xf; + tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; seq_number = priv->stations[sta_id].tid[tid].seq_number & IEEE80211_SCTL_SEQ; hdr->seq_ctrl = cpu_to_le16(seq_number) | @@ -2667,7 +2662,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) * first entry */ iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len); - if (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT)) + if (info->control.hw_key) iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, 0); /* Set up TFD's 2nd entry to point directly to remainder of skb, @@ -2703,9 +2698,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) if (!ieee80211_has_morefrags(hdr->frame_control)) { txq->need_update = 1; - if (qc) { + if (qc) priv->stations[sta_id].tid[tid].seq_number = seq_number; - } } else { wait_write_ptr = 1; txq->need_update = 0; @@ -2715,7 +2709,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) sizeof(out_cmd->cmd.tx)); iwl3945_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr, - ieee80211_get_hdrlen(le16_to_cpu(fc))); + ieee80211_hdrlen(fc)); /* Tell device the write index *just past* this latest filled TFD */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); @@ -2812,7 +2806,7 @@ static void iwl3945_radio_kill_sw(struct iwl3945_priv *priv, int disable_radio) if (disable_radio) { iwl3945_scan_cancel(priv); /* FIXME: This is a workaround for AP */ - if (priv->iw_mode != IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode != NL80211_IFTYPE_AP) { spin_lock_irqsave(&priv->lock, flags); iwl3945_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_SW_BIT_RFKILL); @@ -3167,7 +3161,7 @@ static void iwl3945_rx_beacon_notif(struct iwl3945_priv *priv, le32_to_cpu(beacon->low_tsf), rate); #endif - if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && + if ((priv->iw_mode == NL80211_IFTYPE_AP) && (!test_bit(STATUS_EXIT_PENDING, &priv->status))) queue_work(priv->workqueue, &priv->beacon_update); } @@ -3813,7 +3807,7 @@ int iwl3945_calc_db_from_ratio(int sig_ratio) /* 100:1 or higher, divide by 10 and use table, * add 20 dB to make up for divide by 10 */ if (sig_ratio >= 100) - return (20 + (int)ratio2dB[sig_ratio/10]); + return 20 + (int)ratio2dB[sig_ratio/10]; /* We shouldn't see this */ if (sig_ratio < 1) @@ -4788,8 +4782,11 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv) /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after * sending probe req. This should be set long enough to hear probe responses * from more than one AP. */ -#define IWL_ACTIVE_DWELL_TIME_24 (20) /* all times in msec */ -#define IWL_ACTIVE_DWELL_TIME_52 (10) +#define IWL_ACTIVE_DWELL_TIME_24 (30) /* all times in msec */ +#define IWL_ACTIVE_DWELL_TIME_52 (20) + +#define IWL_ACTIVE_DWELL_FACTOR_24GHZ (3) +#define IWL_ACTIVE_DWELL_FACTOR_52GHZ (2) /* For faster active scanning, scan will move to the next channel if fewer than * PLCP_QUIET_THRESH packets are heard on this channel within @@ -4798,7 +4795,7 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv) * no other traffic). * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */ #define IWL_PLCP_QUIET_THRESH __constant_cpu_to_le16(1) /* packets */ -#define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(5) /* msec */ +#define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(10) /* msec */ /* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel. * Must be set longer than active dwell time. @@ -4808,19 +4805,23 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv) #define IWL_PASSIVE_DWELL_BASE (100) #define IWL_CHANNEL_TUNE_TIME 5 +#define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1)))) + static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv, - enum ieee80211_band band) + enum ieee80211_band band, + u8 n_probes) { if (band == IEEE80211_BAND_5GHZ) - return IWL_ACTIVE_DWELL_TIME_52; + return IWL_ACTIVE_DWELL_TIME_52 + + IWL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1); else - return IWL_ACTIVE_DWELL_TIME_24; + return IWL_ACTIVE_DWELL_TIME_24 + + IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); } static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, enum ieee80211_band band) { - u16 active = iwl3945_get_active_dwell_time(priv, band); u16 passive = (band == IEEE80211_BAND_2GHZ) ? IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; @@ -4835,15 +4836,12 @@ static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; } - if (passive <= active) - passive = active + 1; - return passive; } static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, enum ieee80211_band band, - u8 is_active, u8 direct_mask, + u8 is_active, u8 n_probes, struct iwl3945_scan_channel *scan_ch) { const struct ieee80211_channel *channels = NULL; @@ -4859,9 +4857,12 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, channels = sband->channels; - active_dwell = iwl3945_get_active_dwell_time(priv, band); + active_dwell = iwl3945_get_active_dwell_time(priv, band, n_probes); passive_dwell = iwl3945_get_passive_dwell_time(priv, band); + if (passive_dwell <= active_dwell) + passive_dwell = active_dwell + 1; + for (i = 0, added = 0; i < sband->n_channels; i++) { if (channels[i].flags & IEEE80211_CHAN_DISABLED) continue; @@ -4881,8 +4882,8 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, else scan_ch->type = 1; /* active */ - if (scan_ch->type & 1) - scan_ch->type |= (direct_mask << 1); + if ((scan_ch->type & 1) && n_probes) + scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); scan_ch->active_dwell = cpu_to_le16(active_dwell); scan_ch->passive_dwell = cpu_to_le16(passive_dwell); @@ -5088,7 +5089,7 @@ static void iwl3945_dealloc_ucode_pci(struct iwl3945_priv *priv) * iwl3945_verify_inst_full - verify runtime uCode image in card vs. host, * looking at all data. */ -static int iwl3945_verify_inst_full(struct iwl3945_priv *priv, __le32 * image, u32 len) +static int iwl3945_verify_inst_full(struct iwl3945_priv *priv, __le32 *image, u32 len) { u32 val; u32 save_len = len; @@ -5237,7 +5238,7 @@ static int iwl3945_verify_bsm(struct iwl3945_priv *priv) val = iwl3945_read_prph(priv, BSM_WR_DWCOUNT_REG); for (reg = BSM_SRAM_LOWER_BOUND; reg < BSM_SRAM_LOWER_BOUND + len; - reg += sizeof(u32), image ++) { + reg += sizeof(u32), image++) { val = iwl3945_read_prph(priv, reg); if (val != le32_to_cpu(*image)) { IWL_ERROR("BSM uCode verification failed at " @@ -6058,7 +6059,7 @@ static void iwl3945_bg_set_monitor(struct work_struct *work) if (!iwl3945_is_ready(priv)) IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n"); else - if (iwl3945_set_mode(priv, IEEE80211_IF_TYPE_MNTR) != 0) + if (iwl3945_set_mode(priv, NL80211_IFTYPE_MONITOR) != 0) IWL_ERROR("iwl3945_set_mode() failed\n"); mutex_unlock(&priv->mutex); @@ -6099,7 +6100,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) int rc = 0; struct iwl3945_scan_cmd *scan; struct ieee80211_conf *conf = NULL; - u8 direct_mask; + u8 n_probes = 2; enum ieee80211_band band; conf = ieee80211_get_hw_conf(priv->hw); @@ -6207,7 +6208,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) scan->direct_scan[0].len = priv->direct_ssid_len; memcpy(scan->direct_scan[0].ssid, priv->direct_ssid, priv->direct_ssid_len); - direct_mask = 1; + n_probes++; } else if (!iwl3945_is_associated(priv) && priv->essid_len) { IWL_DEBUG_SCAN ("Kicking off one direct scan for '%s' when not associated\n", @@ -6215,11 +6216,9 @@ static void iwl3945_bg_request_scan(struct work_struct *data) scan->direct_scan[0].id = WLAN_EID_SSID; scan->direct_scan[0].len = priv->essid_len; memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len); - direct_mask = 1; - } else { + n_probes++; + } else IWL_DEBUG_SCAN("Kicking off one indirect scan.\n"); - direct_mask = 0; - } /* We don't build a direct scan probe request; the uCode will do * that based on the direct_mask added to each channel entry */ @@ -6249,21 +6248,13 @@ static void iwl3945_bg_request_scan(struct work_struct *data) /* select Rx antennas */ scan->flags |= iwl3945_get_antenna_flags(priv); - if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) + if (priv->iw_mode == NL80211_IFTYPE_MONITOR) scan->filter_flags = RXON_FILTER_PROMISC_MSK; - if (direct_mask) - scan->channel_count = - iwl3945_get_channels_for_scan( - priv, band, 1, /* active */ - direct_mask, - (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); - else - scan->channel_count = - iwl3945_get_channels_for_scan( - priv, band, 0, /* passive */ - direct_mask, - (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + scan->channel_count = + iwl3945_get_channels_for_scan(priv, band, 1, /* active */ + n_probes, + (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); cmd.len += le16_to_cpu(scan->tx_cmd.len) + scan->channel_count * sizeof(struct iwl3945_scan_channel); @@ -6326,17 +6317,14 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data) #define IWL_DELAY_NEXT_SCAN (HZ*2) -static void iwl3945_bg_post_associate(struct work_struct *data) +static void iwl3945_post_associate(struct iwl3945_priv *priv) { - struct iwl3945_priv *priv = container_of(data, struct iwl3945_priv, - post_associate.work); - int rc = 0; struct ieee80211_conf *conf = NULL; DECLARE_MAC_BUF(mac); - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { - IWL_ERROR("%s Should not be called in AP mode\n", __FUNCTION__); + if (priv->iw_mode == NL80211_IFTYPE_AP) { + IWL_ERROR("%s Should not be called in AP mode\n", __func__); return; } @@ -6348,12 +6336,9 @@ static void iwl3945_bg_post_associate(struct work_struct *data) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - mutex_lock(&priv->mutex); - - if (!priv->vif || !priv->is_open) { - mutex_unlock(&priv->mutex); + if (!priv->vif || !priv->is_open) return; - } + iwl3945_scan_cancel_timeout(priv, 200); conf = ieee80211_get_hw_conf(priv->hw); @@ -6387,7 +6372,7 @@ static void iwl3945_bg_post_associate(struct work_struct *data) else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } @@ -6395,11 +6380,11 @@ static void iwl3945_bg_post_associate(struct work_struct *data) iwl3945_commit_rxon(priv); switch (priv->iw_mode) { - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: iwl3945_rate_scale_init(priv->hw, IWL_AP_ID); break; - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: /* clear out the station table */ iwl3945_clear_stations_table(priv); @@ -6417,7 +6402,7 @@ static void iwl3945_bg_post_associate(struct work_struct *data) default: IWL_ERROR("%s Should not be called in %d mode\n", - __FUNCTION__, priv->iw_mode); + __func__, priv->iw_mode); break; } @@ -6425,7 +6410,6 @@ static void iwl3945_bg_post_associate(struct work_struct *data) /* we have just associated, don't start scan too early */ priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; - mutex_unlock(&priv->mutex); } static void iwl3945_bg_abort_scan(struct work_struct *work) @@ -6573,7 +6557,6 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw) */ mutex_lock(&priv->mutex); iwl3945_scan_cancel_timeout(priv, 100); - cancel_delayed_work(&priv->post_associate); mutex_unlock(&priv->mutex); } @@ -6594,12 +6577,6 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) IWL_DEBUG_MAC80211("enter\n"); - if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { - IWL_DEBUG_MAC80211("leave - monitor\n"); - dev_kfree_skb_any(skb); - return 0; - } - IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); @@ -6662,8 +6639,6 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value); - priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP); - if (!iwl3945_is_ready(priv)) { IWL_DEBUG_MAC80211("leave - not ready\n"); ret = -EIO; @@ -6779,7 +6754,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } @@ -6816,7 +6791,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, } /* handle this temporarily here */ - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS && + if (priv->iw_mode == NL80211_IFTYPE_ADHOC && conf->changed & IEEE80211_IFCC_BEACON) { struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); if (!beacon) @@ -6828,7 +6803,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, /* XXX: this MUST use conf->mac_addr */ - if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && + if ((priv->iw_mode == NL80211_IFTYPE_AP) && (!conf->ssid_len)) { IWL_DEBUG_MAC80211 ("Leaving in AP mode because HostAPD is not ready.\n"); @@ -6851,7 +6826,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { */ - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode == NL80211_IFTYPE_AP) { if (!conf->bssid) { conf->bssid = priv->mac_addr; memcpy(priv->bssid, priv->mac_addr, ETH_ALEN); @@ -6886,11 +6861,11 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, * to verify) - jpk */ memcpy(priv->bssid, conf->bssid, ETH_ALEN); - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) + if (priv->iw_mode == NL80211_IFTYPE_AP) iwl3945_config_ap(priv); else { rc = iwl3945_commit_rxon(priv); - if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc) + if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) iwl3945_add_station(priv, priv->active_rxon.bssid_addr, 1, 0); } @@ -6926,7 +6901,7 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw, if (changed_flags & (*total_flags) & FIF_OTHER_BSS) { IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n", - IEEE80211_IF_TYPE_MNTR, + NL80211_IFTYPE_MONITOR, changed_flags, *total_flags); /* queue work 'cuz mac80211 is holding a lock which * prevents us from issuing (synchronous) f/w cmds */ @@ -6947,7 +6922,6 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, if (iwl3945_is_ready_rf(priv)) { iwl3945_scan_cancel_timeout(priv, 100); - cancel_delayed_work(&priv->post_associate); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); } @@ -6962,6 +6936,63 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211("leave\n"); } +#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) + +static void iwl3945_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes) +{ + struct iwl3945_priv *priv = hw->priv; + + IWL_DEBUG_MAC80211("changes = 0x%X\n", changes); + + if (changes & BSS_CHANGED_ERP_PREAMBLE) { + IWL_DEBUG_MAC80211("ERP_PREAMBLE %d\n", + bss_conf->use_short_preamble); + if (bss_conf->use_short_preamble) + priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + else + priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + } + + if (changes & BSS_CHANGED_ERP_CTS_PROT) { + IWL_DEBUG_MAC80211("ERP_CTS %d\n", bss_conf->use_cts_prot); + if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) + priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; + else + priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; + } + + if (changes & BSS_CHANGED_ASSOC) { + IWL_DEBUG_MAC80211("ASSOC %d\n", bss_conf->assoc); + /* This should never happen as this function should + * never be called from interrupt context. */ + if (WARN_ON_ONCE(in_interrupt())) + return; + if (bss_conf->assoc) { + priv->assoc_id = bss_conf->aid; + priv->beacon_int = bss_conf->beacon_int; + priv->timestamp0 = bss_conf->timestamp & 0xFFFFFFFF; + priv->timestamp1 = (bss_conf->timestamp >> 32) & + 0xFFFFFFFF; + priv->assoc_capability = bss_conf->assoc_capability; + priv->next_scan_jiffies = jiffies + + IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; + mutex_lock(&priv->mutex); + iwl3945_post_associate(priv); + mutex_unlock(&priv->mutex); + } else { + priv->assoc_id = 0; + IWL_DEBUG_MAC80211("DISASSOC %d\n", bss_conf->assoc); + } + } else if (changes && iwl3945_is_associated(priv) && priv->assoc_id) { + IWL_DEBUG_MAC80211("Associated Changes %d\n", changes); + iwl3945_send_rxon_assoc(priv); + } + +} + static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) { int rc = 0; @@ -6979,7 +7010,7 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) goto out_unlock; } - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { /* APs don't scan */ + if (priv->iw_mode == NL80211_IFTYPE_AP) { /* APs don't scan */ rc = -EIO; IWL_ERROR("ERROR: APs don't scan\n"); goto out_unlock; @@ -7121,7 +7152,7 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, spin_unlock_irqrestore(&priv->lock, flags); mutex_lock(&priv->mutex); - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) + if (priv->iw_mode == NL80211_IFTYPE_AP) iwl3945_activate_qos(priv, 1); else if (priv->assoc_id && iwl3945_is_associated(priv)) iwl3945_activate_qos(priv, 0); @@ -7194,8 +7225,6 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) iwl3945_reset_qos(priv); - cancel_delayed_work(&priv->post_associate); - spin_lock_irqsave(&priv->lock, flags); priv->assoc_id = 0; priv->assoc_capability = 0; @@ -7210,7 +7239,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) priv->beacon_int = priv->hw->conf.beacon_int; priv->timestamp1 = 0; priv->timestamp0 = 0; - if ((priv->iw_mode == IEEE80211_IF_TYPE_STA)) + if ((priv->iw_mode == NL80211_IFTYPE_STATION)) priv->beacon_int = 0; spin_unlock_irqrestore(&priv->lock, flags); @@ -7224,14 +7253,14 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) /* we are restarting association process * clear RXON_FILTER_ASSOC_MSK bit */ - if (priv->iw_mode != IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode != NL80211_IFTYPE_AP) { iwl3945_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); } /* Per mac80211.h: This is only used in IBSS mode... */ - if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) { + if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { IWL_DEBUG_MAC80211("leave - not in IBSS\n"); mutex_unlock(&priv->mutex); @@ -7260,7 +7289,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk return -EIO; } - if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) { + if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { IWL_DEBUG_MAC80211("leave - not IBSS\n"); mutex_unlock(&priv->mutex); return -EIO; @@ -7280,7 +7309,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk iwl3945_reset_qos(priv); - queue_work(priv->workqueue, &priv->post_associate.work); + iwl3945_post_associate(priv); mutex_unlock(&priv->mutex); @@ -7341,15 +7370,6 @@ static ssize_t show_temperature(struct device *d, static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); -static ssize_t show_rs_window(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct iwl3945_priv *priv = d->driver_data; - return iwl3945_fill_rs_info(priv->hw, buf, IWL_AP_ID); -} -static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL); - static ssize_t show_tx_power(struct device *d, struct device_attribute *attr, char *buf) { @@ -7456,7 +7476,7 @@ static ssize_t show_measurement(struct device *d, struct iwl3945_priv *priv = dev_get_drvdata(d); struct iwl3945_spectrum_notification measure_report; u32 size = sizeof(measure_report), len = 0, ofs = 0; - u8 *data = (u8 *) & measure_report; + u8 *data = (u8 *)&measure_report; unsigned long flags; spin_lock_irqsave(&priv->lock, flags); @@ -7627,7 +7647,7 @@ static ssize_t show_power_level(struct device *d, else p += sprintf(p, " \n"); - return (p - buf + 1); + return p - buf + 1; } @@ -7649,7 +7669,7 @@ static ssize_t show_statistics(struct device *d, struct iwl3945_priv *priv = dev_get_drvdata(d); u32 size = sizeof(struct iwl3945_notif_statistics); u32 len = 0, ofs = 0; - u8 *data = (u8 *) & priv->statistics; + u8 *data = (u8 *)&priv->statistics; int rc = 0; if (!iwl3945_is_alive(priv)) @@ -7779,7 +7799,6 @@ static void iwl3945_setup_deferred_work(struct iwl3945_priv *priv) INIT_WORK(&priv->rf_kill, iwl3945_bg_rf_kill); INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); INIT_WORK(&priv->set_monitor, iwl3945_bg_set_monitor); - INIT_DELAYED_WORK(&priv->post_associate, iwl3945_bg_post_associate); INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); INIT_DELAYED_WORK(&priv->scan_check, iwl3945_bg_scan_check); @@ -7797,7 +7816,6 @@ static void iwl3945_cancel_deferred_work(struct iwl3945_priv *priv) cancel_delayed_work_sync(&priv->init_alive_start); cancel_delayed_work(&priv->scan_check); cancel_delayed_work(&priv->alive_start); - cancel_delayed_work(&priv->post_associate); cancel_work_sync(&priv->beacon_update); } @@ -7813,7 +7831,6 @@ static struct attribute *iwl3945_sysfs_entries[] = { #endif &dev_attr_power_level.attr, &dev_attr_retry_rate.attr, - &dev_attr_rs_window.attr, &dev_attr_statistics.attr, &dev_attr_status.attr, &dev_attr_temperature.attr, @@ -7842,6 +7859,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { .conf_tx = iwl3945_mac_conf_tx, .get_tsf = iwl3945_mac_get_tsf, .reset_tsf = iwl3945_mac_reset_tsf, + .bss_info_changed = iwl3945_bss_info_changed, .hw_scan = iwl3945_mac_hw_scan }; @@ -7880,6 +7898,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e SET_IEEE80211_DEV(hw, &pdev->dev); hw->rate_control_algorithm = "iwl-3945-rs"; + hw->sta_data_size = sizeof(struct iwl3945_sta_priv); IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); priv = hw->priv; @@ -7899,10 +7918,14 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->ibss_beacon = NULL; /* Tell mac80211 our characteristics */ - hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE | - IEEE80211_HW_SIGNAL_DBM | + hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + /* 4 EDCA QOS priorities */ hw->queues = 4; @@ -7964,7 +7987,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e IWL_DEBUG_INFO("Radio disabled.\n"); } - priv->iw_mode = IEEE80211_IF_TYPE_STA; + priv->iw_mode = NL80211_IFTYPE_STATION; printk(KERN_INFO DRV_NAME ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name); @@ -8004,16 +8027,16 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* nic init */ iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS, - CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); - - iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - err = iwl3945_poll_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); - if (err < 0) { - IWL_DEBUG_INFO("Failed to init the card\n"); + CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); + + iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + err = iwl3945_poll_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); + if (err < 0) { + IWL_DEBUG_INFO("Failed to init the card\n"); goto out_remove_sysfs; - } + } /* Read the EEPROM */ err = iwl3945_eeprom_init(priv); if (err) { @@ -8115,9 +8138,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) iwl3945_unset_hw_setting(priv); iwl3945_clear_stations_table(priv); - if (priv->mac80211_registered) { + if (priv->mac80211_registered) ieee80211_unregister_hw(priv->hw); - } /*netif_stop_queue(dev); */ flush_workqueue(priv->workqueue); @@ -8345,6 +8367,8 @@ static void __exit iwl3945_exit(void) iwl3945_rate_control_unregister(); } +MODULE_FIRMWARE("iwlwifi-3945" IWL3945_UCODE_API ".ucode"); + module_param_named(antenna, iwl3945_param_antenna, int, 0444); MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); module_param_named(disable, iwl3945_param_disable, int, 0444); |