summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2008-10-16 02:16:07 +0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-10-16 02:16:07 +0400
commit2502991560dc8244dbe10e48473d85722c1e2ec1 (patch)
tree63b1f3be2ed56ff06f1e8db709e4ce85d69c3add /drivers/net/wireless/iwlwifi
parent7e69a8c4d06b7ecb874f571e82b715a9f79bc3c4 (diff)
parenta9ff8f6462635c8d9f8d64b7b10ddcea8404d77b (diff)
downloadlinux-2502991560dc8244dbe10e48473d85722c1e2ec1.tar.xz
Merge branch 'fixes' into for-linus
Conflicts: arch/arm/mach-versatile/core.c
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-debug.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-io.h24
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.c200
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.h9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c205
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-hw.h13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000-hw.h7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c71
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c331
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.h29
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c275
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-calib.c75
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h24
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c136
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h25
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-csr.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h107
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fh.h9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.h22
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c102
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.h8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c163
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c41
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c31
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c65
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c250
30 files changed, 1007 insertions, 1266 deletions
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-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 3f51f3635344..7ca5627cc078 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -520,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:
@@ -531,99 +531,6 @@ 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)
@@ -657,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;
@@ -684,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 =
@@ -696,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]: "
@@ -771,100 +681,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
priv->last_rx_noise = rx_status.noise;
}
- if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
- iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status);
- return;
- }
-
- 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,
@@ -990,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;
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 23fed3298962..9838de5f4369 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -399,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);
@@ -410,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
@@ -1607,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;
@@ -1648,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)
{
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 b08036a9d894..f6003e7996af 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -209,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
@@ -445,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;
@@ -511,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,
@@ -832,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;
}
@@ -1614,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-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 90a2b6dee7c0..93944de923ca 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -35,8 +35,6 @@
#include <linux/workqueue.h>
-#include "../net/mac80211/rate.h"
-
#include "iwl-dev.h"
#include "iwl-sta.h"
#include "iwl-core.h"
@@ -163,12 +161,15 @@ struct iwl_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 iwl_lq_sta *lq_sta, u32 rate_n_flags);
@@ -354,17 +355,11 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid)
static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
struct iwl_lq_sta *lq_data, u8 tid,
- struct sta_info *sta)
+ 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,7 +368,7 @@ 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 iwl_lq_sta *lq_data,
- struct sta_info *sta)
+ struct ieee80211_sta *sta)
{
if ((tid < TID_MAX_LOAD_COUNT))
rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
@@ -436,7 +431,7 @@ static int rs_collect_tx_data(struct iwl_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;
@@ -773,7 +768,8 @@ 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;
@@ -781,11 +777,9 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
int rs_index, index = 0;
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 iwl_rate_scale_data *window = NULL;
struct iwl_rate_scale_data *search_win = NULL;
@@ -811,17 +805,9 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
if (retries > 15)
retries = 15;
- rcu_read_lock();
+ lq_sta = (struct iwl_lq_sta *)priv_sta;
- sta = sta_info_get(local, hdr->addr1);
-
- if (!sta || !sta->rate_ctrl_priv)
- goto out;
-
-
- lq_sta = (struct iwl_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;
@@ -965,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;
}
@@ -1128,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;
}
}
@@ -1142,7 +1128,7 @@ static s32 rs_get_best_rate(struct iwl_priv *priv,
static int rs_switch_to_mimo2(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta,
struct ieee80211_conf *conf,
- struct sta_info *sta,
+ struct ieee80211_sta *sta,
struct iwl_scale_tbl_info *tbl, int index)
{
u16 rate_mask;
@@ -1153,8 +1139,8 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
!sta->ht_info.ht_supported)
return -1;
- if (((sta->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS) >> 2)
- == 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,7 +1196,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
static int rs_switch_to_siso(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta,
struct ieee80211_conf *conf,
- struct sta_info *sta,
+ struct ieee80211_sta *sta,
struct iwl_scale_tbl_info *tbl, int index)
{
u16 rate_mask;
@@ -1270,7 +1256,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
static int rs_move_legacy_other(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta,
struct ieee80211_conf *conf,
- struct sta_info *sta,
+ struct ieee80211_sta *sta,
int index)
{
struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
@@ -1281,15 +1267,23 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
(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;
@@ -1299,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;
@@ -1312,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;
}
@@ -1359,7 +1364,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
static int rs_move_siso_to_other(struct iwl_priv *priv,
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 iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
@@ -1370,34 +1375,51 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
(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 &&
@@ -1427,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;
}
@@ -1452,43 +1475,64 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
static int rs_move_mimo_to_other(struct iwl_priv *priv,
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 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))
@@ -1517,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;
}
@@ -1624,12 +1668,11 @@ static void rs_stay_in_table(struct iwl_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;
@@ -1644,7 +1687,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
__le16 fc;
u16 rate_mask;
u8 update_lq = 0;
- struct iwl_lq_sta *lq_sta;
struct iwl_scale_tbl_info *tbl, *tbl1;
u16 rate_scale_index_msk = 0;
u32 rate;
@@ -1665,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 iwl_lq_sta *)sta->rate_ctrl_priv;
+ lq_sta->supp_rates = sta->supp_rates[lq_sta->band];
tid = rs_tl_add_packet(lq_sta, hdr);
@@ -1686,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);
@@ -1747,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) {
@@ -1769,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,
@@ -2005,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;
}
@@ -2021,9 +2049,9 @@ 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 iwl_lq_sta *lq_sta;
struct iwl_scale_tbl_info *tbl;
int rate_idx;
int i;
@@ -2032,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 iwl_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;
@@ -2076,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 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 iwl_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);
@@ -2124,23 +2144,22 @@ 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 iwl_lq_sta *lq_sta;
struct iwl_priv *priv;
@@ -2163,33 +2182,28 @@ static void *rs_alloc_sta(void *priv_rate, gfp_t gfp)
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 iwl_priv *priv = (struct iwl_priv *)priv_r;
+ struct ieee80211_conf *conf = &priv->hw->conf;
struct iwl_lq_sta *lq_sta = priv_sta;
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-
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]);
- 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);
@@ -2212,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);
@@ -2260,7 +2273,7 @@ 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,
@@ -2382,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)
@@ -2405,12 +2418,12 @@ static void rs_clear(void *priv_rate)
#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 iwl_lq_sta *lq_sta = priv_sta;
- struct iwl_priv *priv;
+ 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");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
index 84d4d1e33755..d148d73635eb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
@@ -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*/
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index e01f048a02dd..24a1aeb6448f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -337,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) {
@@ -448,8 +448,8 @@ static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv,
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)
@@ -485,7 +485,7 @@ static u8 iwl4965_rate_get_lowest_plcp(struct iwl_priv *priv)
return IWL_RATE_6M_PLCP;
}
-unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
+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;
@@ -564,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)
@@ -586,6 +584,8 @@ static void iwl4965_ht_conf(struct iwl_priv *priv,
iwl_conf->supported_chan_width = 0;
}
+ 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;
@@ -672,7 +672,7 @@ static void iwl4965_setup_rxon_timing(struct iwl_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);
@@ -721,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;
@@ -740,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;
@@ -785,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];
@@ -1182,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);
}
@@ -1270,7 +1270,7 @@ int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
if (src == IWL_PWR_SRC_VAUX) {
u32 val;
- ret = pci_read_config_dword(priv->pci_dev, PCI_POWER_SOURCE,
+ ret = pci_read_config_dword(priv->pci_dev, PCI_CFG_POWER_SOURCE,
&val);
if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT)
@@ -2388,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)
@@ -2469,7 +2469,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
DECLARE_MAC_BUF(mac);
unsigned long flags;
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+ if (priv->iw_mode == NL80211_IFTYPE_AP) {
IWL_ERROR("%s Should not be called in AP mode\n", __func__);
return;
}
@@ -2486,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);
@@ -2503,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);
@@ -2523,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;
}
@@ -2531,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;
@@ -2550,44 +2550,23 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
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");
-
- 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));
+ /* 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);
- 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);
}
/*****************************************************************************
@@ -2728,12 +2707,6 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
IWL_DEBUG_MACDUMP("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);
@@ -2798,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;
@@ -2817,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;
}
@@ -2830,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);
@@ -2851,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);
@@ -2880,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);
@@ -2896,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;
}
@@ -2945,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;
}
@@ -2984,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)
@@ -2994,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");
@@ -3017,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);
@@ -3052,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);
}
@@ -3092,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 */
@@ -3173,6 +3149,10 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
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);
@@ -3189,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");
@@ -3201,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");
@@ -3243,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,
@@ -3332,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
@@ -3403,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);
@@ -3416,13 +3402,13 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
static int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
enum ieee80211_ampdu_mlme_action action,
- const u8 *addr, u16 tid, u16 *ssn)
+ 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, addr), tid);
+ print_mac(mac, sta->addr), tid);
if (!(priv->cfg->sku & IWL_SKU_N))
return -EACCES;
@@ -3430,16 +3416,16 @@ static int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
switch (action) {
case IEEE80211_AMPDU_RX_START:
IWL_DEBUG_HT("start Rx\n");
- return iwl_rx_agg_start(priv, addr, tid, *ssn);
+ 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, addr, tid);
+ 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, addr, tid, ssn);
+ 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, addr, tid);
+ return iwl_tx_agg_stop(priv, sta->addr, tid);
default:
IWL_DEBUG_HT("unknown\n");
return -EINVAL;
@@ -3521,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);
@@ -3535,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);
@@ -3544,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);
@@ -3573,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;
@@ -3630,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
@@ -3706,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
@@ -3734,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) {
@@ -3742,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);
}
@@ -3769,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) {
@@ -3870,10 +3875,12 @@ static ssize_t store_retry_rate(struct device *d,
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;
}
@@ -3894,9 +3901,9 @@ static ssize_t store_power_level(struct device *d,
{
struct iwl_priv *priv = dev_get_drvdata(d);
int ret;
- int mode;
+ unsigned long mode;
+
- mode = simple_strtoul(buf, NULL, 0);
mutex_lock(&priv->mutex);
if (!iwl_is_ready(priv)) {
@@ -3904,6 +3911,10 @@ static ssize_t store_power_level(struct device *d,
goto out;
}
+ 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");
@@ -4080,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);
@@ -4102,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);
@@ -4150,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)
@@ -4204,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",
@@ -4225,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
@@ -4247,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) {
@@ -4481,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}
};
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 28b5b09996ed..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;
@@ -2026,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
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 80f2f84defa8..4c312c55f90c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -306,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)) {
@@ -399,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)) {
@@ -646,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))
@@ -697,8 +703,12 @@ 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.
@@ -709,10 +719,11 @@ static int iwl_get_active_rx_chain_count(struct iwl_priv *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)))
- return 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
- return 3;
+ return IWL_NUM_RX_CHAINS_MULTIPLE;
}
static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
@@ -720,17 +731,19 @@ 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_cnt = (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_cnt = (is_cam) ? active_cnt : 1;
+ case WLAN_HT_CAP_SM_PS_DISABLED:
+ idle_cnt = (is_cam) ? active_cnt : IWL_NUM_IDLE_CHAINS_SINGLE;
break;
- case IWL_MIMO_PS_INVALID:
+ case WLAN_HT_CAP_SM_PS_INVALID:
default:
- IWL_ERROR("invalide mimo ps mode %d\n", priv->ps_mode);
+ IWL_ERROR("invalide mimo ps mode %d\n",
+ priv->current_ht_config.sm_ps);
WARN_ON(1);
idle_cnt = -1;
break;
@@ -738,6 +751,17 @@ static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
return idle_cnt;
}
+/* 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;
+}
+
/**
* iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
*
@@ -748,37 +772,47 @@ void iwl_set_rxon_chain(struct iwl_priv *priv)
{
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;
+ 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. */
- rx_chain = 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? */
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 accoridng hw settings */
- if (priv->hw_params.rx_chains_num < active_rx_cnt)
- active_rx_cnt = priv->hw_params.rx_chains_num;
- if (priv->hw_params.rx_chains_num < idle_rx_cnt)
- idle_rx_cnt = priv->hw_params.rx_chains_num;
+ /* 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 >= 2) && is_cam)
+ 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=0x%Xi active=%d idle=%d\n",
+ IWL_DEBUG_ASSOC("rx_chain=0x%X active=%d idle=%d\n",
priv->staging_rxon.rx_chain,
active_rx_cnt, idle_rx_cnt);
@@ -788,7 +822,7 @@ void iwl_set_rxon_chain(struct iwl_priv *priv)
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
@@ -797,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);
@@ -834,6 +869,10 @@ int iwl_setup_mac(struct iwl_priv *priv)
/* Tell mac80211 our characteristics */
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 */
@@ -891,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);
@@ -905,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);
@@ -922,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;
@@ -950,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;
@@ -993,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);
@@ -1150,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) {
@@ -1231,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;
@@ -1274,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)
{
@@ -1391,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 64f139e97444..288b6a800e03 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -184,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);
@@ -218,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);
@@ -237,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);
@@ -256,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);
@@ -286,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 *
*****************************************************/
@@ -312,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);
@@ -337,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 52629fbd835a..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*/
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index d2daa174df22..e548d67f87fd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -110,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)
@@ -162,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-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index cdfb343c7ec6..c018121085e9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -225,12 +225,6 @@ struct iwl_frame {
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)
@@ -412,6 +406,7 @@ struct iwl_ht_info {
/* self configuration data */
u8 is_ht;
u8 supported_chan_width;
+ u8 sm_ps;
u8 is_green_field;
u8 sgf; /* HT_SHORT_GI_* short guard interval */
u8 max_amsdu_size;
@@ -570,50 +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 int iwl4965_set_power(struct iwl_priv *priv, void *cmd);
-
-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)
{
@@ -636,12 +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_check_empty_hw_queue(struct iwl_priv *priv, int sta_id,
- u8 tid, int txq_id);
/* Structures, enum, and defines specific to the 4965 */
@@ -656,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
@@ -671,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
@@ -727,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 {
@@ -745,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 {
@@ -789,17 +740,18 @@ 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 */
@@ -813,6 +765,7 @@ enum {
#define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */
+#define IWL_CALIB_MAX 3
struct iwl_priv {
@@ -828,7 +781,6 @@ 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);
@@ -857,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;
@@ -939,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;
@@ -1005,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;
@@ -1025,7 +974,6 @@ struct iwl_priv {
* hardware */
u16 assoc_id;
u16 assoc_capability;
- u8 ps_mode;
struct iwl_qos_info qos_data;
@@ -1047,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-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h
index cd11c0ca2991..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)
/**
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 2eb03eea1908..8300f3d00a06 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -120,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;
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-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index a099c9e30e55..60a03d2d2d0e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -152,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_MAX;
+ struct iwl_powertable_cmd *cmd;
+ int i;
u16 pci_pm;
IWL_DEBUG_POWER("Initialize power \n");
@@ -167,25 +168,19 @@ 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 iwl_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_MAX; 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*/
@@ -255,17 +250,26 @@ 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_SYS_AUTO:
@@ -286,11 +290,11 @@ int iwl_power_update_mode(struct iwl_priv *priv, u8 refresh)
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)) {
+ ((setting->power_mode != final_mode) || force)) {
struct iwl_powertable_cmd cmd;
if (final_mode != IWL_POWER_MODE_CAM)
@@ -324,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;
@@ -337,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;
}
@@ -359,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);
@@ -431,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 abcbbf96a84e..df484a90ae64 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -72,14 +72,16 @@ struct iwl_power_mgr {
/* 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-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index e81bfc42a7cb..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 iwl_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 */
@@ -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--;
@@ -1130,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:
@@ -1171,7 +1075,6 @@ 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;
/* TSF isn't reliable. In order to allow smooth user experience,
@@ -1253,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;
@@ -1271,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 */
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 6c8ac3a87d54..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
@@ -464,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;
@@ -480,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;
}
@@ -710,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);
@@ -850,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 {
@@ -858,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) |
@@ -869,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 |
@@ -922,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 6283a3a707f5..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,20 +191,20 @@ 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\n", mimo_ps_mode);
@@ -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,7 +817,7 @@ 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)
@@ -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,6 +968,11 @@ 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\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 78b1a7a4ca40..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
@@ -478,7 +475,6 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_hw_txq_ctx_free);
-
/**
* iwl_txq_ctx_reset - Reset TX queue context
* Destroys all DMA structures and initialise them again
@@ -545,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
*/
@@ -796,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");
@@ -822,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);
@@ -849,7 +843,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
txq_id = swq_id;
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;
seq_number &= IEEE80211_SCTL_SEQ;
hdr->seq_ctrl = hdr->seq_ctrl &
@@ -1064,7 +1058,7 @@ 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);
+ 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,
@@ -1072,12 +1066,26 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
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 */
@@ -1185,17 +1193,16 @@ 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];
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index b775d5bab668..d15a2c997954 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1160,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");
@@ -1447,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)
@@ -1746,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)) {
@@ -2120,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);
@@ -2156,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;
}
@@ -2218,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;
@@ -2237,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;
@@ -2282,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];
@@ -2302,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,
@@ -2469,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;
@@ -2481,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 */
@@ -2502,7 +2502,7 @@ 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:
@@ -2565,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);
@@ -2590,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) |
@@ -2709,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);
@@ -2806,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);
@@ -3161,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);
}
@@ -4782,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
@@ -4792,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.
@@ -4802,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;
@@ -4829,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;
@@ -4853,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;
@@ -4875,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);
@@ -6052,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);
@@ -6093,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);
@@ -6201,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",
@@ -6209,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 */
@@ -6243,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);
@@ -6320,16 +6317,13 @@ 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) {
+ if (priv->iw_mode == NL80211_IFTYPE_AP) {
IWL_ERROR("%s Should not be called in AP mode\n", __func__);
return;
}
@@ -6342,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);
@@ -6381,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;
}
@@ -6389,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);
@@ -6419,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)
@@ -6567,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);
}
@@ -6650,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;
@@ -6767,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;
}
@@ -6804,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)
@@ -6816,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");
@@ -6839,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);
@@ -6874,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);
}
@@ -6914,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 */
@@ -6935,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);
}
@@ -6950,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;
@@ -6967,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;
@@ -7109,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);
@@ -7182,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;
@@ -7198,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);
@@ -7212,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);
@@ -7248,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;
@@ -7268,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);
@@ -7329,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)
{
@@ -7767,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);
@@ -7785,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);
}
@@ -7801,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,
@@ -7830,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
};
@@ -7868,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;
@@ -7890,6 +7921,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
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;
@@ -7951,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);
@@ -8331,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);