Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-next-2.6
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index 4cca203..fec5645 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -43,6 +43,23 @@
return 0;
}
+/* Update the rfkill state */
+static void b43_rfkill_update_state(struct b43_wldev *dev)
+{
+ struct b43_rfkill *rfk = &(dev->wl->rfkill);
+
+ if (!dev->radio_hw_enable) {
+ rfk->rfkill->state = RFKILL_STATE_HARD_BLOCKED;
+ return;
+ }
+
+ if (!dev->phy.radio_on)
+ rfk->rfkill->state = RFKILL_STATE_SOFT_BLOCKED;
+ else
+ rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
+
+}
+
/* The poll callback for the hardware button. */
static void b43_rfkill_poll(struct input_polled_dev *poll_dev)
{
@@ -60,6 +77,7 @@
if (unlikely(enabled != dev->radio_hw_enable)) {
dev->radio_hw_enable = enabled;
report_change = 1;
+ b43_rfkill_update_state(dev);
b43info(wl, "Radio hardware status changed to %s\n",
enabled ? "ENABLED" : "DISABLED");
}
@@ -135,7 +153,7 @@
snprintf(rfk->name, sizeof(rfk->name),
"b43-%s", wiphy_name(wl->hw->wiphy));
rfk->rfkill->name = rfk->name;
- rfk->rfkill->state = RFKILL_STATE_ON;
+ rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
rfk->rfkill->data = dev;
rfk->rfkill->toggle_radio = b43_rfkill_soft_toggle;
rfk->rfkill->user_claim_unsupported = 1;
diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c
index 8935a30..476add9 100644
--- a/drivers/net/wireless/b43legacy/rfkill.c
+++ b/drivers/net/wireless/b43legacy/rfkill.c
@@ -44,6 +44,23 @@
return 0;
}
+/* Update the rfkill state */
+static void b43legacy_rfkill_update_state(struct b43legacy_wldev *dev)
+{
+ struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
+
+ if (!dev->radio_hw_enable) {
+ rfk->rfkill->state = RFKILL_STATE_HARD_BLOCKED;
+ return;
+ }
+
+ if (!dev->phy.radio_on)
+ rfk->rfkill->state = RFKILL_STATE_SOFT_BLOCKED;
+ else
+ rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
+
+}
+
/* The poll callback for the hardware button. */
static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev)
{
@@ -61,6 +78,7 @@
if (unlikely(enabled != dev->radio_hw_enable)) {
dev->radio_hw_enable = enabled;
report_change = 1;
+ b43legacy_rfkill_update_state(dev);
b43legacyinfo(wl, "Radio hardware status changed to %s\n",
enabled ? "ENABLED" : "DISABLED");
}
@@ -139,7 +157,7 @@
snprintf(rfk->name, sizeof(rfk->name),
"b43legacy-%s", wiphy_name(wl->hw->wiphy));
rfk->rfkill->name = rfk->name;
- rfk->rfkill->state = RFKILL_STATE_ON;
+ rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
rfk->rfkill->data = dev;
rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle;
rfk->rfkill->user_claim_unsupported = 1;
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
index 4fd7380..d669e59 100644
--- a/drivers/net/wireless/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -78,6 +78,9 @@
prism_header = 2;
phdrlen = sizeof(struct linux_wlan_ng_cap_hdr);
}
+ } else if (dev->type == ARPHRD_IEEE80211_RADIOTAP) {
+ prism_header = 3;
+ phdrlen = sizeof(struct hostap_radiotap_rx);
} else {
prism_header = 0;
phdrlen = 0;
@@ -165,6 +168,24 @@
hdr->ssi_noise = htonl(rx_stats->noise);
hdr->preamble = htonl(0); /* unknown */
hdr->encoding = htonl(1); /* cck */
+ } else if (prism_header == 3) {
+ struct hostap_radiotap_rx *hdr;
+ hdr = (struct hostap_radiotap_rx *)skb_push(skb, phdrlen);
+ memset(hdr, 0, phdrlen);
+ hdr->hdr.it_len = cpu_to_le16(phdrlen);
+ hdr->hdr.it_present =
+ cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
+ (1 << IEEE80211_RADIOTAP_CHANNEL) |
+ (1 << IEEE80211_RADIOTAP_RATE) |
+ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
+ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE));
+ hdr->tsft = cpu_to_le64(rx_stats->mac_time);
+ hdr->chan_freq = cpu_to_le16(freq_list[local->channel - 1]);
+ hdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_CCK |
+ IEEE80211_CHAN_2GHZ);
+ hdr->rate = rx_stats->rate / 5;
+ hdr->dbm_antsignal = rx_stats->signal;
+ hdr->dbm_antnoise = rx_stats->noise;
}
ret = skb->len - phdrlen;
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index cdf90c4..79a9bc9 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -3204,6 +3204,7 @@
local->auth_algs = PRISM2_AUTH_OPEN | PRISM2_AUTH_SHARED_KEY;
local->sram_type = -1;
local->scan_channel_mask = 0xffff;
+ local->monitor_type = PRISM2_MONITOR_RADIOTAP;
/* Initialize task queue structures */
INIT_WORK(&local->reset_queue, handle_reset_queue);
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index ed52d98..3f8b1d7 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -897,6 +897,8 @@
if (local->monitor_type == PRISM2_MONITOR_PRISM ||
local->monitor_type == PRISM2_MONITOR_CAPHDR) {
dev->type = ARPHRD_IEEE80211_PRISM;
+ } else if (local->monitor_type == PRISM2_MONITOR_RADIOTAP) {
+ dev->type = ARPHRD_IEEE80211_RADIOTAP;
} else {
dev->type = ARPHRD_IEEE80211;
}
@@ -2520,7 +2522,8 @@
case PRISM2_PARAM_MONITOR_TYPE:
if (value != PRISM2_MONITOR_80211 &&
value != PRISM2_MONITOR_CAPHDR &&
- value != PRISM2_MONITOR_PRISM) {
+ value != PRISM2_MONITOR_PRISM &&
+ value != PRISM2_MONITOR_RADIOTAP) {
ret = -EINVAL;
break;
}
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index f7aec93..b5213f6 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -596,25 +596,7 @@
int hostap_80211_header_parse(const struct sk_buff *skb, unsigned char *haddr)
{
- struct hostap_interface *iface = netdev_priv(skb->dev);
- local_info_t *local = iface->local;
-
- if (local->monitor_type == PRISM2_MONITOR_PRISM ||
- local->monitor_type == PRISM2_MONITOR_CAPHDR) {
- const unsigned char *mac = skb_mac_header(skb);
-
- if (*(u32 *)mac == LWNG_CAP_DID_BASE) {
- memcpy(haddr,
- mac + sizeof(struct linux_wlan_ng_prism_hdr) + 10,
- ETH_ALEN); /* addr2 */
- } else { /* (*(u32 *)mac == htonl(LWNG_CAPHDR_VERSION)) */
- memcpy(haddr,
- mac + sizeof(struct linux_wlan_ng_cap_hdr) + 10,
- ETH_ALEN); /* addr2 */
- }
- } else
- memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */
-
+ memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */
return ETH_ALEN;
}
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index 15445bc..ffdf487 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -5,6 +5,7 @@
#include <linux/netdevice.h>
#include <linux/mutex.h>
#include <net/iw_handler.h>
+#include <net/ieee80211_radiotap.h>
#include "hostap_config.h"
#include "hostap_common.h"
@@ -55,6 +56,17 @@
__be32 encoding;
} __attribute__ ((packed));
+struct hostap_radiotap_rx {
+ struct ieee80211_radiotap_header hdr;
+ __le64 tsft;
+ u8 rate;
+ u8 padding;
+ __le16 chan_freq;
+ __le16 chan_flags;
+ s8 dbm_antsignal;
+ s8 dbm_antnoise;
+} __attribute__ ((packed));
+
#define LWNG_CAP_DID_BASE (4 | (1 << 6)) /* section 4, group 1 */
#define LWNG_CAPHDR_VERSION 0x80211001
@@ -734,7 +746,7 @@
unsigned long scan_timestamp; /* Time started to scan */
enum {
PRISM2_MONITOR_80211 = 0, PRISM2_MONITOR_PRISM = 1,
- PRISM2_MONITOR_CAPHDR = 2
+ PRISM2_MONITOR_CAPHDR = 2, PRISM2_MONITOR_RADIOTAP = 3
} monitor_type;
int monitor_allow_fcserr;
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index d7ea32f..b628a44 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -8,7 +8,6 @@
select MAC80211_LEDS if IWLWIFI_LEDS
select LEDS_CLASS if IWLWIFI_LEDS
select RFKILL if IWLWIFI_RFKILL
- select RFKILL_INPUT if (IWLWIFI_RFKILL && INPUT)
config IWLWIFI_LEDS
bool
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index a9b3eda..a774978 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -36,6 +36,10 @@
#include <linux/kernel.h>
#include <net/ieee80211_radiotap.h>
+/*used for rfkill*/
+#include <linux/rfkill.h>
+#include <linux/input.h>
+
/* Hardware specific file defines the PCI IDs table for that hardware module */
extern struct pci_device_id iwl3945_hw_card_ids[];
@@ -686,6 +690,23 @@
#endif
+#ifdef CONFIG_IWLWIFI_RFKILL
+struct iwl3945_priv;
+
+struct iwl3945_rfkill_mngr {
+ struct rfkill *rfkill;
+ struct input_dev *input_dev;
+};
+
+void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv);
+void iwl3945_rfkill_unregister(struct iwl3945_priv *priv);
+int iwl3945_rfkill_init(struct iwl3945_priv *priv);
+#else
+static inline void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) {}
+static inline void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) {}
+static inline int iwl3945_rfkill_init(struct iwl3945_priv *priv) { return 0; }
+#endif
+
#define IWL_MAX_NUM_QUEUES IWL39_MAX_NUM_QUEUES
struct iwl3945_priv {
@@ -779,6 +800,10 @@
struct iwl3945_init_alive_resp card_alive_init;
struct iwl3945_alive_resp card_alive;
+#ifdef CONFIG_IWLWIFI_RFKILL
+ struct iwl3945_rfkill_mngr rfkill_mngr;
+#endif
+
#ifdef CONFIG_IWL3945_LEDS
struct iwl3945_led led[IWL_LED_TRG_MAX];
unsigned long last_blink_time;
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
index 2023031..c7ebb3b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
@@ -822,9 +822,6 @@
lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
- if (!priv->lq_mngr.lq_ready)
- goto out;
-
if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
!lq_sta->ibss_sta_added)
goto out;
@@ -1678,10 +1675,6 @@
if (!sta || !sta->rate_ctrl_priv)
return;
- if (!priv->lq_mngr.lq_ready) {
- IWL_DEBUG_RATE("still rate scaling not ready\n");
- return;
- }
lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
tid = rs_tl_add_packet(lq_sta, hdr);
@@ -2140,11 +2133,8 @@
lq_sta->ibss_sta_added = 1;
rs_initialize_lq(priv, conf, sta);
}
- if (!lq_sta->ibss_sta_added)
- goto done;
}
-done:
if ((i < 0) || (i > IWL_RATE_COUNT)) {
sel->rate_idx = rate_lowest_index(local, sband, sta);
goto out;
@@ -2279,9 +2269,6 @@
lq_sta->drv = priv;
#endif
- if (priv->assoc_station_added)
- priv->lq_mngr.lq_ready = 1;
-
rs_initialize_lq(priv, conf, sta);
}
@@ -2421,7 +2408,7 @@
IWL_DEBUG_RATE("enter\n");
- priv->lq_mngr.lq_ready = 0;
+ /* TODO - add rate scale state reset */
IWL_DEBUG_RATE("leave\n");
}
@@ -2716,13 +2703,6 @@
return cnt;
}
-void iwl4965_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
-{
- struct iwl_priv *priv = hw->priv;
-
- priv->lq_mngr.lq_ready = 1;
-}
-
int iwl4965_rate_control_register(void)
{
return ieee80211_rate_control_register(&rs_ops);
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h
index cbd1264..9b99728 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h
@@ -296,14 +296,6 @@
extern int iwl4965_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id);
/**
- * iwl4965_rate_scale_init - Initialize the rate scale table based on assoc info
- *
- * The specific throughput table used is based on the type of network
- * the associated with, including A, B, G, and G w/ TGG protection
- */
-extern void iwl4965_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);
-
-/**
* iwl4965_rate_control_register - Register the rate control algorithm callbacks
*
* Since the rate control algorithm is hardware specific, there is no need
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index ab50273..8c93f8d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -555,8 +555,6 @@
return ret;
}
-#define REG_RECALIB_PERIOD (60)
-
/* Reset differential Rx gains in NIC to prepare for chain noise calibration.
* Called after every association, but this runs only once!
* ... once chain noise is calibrated the first time, it's good forever. */
@@ -839,17 +837,8 @@
priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
priv->hw_params.first_ampdu_q = IWL49_FIRST_AMPDU_QUEUE;
- priv->hw_params.sw_crypto = priv->cfg->mod_params->sw_crypto;
- priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
- priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
- if (priv->cfg->mod_params->amsdu_size_8K)
- priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K;
- else
- priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K;
- priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256;
priv->hw_params.max_stations = IWL4965_STATION_COUNT;
priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID;
-
priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE;
priv->hw_params.max_bsm_size = BSM_SRAM_SIZE;
@@ -1890,87 +1879,10 @@
return 1;
}
-/* Calculate noise level, based on measurements during network silence just
- * before arriving beacon. This measurement can be done only if we know
- * exactly when to expect beacons, therefore only when we're associated. */
-static void iwl4965_rx_calc_noise(struct iwl_priv *priv)
+static void iwl4965_temperature_calib(struct iwl_priv *priv)
{
- struct statistics_rx_non_phy *rx_info
- = &(priv->statistics.rx.general);
- int num_active_rx = 0;
- int total_silence = 0;
- int bcn_silence_a =
- le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
- int bcn_silence_b =
- le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
- int bcn_silence_c =
- le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
-
- if (bcn_silence_a) {
- total_silence += bcn_silence_a;
- num_active_rx++;
- }
- if (bcn_silence_b) {
- total_silence += bcn_silence_b;
- num_active_rx++;
- }
- if (bcn_silence_c) {
- total_silence += bcn_silence_c;
- num_active_rx++;
- }
-
- /* Average among active antennas */
- if (num_active_rx)
- priv->last_rx_noise = (total_silence / num_active_rx) - 107;
- else
- priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
-
- IWL_DEBUG_CALIB("inband silence a %u, b %u, c %u, dBm %d\n",
- bcn_silence_a, bcn_silence_b, bcn_silence_c,
- priv->last_rx_noise);
-}
-
-void iwl4965_hw_rx_statistics(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
-{
- struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
- int change;
s32 temp;
- IWL_DEBUG_RX("Statistics notification received (%d vs %d).\n",
- (int)sizeof(priv->statistics), pkt->len);
-
- change = ((priv->statistics.general.temperature !=
- pkt->u.stats.general.temperature) ||
- ((priv->statistics.flag &
- STATISTICS_REPLY_FLG_FAT_MODE_MSK) !=
- (pkt->u.stats.flag & STATISTICS_REPLY_FLG_FAT_MODE_MSK)));
-
- memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
-
- set_bit(STATUS_STATISTICS, &priv->status);
-
- /* Reschedule the statistics timer to occur in
- * REG_RECALIB_PERIOD seconds to ensure we get a
- * thermal update even if the uCode doesn't give
- * us one */
- mod_timer(&priv->statistics_periodic, jiffies +
- msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
-
- if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
- (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
- iwl4965_rx_calc_noise(priv);
- queue_work(priv->workqueue, &priv->run_time_calib_work);
- }
-
- iwl_leds_background(priv);
-
- /* If the hardware hasn't reported a change in
- * temperature then don't bother computing a
- * calibrated temperature value */
- if (!change)
- return;
-
temp = iwl4965_hw_get_temperature(priv);
if (temp < 0)
return;
@@ -1996,775 +1908,6 @@
queue_work(priv->workqueue, &priv->txpower_work);
}
-static void iwl4965_add_radiotap(struct iwl_priv *priv,
- struct sk_buff *skb,
- struct iwl4965_rx_phy_res *rx_start,
- struct ieee80211_rx_status *stats,
- u32 ampdu_status)
-{
- s8 signal = stats->signal;
- s8 noise = 0;
- int rate = stats->rate_idx;
- u64 tsf = stats->mactime;
- __le16 antenna;
- __le16 phy_flags_hw = rx_start->phy_flags;
- struct iwl4965_rt_rx_hdr {
- struct ieee80211_radiotap_header rt_hdr;
- __le64 rt_tsf; /* TSF */
- u8 rt_flags; /* radiotap packet flags */
- u8 rt_rate; /* rate in 500kb/s */
- __le16 rt_channelMHz; /* channel in MHz */
- __le16 rt_chbitmask; /* channel bitfield */
- s8 rt_dbmsignal; /* signal in dBm, kluged to signed */
- s8 rt_dbmnoise;
- u8 rt_antenna; /* antenna number */
- } __attribute__ ((packed)) *iwl4965_rt;
-
- /* TODO: We won't have enough headroom for HT frames. Fix it later. */
- if (skb_headroom(skb) < sizeof(*iwl4965_rt)) {
- if (net_ratelimit())
- printk(KERN_ERR "not enough headroom [%d] for "
- "radiotap head [%zd]\n",
- skb_headroom(skb), sizeof(*iwl4965_rt));
- return;
- }
-
- /* put radiotap header in front of 802.11 header and data */
- iwl4965_rt = (void *)skb_push(skb, sizeof(*iwl4965_rt));
-
- /* initialise radiotap header */
- iwl4965_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
- iwl4965_rt->rt_hdr.it_pad = 0;
-
- /* total header + data */
- put_unaligned(cpu_to_le16(sizeof(*iwl4965_rt)),
- &iwl4965_rt->rt_hdr.it_len);
-
- /* Indicate all the fields we add to the radiotap header */
- put_unaligned(cpu_to_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(cpu_to_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(cpu_to_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(cpu_to_le16(IEEE80211_CHAN_CCK |
- IEEE80211_CHAN_2GHZ),
- &iwl4965_rt->rt_chbitmask);
- else /* 802.11g */
- put_unaligned(cpu_to_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 */
- int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
- priv->rx_stats[idx].cnt++;
- priv->rx_stats[idx].bytes += len;
-}
-
-/*
- * returns non-zero if packet should be dropped
- */
-static int iwl4965_set_decrypted_flag(struct iwl_priv *priv,
- struct ieee80211_hdr *hdr,
- u32 decrypt_res,
- struct ieee80211_rx_status *stats)
-{
- u16 fc = le16_to_cpu(hdr->frame_control);
-
- if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK)
- return 0;
-
- if (!(fc & IEEE80211_FCTL_PROTECTED))
- return 0;
-
- IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res);
- switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) {
- case RX_RES_STATUS_SEC_TYPE_TKIP:
- /* The uCode has got a bad phase 1 Key, pushes the packet.
- * Decryption will be done in SW. */
- if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
- RX_RES_STATUS_BAD_KEY_TTAK)
- break;
-
- case RX_RES_STATUS_SEC_TYPE_WEP:
- if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
- RX_RES_STATUS_BAD_ICV_MIC) {
- /* bad ICV, the packet is destroyed since the
- * decryption is inplace, drop it */
- IWL_DEBUG_RX("Packet destroyed\n");
- return -1;
- }
- case RX_RES_STATUS_SEC_TYPE_CCMP:
- if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
- RX_RES_STATUS_DECRYPT_OK) {
- IWL_DEBUG_RX("hw decrypt successfully!!!\n");
- stats->flag |= RX_FLAG_DECRYPTED;
- }
- break;
-
- default:
- break;
- }
- return 0;
-}
-
-static u32 iwl4965_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
-{
- u32 decrypt_out = 0;
-
- if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) ==
- RX_RES_STATUS_STATION_FOUND)
- decrypt_out |= (RX_RES_STATUS_STATION_FOUND |
- RX_RES_STATUS_NO_STATION_INFO_MISMATCH);
-
- decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK);
-
- /* packet was not encrypted */
- if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
- RX_RES_STATUS_SEC_TYPE_NONE)
- return decrypt_out;
-
- /* packet was encrypted with unknown alg */
- if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
- RX_RES_STATUS_SEC_TYPE_ERR)
- return decrypt_out;
-
- /* decryption was not done in HW */
- if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) !=
- RX_MPDU_RES_STATUS_DEC_DONE_MSK)
- return decrypt_out;
-
- switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) {
-
- case RX_RES_STATUS_SEC_TYPE_CCMP:
- /* alg is CCM: check MIC only */
- if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK))
- /* Bad MIC */
- decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
- else
- decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
-
- break;
-
- case RX_RES_STATUS_SEC_TYPE_TKIP:
- if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) {
- /* Bad TTAK */
- decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
- break;
- }
- /* fall through if TTAK OK */
- default:
- if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
- decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
- else
- decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
- break;
- };
-
- IWL_DEBUG_RX("decrypt_in:0x%x decrypt_out = 0x%x\n",
- decrypt_in, decrypt_out);
-
- return decrypt_out;
-}
-
-static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data,
- int include_phy,
- struct iwl_rx_mem_buffer *rxb,
- struct ieee80211_rx_status *stats)
-{
- struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
- struct iwl4965_rx_phy_res *rx_start = (include_phy) ?
- (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) : NULL;
- struct ieee80211_hdr *hdr;
- u16 len;
- __le32 *rx_end;
- unsigned int skblen;
- u32 ampdu_status;
- u32 ampdu_status_legacy;
-
- if (!include_phy && priv->last_phy_res[0])
- rx_start = (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1];
-
- if (!rx_start) {
- IWL_ERROR("MPDU frame without a PHY data\n");
- return;
- }
- if (include_phy) {
- hdr = (struct ieee80211_hdr *)((u8 *) & rx_start[1] +
- rx_start->cfg_phy_cnt);
-
- len = le16_to_cpu(rx_start->byte_count);
-
- rx_end = (__le32 *) ((u8 *) & pkt->u.raw[0] +
- sizeof(struct iwl4965_rx_phy_res) +
- rx_start->cfg_phy_cnt + len);
-
- } else {
- struct iwl4965_rx_mpdu_res_start *amsdu =
- (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw;
-
- hdr = (struct ieee80211_hdr *)(pkt->u.raw +
- sizeof(struct iwl4965_rx_mpdu_res_start));
- len = le16_to_cpu(amsdu->byte_count);
- rx_start->byte_count = amsdu->byte_count;
- rx_end = (__le32 *) (((u8 *) hdr) + len);
- }
- /* In monitor mode allow 802.11 ACk frames (10 bytes) */
- if (len > priv->hw_params.max_pkt_size ||
- len < ((priv->iw_mode == IEEE80211_IF_TYPE_MNTR) ? 10 : 16)) {
- IWL_WARNING("byte count out of range [16,4K] : %d\n", len);
- return;
- }
-
- ampdu_status = le32_to_cpu(*rx_end);
- skblen = ((u8 *) rx_end - (u8 *) & pkt->u.raw[0]) + sizeof(u32);
-
- if (!include_phy) {
- /* New status scheme, need to translate */
- ampdu_status_legacy = ampdu_status;
- ampdu_status = iwl4965_translate_rx_status(priv, ampdu_status);
- }
-
- /* start from MAC */
- skb_reserve(rxb->skb, (void *)hdr - (void *)pkt);
- skb_put(rxb->skb, len); /* end where data ends */
-
- /* We only process data packets if the interface is open */
- if (unlikely(!priv->is_open)) {
- IWL_DEBUG_DROP_LIMIT
- ("Dropping packet while interface is not open.\n");
- return;
- }
-
- stats->flag = 0;
- hdr = (struct ieee80211_hdr *)rxb->skb->data;
-
- /* in case of HW accelerated crypto and bad decryption, drop */
- if (!priv->hw_params.sw_crypto &&
- iwl4965_set_decrypted_flag(priv, hdr, ampdu_status, stats))
- return;
-
- if (priv->add_radiotap)
- iwl4965_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--;
- rxb->skb = NULL;
-}
-
-/* Calc max signal level (dBm) among 3 possible receivers */
-static int iwl4965_calc_rssi(struct iwl_priv *priv,
- struct iwl4965_rx_phy_res *rx_resp)
-{
- /* data from PHY/DSP regarding signal strength, etc.,
- * contents are always there, not configurable by host. */
- struct iwl4965_rx_non_cfg_phy *ncphy =
- (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy;
- u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL_AGC_DB_MASK)
- >> IWL_AGC_DB_POS;
-
- u32 valid_antennae =
- (le16_to_cpu(rx_resp->phy_flags) & RX_PHY_FLAGS_ANTENNAE_MASK)
- >> RX_PHY_FLAGS_ANTENNAE_OFFSET;
- u8 max_rssi = 0;
- u32 i;
-
- /* Find max rssi among 3 possible receivers.
- * These values are measured by the digital signal processor (DSP).
- * They should stay fairly constant even as the signal strength varies,
- * if the radio's automatic gain control (AGC) is working right.
- * AGC value (see below) will provide the "interesting" info. */
- for (i = 0; i < 3; i++)
- if (valid_antennae & (1 << i))
- max_rssi = max(ncphy->rssi_info[i << 1], max_rssi);
-
- IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n",
- ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4],
- max_rssi, agc);
-
- /* dBm = max_rssi dB - agc dB - constant.
- * Higher AGC (higher radio gain) means lower signal. */
- return (max_rssi - agc - IWL_RSSI_OFFSET);
-}
-
-static void iwl4965_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
- priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
- priv->stations[sta_id].sta.sta.modify_mask = 0;
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-}
-
-static void iwl4965_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr)
-{
- /* FIXME: need locking over ps_status ??? */
- u8 sta_id = iwl_find_station(priv, addr);
-
- if (sta_id != IWL_INVALID_STATION) {
- u8 sta_awake = priv->stations[sta_id].
- ps_status == STA_PS_STATUS_WAKE;
-
- if (sta_awake && ps_bit)
- priv->stations[sta_id].ps_status = STA_PS_STATUS_SLEEP;
- else if (!sta_awake && !ps_bit) {
- iwl4965_sta_modify_ps_wake(priv, sta_id);
- priv->stations[sta_id].ps_status = STA_PS_STATUS_WAKE;
- }
- }
-}
-#ifdef CONFIG_IWLWIFI_DEBUG
-
-/**
- * iwl4965_dbg_report_frame - dump frame to syslog during debug sessions
- *
- * You may hack this function to show different aspects of received frames,
- * including selective frame dumps.
- * group100 parameter selects whether to show 1 out of 100 good frames.
- *
- * TODO: This was originally written for 3945, need to audit for
- * proper operation with 4965.
- */
-static void iwl4965_dbg_report_frame(struct iwl_priv *priv,
- struct iwl_rx_packet *pkt,
- struct ieee80211_hdr *header, int group100)
-{
- u32 to_us;
- u32 print_summary = 0;
- u32 print_dump = 0; /* set to 1 to dump all frames' contents */
- u32 hundred = 0;
- u32 dataframe = 0;
- __le16 fc;
- u16 seq_ctl;
- u16 channel;
- u16 phy_flags;
- int rate_sym;
- u16 length;
- u16 status;
- u16 bcn_tmr;
- u32 tsf_low;
- u64 tsf;
- u8 rssi;
- u8 agc;
- u16 sig_avg;
- u16 noise_diff;
- struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
- struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
- struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt);
- u8 *data = IWL_RX_DATA(pkt);
-
- if (likely(!(priv->debug_level & IWL_DL_RX)))
- return;
-
- /* MAC header */
- fc = header->frame_control;
- seq_ctl = le16_to_cpu(header->seq_ctrl);
-
- /* metadata */
- channel = le16_to_cpu(rx_hdr->channel);
- phy_flags = le16_to_cpu(rx_hdr->phy_flags);
- rate_sym = rx_hdr->rate;
- length = le16_to_cpu(rx_hdr->len);
-
- /* end-of-frame status and timestamp */
- status = le32_to_cpu(rx_end->status);
- bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
- tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
- tsf = le64_to_cpu(rx_end->timestamp);
-
- /* signal statistics */
- rssi = rx_stats->rssi;
- agc = rx_stats->agc;
- sig_avg = le16_to_cpu(rx_stats->sig_avg);
- noise_diff = le16_to_cpu(rx_stats->noise_diff);
-
- to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
-
- /* if data frame is to us and all is good,
- * (optionally) print summary for only 1 out of every 100 */
- if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) ==
- cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
- dataframe = 1;
- if (!group100)
- print_summary = 1; /* print each frame */
- else if (priv->framecnt_to_us < 100) {
- priv->framecnt_to_us++;
- print_summary = 0;
- } else {
- priv->framecnt_to_us = 0;
- print_summary = 1;
- hundred = 1;
- }
- } else {
- /* print summary for all other frames */
- print_summary = 1;
- }
-
- if (print_summary) {
- char *title;
- int rate_idx;
- u32 bitrate;
-
- if (hundred)
- title = "100Frames";
- else if (ieee80211_has_retry(fc))
- title = "Retry";
- else if (ieee80211_is_assoc_resp(fc))
- title = "AscRsp";
- else if (ieee80211_is_reassoc_resp(fc))
- title = "RasRsp";
- else if (ieee80211_is_probe_resp(fc)) {
- title = "PrbRsp";
- print_dump = 1; /* dump frame contents */
- } else if (ieee80211_is_beacon(fc)) {
- title = "Beacon";
- print_dump = 1; /* dump frame contents */
- } else if (ieee80211_is_atim(fc))
- title = "ATIM";
- else if (ieee80211_is_auth(fc))
- title = "Auth";
- else if (ieee80211_is_deauth(fc))
- title = "DeAuth";
- else if (ieee80211_is_disassoc(fc))
- title = "DisAssoc";
- else
- title = "Frame";
-
- rate_idx = iwl_hwrate_to_plcp_idx(rate_sym);
- if (unlikely(rate_idx == -1))
- bitrate = 0;
- else
- bitrate = iwl_rates[rate_idx].ieee / 2;
-
- /* print frame summary.
- * MAC addresses show just the last byte (for brevity),
- * but you can hack it to show more, if you'd like to. */
- if (dataframe)
- IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
- "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
- title, le16_to_cpu(fc), header->addr1[5],
- length, rssi, channel, bitrate);
- else {
- /* src/dst addresses assume managed mode */
- IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
- "src=0x%02x, rssi=%u, tim=%lu usec, "
- "phy=0x%02x, chnl=%d\n",
- title, le16_to_cpu(fc), header->addr1[5],
- header->addr3[5], rssi,
- tsf_low - priv->scan_start_tsf,
- phy_flags, channel);
- }
- }
- if (print_dump)
- iwl_print_hex_dump(priv, IWL_DL_RX, data, length);
-}
-#else
-static inline void iwl4965_dbg_report_frame(struct iwl_priv *priv,
- struct iwl_rx_packet *pkt,
- struct ieee80211_hdr *header,
- int group100)
-{
-}
-#endif
-
-
-
-/* Called for REPLY_RX (legacy ABG frames), or
- * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
-void iwl4965_rx_reply_rx(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
-{
- struct ieee80211_hdr *header;
- struct ieee80211_rx_status rx_status;
- struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
- /* Use phy data (Rx signal strength, etc.) contained within
- * this rx packet for legacy frames,
- * or phy data cached from REPLY_RX_PHY_CMD for HT frames. */
- int include_phy = (pkt->hdr.cmd == REPLY_RX);
- struct iwl4965_rx_phy_res *rx_start = (include_phy) ?
- (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) :
- (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1];
- __le32 *rx_end;
- unsigned int len = 0;
- u16 fc;
- u8 network_packet;
-
- rx_status.mactime = le64_to_cpu(rx_start->timestamp);
- rx_status.freq =
- ieee80211_channel_to_frequency(le16_to_cpu(rx_start->channel));
- rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
- IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
- rx_status.rate_idx =
- iwl_hwrate_to_plcp_idx(le32_to_cpu(rx_start->rate_n_flags));
- if (rx_status.band == IEEE80211_BAND_5GHZ)
- rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
-
- rx_status.antenna = 0;
- rx_status.flag = 0;
-
- if ((unlikely(rx_start->cfg_phy_cnt > 20))) {
- IWL_DEBUG_DROP("dsp size out of range [0,20]: %d/n",
- rx_start->cfg_phy_cnt);
- return;
- }
-
- if (!include_phy) {
- if (priv->last_phy_res[0])
- rx_start = (struct iwl4965_rx_phy_res *)
- &priv->last_phy_res[1];
- else
- rx_start = NULL;
- }
-
- if (!rx_start) {
- IWL_ERROR("MPDU frame without a PHY data\n");
- return;
- }
-
- if (include_phy) {
- header = (struct ieee80211_hdr *)((u8 *) & rx_start[1]
- + rx_start->cfg_phy_cnt);
-
- len = le16_to_cpu(rx_start->byte_count);
- rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt +
- sizeof(struct iwl4965_rx_phy_res) + len);
- } else {
- struct iwl4965_rx_mpdu_res_start *amsdu =
- (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw;
-
- header = (void *)(pkt->u.raw +
- sizeof(struct iwl4965_rx_mpdu_res_start));
- len = le16_to_cpu(amsdu->byte_count);
- rx_end = (__le32 *) (pkt->u.raw +
- sizeof(struct iwl4965_rx_mpdu_res_start) + len);
- }
-
- if (!(*rx_end & RX_RES_STATUS_NO_CRC32_ERROR) ||
- !(*rx_end & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
- IWL_DEBUG_RX("Bad CRC or FIFO: 0x%08X.\n",
- le32_to_cpu(*rx_end));
- return;
- }
-
- priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp);
-
- /* Find max signal strength (dBm) among 3 antenna/receiver chains */
- rx_status.signal = iwl4965_calc_rssi(priv, rx_start);
-
- /* Meaningful noise values are available only from beacon statistics,
- * which are gathered only when associated, and indicate noise
- * only for the associated network channel ...
- * Ignore these noise values while scanning (other channels) */
- if (iwl_is_associated(priv) &&
- !test_bit(STATUS_SCANNING, &priv->status)) {
- rx_status.noise = priv->last_rx_noise;
- rx_status.qual = iwl4965_calc_sig_qual(rx_status.signal,
- rx_status.noise);
- } else {
- rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
- rx_status.qual = iwl4965_calc_sig_qual(rx_status.signal, 0);
- }
-
- /* Reset beacon noise level if not associated. */
- if (!iwl_is_associated(priv))
- priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
-
- /* Set "1" to report good data frames in groups of 100 */
- /* FIXME: need to optimze the call: */
- iwl4965_dbg_report_frame(priv, pkt, header, 1);
-
- IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n",
- rx_status.signal, rx_status.noise, rx_status.signal,
- (unsigned long long)rx_status.mactime);
-
-
- if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
- iwl4965_handle_data_packet(priv, 1, include_phy,
- rxb, &rx_status);
- return;
- }
-
- network_packet = iwl4965_is_network_packet(priv, header);
- if (network_packet) {
- priv->last_rx_rssi = rx_status.signal;
- priv->last_beacon_time = priv->ucode_beacon_time;
- priv->last_tsf = le64_to_cpu(rx_start->timestamp);
- }
-
- fc = le16_to_cpu(header->frame_control);
- switch (fc & IEEE80211_FCTL_FTYPE) {
- case IEEE80211_FTYPE_MGMT:
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
- iwl4965_update_ps_mode(priv, fc & IEEE80211_FCTL_PM,
- header->addr2);
- iwl4965_handle_data_packet(priv, 0, include_phy, rxb, &rx_status);
- break;
-
- case IEEE80211_FTYPE_CTL:
- switch (fc & IEEE80211_FCTL_STYPE) {
- case IEEE80211_STYPE_BACK_REQ:
- IWL_DEBUG_HT("IEEE80211_STYPE_BACK_REQ arrived\n");
- iwl4965_handle_data_packet(priv, 0, include_phy,
- rxb, &rx_status);
- break;
- default:
- break;
- }
- break;
-
- case IEEE80211_FTYPE_DATA: {
- DECLARE_MAC_BUF(mac1);
- DECLARE_MAC_BUF(mac2);
- DECLARE_MAC_BUF(mac3);
-
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
- iwl4965_update_ps_mode(priv, fc & IEEE80211_FCTL_PM,
- header->addr2);
-
- if (unlikely(!network_packet))
- 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));
- else if (unlikely(iwl4965_is_duplicate_packet(priv, header)))
- IWL_DEBUG_DROP("Dropping (dup): %s, %s, %s\n",
- print_mac(mac1, header->addr1),
- print_mac(mac2, header->addr2),
- print_mac(mac3, header->addr3));
- else
- iwl4965_handle_data_packet(priv, 1, include_phy, rxb,
- &rx_status);
- break;
- }
- default:
- break;
-
- }
-}
-
-/**
- * iwl4965_tx_status_reply_compressed_ba - Update tx status from block-ack
- *
- * Go through block-ack's bitmap of ACK'd frames, update driver's record of
- * ACK vs. not. This gets sent to mac80211, then to rate scaling algo.
- */
-static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv,
- struct iwl_ht_agg *agg,
- struct iwl4965_compressed_ba_resp*
- ba_resp)
-
-{
- int i, sh, ack;
- u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
- u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
- u64 bitmap;
- int successes = 0;
- struct ieee80211_tx_info *info;
-
- if (unlikely(!agg->wait_for_ba)) {
- IWL_ERROR("Received BA when not expected\n");
- return -EINVAL;
- }
-
- /* Mark that the expected block-ack response arrived */
- agg->wait_for_ba = 0;
- IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->seq_ctl);
-
- /* Calculate shift to align block-ack bits with our Tx window bits */
- sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl>>4);
- if (sh < 0) /* tbw something is wrong with indices */
- sh += 0x100;
-
- /* don't use 64-bit values for now */
- bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
-
- if (agg->frame_count > (64 - sh)) {
- IWL_DEBUG_TX_REPLY("more frames than bitmap size");
- return -1;
- }
-
- /* check for success or failure according to the
- * transmitted bitmap and block-ack bitmap */
- bitmap &= agg->bitmap;
-
- /* For each frame attempted in aggregation,
- * update driver's record of tx frame's status. */
- for (i = 0; i < agg->frame_count ; i++) {
- ack = bitmap & (1 << i);
- successes += !!ack;
- IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n",
- ack? "ACK":"NACK", i, (agg->start_idx + i) & 0xff,
- agg->start_idx + i);
- }
-
- info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]);
- memset(&info->status, 0, sizeof(info->status));
- info->flags = IEEE80211_TX_STAT_ACK;
- info->flags |= IEEE80211_TX_STAT_AMPDU;
- info->status.ampdu_ack_map = successes;
- info->status.ampdu_ack_len = agg->frame_count;
- iwl_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
-
- IWL_DEBUG_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap);
-
- return 0;
-}
-
/**
* iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration
*/
@@ -2816,82 +1959,6 @@
return 0;
}
-
-/**
- * iwl4965_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA
- *
- * Handles block-acknowledge notification from device, which reports success
- * of frames sent via aggregation.
- */
-static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
-{
- struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
- struct iwl4965_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
- int index;
- struct iwl_tx_queue *txq = NULL;
- struct iwl_ht_agg *agg;
- DECLARE_MAC_BUF(mac);
-
- /* "flow" corresponds to Tx queue */
- u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
-
- /* "ssn" is start of block-ack Tx window, corresponds to index
- * (in Tx queue's circular buffer) of first TFD/frame in window */
- u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
-
- if (scd_flow >= priv->hw_params.max_txq_num) {
- IWL_ERROR("BUG_ON scd_flow is bigger than number of queues");
- return;
- }
-
- txq = &priv->txq[scd_flow];
- agg = &priv->stations[ba_resp->sta_id].tid[ba_resp->tid].agg;
-
- /* Find index just before block-ack window */
- index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
-
- /* TODO: Need to get this copy more safely - now good for debug */
-
- IWL_DEBUG_TX_REPLY("REPLY_COMPRESSED_BA [%d]Received from %s, "
- "sta_id = %d\n",
- agg->wait_for_ba,
- print_mac(mac, (u8*) &ba_resp->sta_addr_lo32),
- ba_resp->sta_id);
- IWL_DEBUG_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = "
- "%d, scd_ssn = %d\n",
- ba_resp->tid,
- ba_resp->seq_ctl,
- (unsigned long long)le64_to_cpu(ba_resp->bitmap),
- ba_resp->scd_flow,
- ba_resp->scd_ssn);
- IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx \n",
- agg->start_idx,
- (unsigned long long)agg->bitmap);
-
- /* Update driver's record of ACK vs. not for each frame in window */
- iwl4965_tx_status_reply_compressed_ba(priv, agg, ba_resp);
-
- /* Release all TFDs before the SSN, i.e. all TFDs in front of
- * block-ack window (we assume that they've been successfully
- * transmitted ... if not, it's too late anyway). */
- if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
- /* calculate mac80211 ampdu sw queue to wake */
- int ampdu_q =
- scd_flow - priv->hw_params.first_ampdu_q + priv->hw->queues;
- int freed = iwl_tx_queue_reclaim(priv, scd_flow, index);
- priv->stations[ba_resp->sta_id].
- tid[ba_resp->tid].tfds_in_queue -= freed;
- if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
- priv->mac80211_registered &&
- agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)
- ieee80211_wake_queue(priv->hw, ampdu_q);
-
- iwl_txq_check_empty(priv, ba_resp->sta_id,
- ba_resp->tid, scd_flow);
- }
-}
-
/**
* iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue
*/
@@ -2986,49 +2053,6 @@
return 0;
}
-static int iwl4965_rx_agg_start(struct iwl_priv *priv,
- const u8 *addr, int tid, u16 ssn)
-{
- unsigned long flags;
- int sta_id;
-
- sta_id = iwl_find_station(priv, addr);
- if (sta_id == IWL_INVALID_STATION)
- return -ENXIO;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].sta.station_flags_msk = 0;
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
- priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
- priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
- CMD_ASYNC);
-}
-
-static int iwl4965_rx_agg_stop(struct iwl_priv *priv,
- const u8 *addr, int tid)
-{
- unsigned long flags;
- int sta_id;
-
- sta_id = iwl_find_station(priv, addr);
- if (sta_id == IWL_INVALID_STATION)
- return -ENXIO;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].sta.station_flags_msk = 0;
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
- priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
- CMD_ASYNC);
-}
-
int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
enum ieee80211_ampdu_mlme_action action,
const u8 *addr, u16 tid, u16 *ssn)
@@ -3039,13 +2063,16 @@
IWL_DEBUG_HT("A-MPDU action on addr %s tid %d\n",
print_mac(mac, addr), tid);
+ if (!(priv->cfg->sku & IWL_SKU_N))
+ return -EACCES;
+
switch (action) {
case IEEE80211_AMPDU_RX_START:
IWL_DEBUG_HT("start Rx\n");
- return iwl4965_rx_agg_start(priv, addr, tid, *ssn);
+ return iwl_rx_agg_start(priv, addr, tid, *ssn);
case IEEE80211_AMPDU_RX_STOP:
IWL_DEBUG_HT("stop Rx\n");
- return iwl4965_rx_agg_stop(priv, addr, tid);
+ return iwl_rx_agg_stop(priv, addr, tid);
case IEEE80211_AMPDU_TX_START:
IWL_DEBUG_HT("start Tx\n");
return iwl_tx_agg_start(priv, addr, tid, ssn);
@@ -3320,11 +2347,9 @@
static void iwl4965_rx_handler_setup(struct iwl_priv *priv)
{
/* Legacy Rx frames */
- priv->rx_handlers[REPLY_RX] = iwl4965_rx_reply_rx;
+ priv->rx_handlers[REPLY_RX] = iwl_rx_reply_rx;
/* Tx response */
priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx;
- /* block ack */
- priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl4965_rx_reply_compressed_ba;
}
static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
@@ -3391,6 +2416,7 @@
.set_power = iwl4965_set_power,
.send_tx_power = iwl4965_send_tx_power,
.update_chain_flags = iwl4965_update_chain_flags,
+ .temperature = iwl4965_temperature_calib,
};
static struct iwl_ops iwl4965_ops = {
@@ -3422,11 +2448,14 @@
module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, 0444);
MODULE_PARM_DESC(queues_num, "number of hw queues.");
-
/* QoS */
module_param_named(qos_enable, iwl4965_mod_params.enable_qos, int, 0444);
MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
+/* 11n */
+module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, 0444);
+MODULE_PARM_DESC(11n_disable, "disable 11n functionality");
module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, int, 0444);
MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
+
module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, 0444);
MODULE_PARM_DESC(fw_restart4965, "restart firmware in case of error");
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 438c381..7cc73e9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -675,7 +675,7 @@
goto restart;
}
- iwlcore_clear_stations_table(priv);
+ iwl_clear_stations_table(priv);
ret = priv->cfg->ops->lib->alive_notify(priv);
if (ret) {
IWL_WARNING("Could not complete ALIVE transition: %d\n", ret);
@@ -807,11 +807,8 @@
iwl5000_send_Xtal_calib(priv);
- if (priv->ucode_type == UCODE_RT) {
+ if (priv->ucode_type == UCODE_RT)
iwl5000_send_calib_results(priv);
- set_bit(STATUS_READY, &priv->status);
- priv->is_open = 1;
- }
return 0;
}
@@ -827,19 +824,11 @@
priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
priv->hw_params.first_ampdu_q = IWL50_FIRST_AMPDU_QUEUE;
- priv->hw_params.sw_crypto = priv->cfg->mod_params->sw_crypto;
- priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
- priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
- if (priv->cfg->mod_params->amsdu_size_8K)
- priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K;
- else
- priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K;
- priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256;
priv->hw_params.max_stations = IWL5000_STATION_COUNT;
priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE;
- priv->hw_params.max_bsm_size = BSM_SRAM_SIZE;
+ priv->hw_params.max_bsm_size = 0;
priv->hw_params.fat_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ);
priv->hw_params.sens = &iwl5000_sensitivity;
@@ -1426,13 +1415,18 @@
/* half dBm need to multiply */
tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt);
- tx_power_cmd.flags = 0;
+ tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED;
tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO;
return iwl_send_cmd_pdu_async(priv, REPLY_TX_POWER_DBM_CMD,
sizeof(tx_power_cmd), &tx_power_cmd,
NULL);
}
+static void iwl5000_temperature(struct iwl_priv *priv)
+{
+ /* store temperature from statistics (in Celsius) */
+ priv->temperature = le32_to_cpu(priv->statistics.general.temperature);
+}
static struct iwl_hcmd_ops iwl5000_hcmd = {
.rxon_assoc = iwl5000_send_rxon_assoc,
@@ -1462,6 +1456,7 @@
.init_alive_start = iwl5000_init_alive_start,
.alive_notify = iwl5000_alive_notify,
.send_tx_power = iwl5000_send_tx_power,
+ .temperature = iwl5000_temperature,
.apm_ops = {
.init = iwl5000_apm_init,
.reset = iwl5000_apm_reset,
@@ -1541,6 +1536,8 @@
MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series");
module_param_named(qos_enable50, iwl50_mod_params.enable_qos, int, 0444);
MODULE_PARM_DESC(qos_enable50, "enable all 50XX QoS functionality");
+module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, 0444);
+MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality");
module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K, int, 0444);
MODULE_PARM_DESC(amsdu_size_8K50, "enable 8K amsdu size in 50XX series");
module_param_named(fw_restart50, iwl50_mod_params.restart_fw, int, 0444);
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
index 48f5800..ef49440 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -470,7 +470,7 @@
EXPORT_SYMBOL(iwl_init_sensitivity);
void iwl_sensitivity_calibration(struct iwl_priv *priv,
- struct iwl4965_notif_statistics *resp)
+ struct iwl_notif_statistics *resp)
{
u32 rx_enable_time;
u32 fa_cck;
@@ -584,7 +584,7 @@
* 2) Differential rx gain settings to balance the 3 receivers.
*/
void iwl_chain_noise_calibration(struct iwl_priv *priv,
- struct iwl4965_notif_statistics *stat_resp)
+ struct iwl_notif_statistics *stat_resp)
{
struct iwl_chain_noise_data *data = NULL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-calib.h
index 5524a29..94c8e31 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.h
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.h
@@ -67,9 +67,9 @@
#include "iwl-commands.h"
void iwl_chain_noise_calibration(struct iwl_priv *priv,
- struct iwl4965_notif_statistics *stat_resp);
+ struct iwl_notif_statistics *stat_resp);
void iwl_sensitivity_calibration(struct iwl_priv *priv,
- struct iwl4965_notif_statistics *resp);
+ struct iwl_notif_statistics *resp);
void iwl_init_sensitivity(struct iwl_priv *priv);
void iwl_reset_run_time_calib(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 920dfc1..fe05d60 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -336,6 +336,8 @@
* struct iwl5000_tx_power_dbm_cmd
*/
#define IWL50_TX_POWER_AUTO 0x7f
+#define IWL50_TX_POWER_NO_CLOSED (0x1 << 6)
+
struct iwl5000_tx_power_dbm_cmd {
s8 global_lmt; /*in half-dBm (e.g. 30 = 15 dBm) */
u8 flags;
@@ -1534,7 +1536,7 @@
*
* Reports Block-Acknowledge from recipient station
*/
-struct iwl4965_compressed_ba_resp {
+struct iwl_compressed_ba_resp {
__le32 sta_addr_lo32;
__le16 sta_addr_hi16;
__le16 reserved;
@@ -2504,7 +2506,7 @@
*/
#define IWL_STATS_CONF_CLEAR_STATS __constant_cpu_to_le32(0x1) /* see above */
#define IWL_STATS_CONF_DISABLE_NOTIF __constant_cpu_to_le32(0x2)/* see above */
-struct iwl4965_statistics_cmd {
+struct iwl_statistics_cmd {
__le32 configuration_flags; /* IWL_STATS_CONF_* */
} __attribute__ ((packed));
@@ -2525,7 +2527,7 @@
*/
#define STATISTICS_REPLY_FLG_BAND_24G_MSK __constant_cpu_to_le32(0x2)
#define STATISTICS_REPLY_FLG_FAT_MODE_MSK __constant_cpu_to_le32(0x8)
-struct iwl4965_notif_statistics {
+struct iwl_notif_statistics {
__le32 flag;
struct statistics_rx rx;
struct statistics_tx tx;
@@ -2998,8 +3000,8 @@
struct iwl_rem_sta_resp rem_sta;
struct iwl4965_sleep_notification sleep_notif;
struct iwl4965_spectrum_resp spectrum;
- struct iwl4965_notif_statistics stats;
- struct iwl4965_compressed_ba_resp compressed_ba;
+ struct iwl_notif_statistics stats;
+ struct iwl_compressed_ba_resp compressed_ba;
struct iwl4965_missed_beacon_notif missed_beacon;
struct iwl5000_calibration calib;
__le32 status;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index eb74a40..eee220c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -273,22 +273,27 @@
EXPORT_SYMBOL(iwl_hw_nic_init);
/**
- * iwlcore_clear_stations_table - Clear the driver's station table
+ * iwl_clear_stations_table - Clear the driver's station table
*
* NOTE: This does not clear or otherwise alter the device's station table.
*/
-void iwlcore_clear_stations_table(struct iwl_priv *priv)
+void iwl_clear_stations_table(struct iwl_priv *priv)
{
unsigned long flags;
spin_lock_irqsave(&priv->sta_lock, flags);
+ if (iwl_is_alive(priv) &&
+ !test_bit(STATUS_EXIT_PENDING, &priv->status) &&
+ iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL))
+ IWL_ERROR("Couldn't clear the station table\n");
+
priv->num_stations = 0;
memset(priv->stations, 0, sizeof(priv->stations));
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
-EXPORT_SYMBOL(iwlcore_clear_stations_table);
+EXPORT_SYMBOL(iwl_clear_stations_table);
void iwl_reset_qos(struct iwl_priv *priv)
{
@@ -490,7 +495,9 @@
sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE;
- iwlcore_init_ht_hw_capab(priv, &sband->ht_info, IEEE80211_BAND_5GHZ);
+ if (priv->cfg->sku & IWL_SKU_N)
+ iwlcore_init_ht_hw_capab(priv, &sband->ht_info,
+ IEEE80211_BAND_5GHZ);
sband = &priv->bands[IEEE80211_BAND_2GHZ];
sband->channels = channels;
@@ -498,7 +505,9 @@
sband->bitrates = rates;
sband->n_bitrates = IWL_RATE_COUNT;
- iwlcore_init_ht_hw_capab(priv, &sband->ht_info, IEEE80211_BAND_2GHZ);
+ if (priv->cfg->sku & IWL_SKU_N)
+ iwlcore_init_ht_hw_capab(priv, &sband->ht_info,
+ IEEE80211_BAND_2GHZ);
priv->ieee_channels = channels;
priv->ieee_rates = rates;
@@ -814,8 +823,9 @@
IEEE80211_HW_NOISE_DBM;
/* Default value; 4 EDCA QOS priorities */
hw->queues = 4;
- /* Enhanced value; more queues, to support 11n aggregation */
- hw->ampdu_queues = 12;
+ /* queues to support 11n aggregation */
+ if (priv->cfg->sku & IWL_SKU_N)
+ hw->ampdu_queues = 12;
hw->conf.beacon_int = 100;
@@ -837,11 +847,28 @@
}
EXPORT_SYMBOL(iwl_setup_mac);
+int iwl_set_hw_params(struct iwl_priv *priv)
+{
+ priv->hw_params.sw_crypto = priv->cfg->mod_params->sw_crypto;
+ priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
+ priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
+ if (priv->cfg->mod_params->amsdu_size_8K)
+ priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K;
+ else
+ priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K;
+ priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256;
+
+ if (priv->cfg->mod_params->disable_11n)
+ priv->cfg->sku &= ~IWL_SKU_N;
+
+ /* Device-specific setup */
+ return priv->cfg->ops->lib->set_hw_params(priv);
+}
+EXPORT_SYMBOL(iwl_set_hw_params);
int iwl_init_drv(struct iwl_priv *priv)
{
int ret;
- int i;
priv->retry_rate = 1;
priv->ibss_beacon = NULL;
@@ -852,15 +879,12 @@
spin_lock_init(&priv->hcmd_lock);
spin_lock_init(&priv->lq_mngr.lock);
- for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++)
- INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
-
INIT_LIST_HEAD(&priv->free_frames);
mutex_init(&priv->mutex);
/* Clear the driver's (not device's) station table */
- iwlcore_clear_stations_table(priv);
+ iwl_clear_stations_table(priv);
priv->data_retry_limit = -1;
priv->ieee_channels = NULL;
@@ -1383,7 +1407,14 @@
spin_lock_irqsave(&priv->lock, flags);
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
- clear_bit(STATUS_RF_KILL_SW, &priv->status);
+ /* If the driver is up it will receive CARD_STATE_NOTIFICATION
+ * notification where it will clear SW rfkill status.
+ * Setting it here would break the handler. Only if the
+ * interface is down we can set here since we don't
+ * receive any further notification.
+ */
+ if (!priv->is_open)
+ clear_bit(STATUS_RF_KILL_SW, &priv->status);
spin_unlock_irqrestore(&priv->lock, flags);
/* wake up ucode */
@@ -1401,8 +1432,10 @@
return 0;
}
- if (priv->is_open)
- queue_work(priv->workqueue, &priv->restart);
+ /* If the driver is already loaded, it will receive
+ * CARD_STATE_NOTIFICATION notifications and the handler will
+ * call restart to reload the driver.
+ */
return 1;
}
EXPORT_SYMBOL(iwl_radio_kill_sw_enable_radio);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 2838093..eb4abe1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -140,6 +140,7 @@
int (*set_power)(struct iwl_priv *priv, void *cmd);
int (*send_tx_power) (struct iwl_priv *priv);
void (*update_chain_flags)(struct iwl_priv *priv);
+ void (*temperature) (struct iwl_priv *priv);
/* eeprom operations (as defined in iwl-eeprom.h) */
struct iwl_eeprom_ops eeprom_ops;
};
@@ -157,6 +158,7 @@
int disable_hw_scan; /* def: 0 = use h/w scan */
int num_of_queues; /* def: HW dependent */
int enable_qos; /* def: 1 = use quality of service */
+ int disable_11n; /* def: 0 = disable 11n capabilities */
int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */
int antenna; /* def: 0 = both antennas (use diversity) */
int restart_fw; /* def: 1 = restart firmware */
@@ -179,7 +181,7 @@
struct ieee80211_ops *hw_ops);
void iwl_hw_detect(struct iwl_priv *priv);
-void iwlcore_clear_stations_table(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);
@@ -191,6 +193,7 @@
struct ieee80211_ht_info *sta_ht_inf);
int iwl_hw_nic_init(struct iwl_priv *priv);
int iwl_setup_mac(struct iwl_priv *priv);
+int iwl_set_hw_params(struct iwl_priv *priv);
int iwl_init_drv(struct iwl_priv *priv);
void iwl_uninit_drv(struct iwl_priv *priv);
/* "keep warm" functions */
@@ -209,6 +212,8 @@
void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
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);
@@ -218,6 +223,8 @@
/* Handlers */
void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
+void iwl_rx_statistics(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb);
/* TX helpers */
@@ -368,7 +375,13 @@
extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags);
extern int iwl_verify_ucode(struct iwl_priv *priv);
extern int iwl_send_lq_cmd(struct iwl_priv *priv,
- struct iwl_link_quality_cmd *lq, u8 flags);
+ struct iwl_link_quality_cmd *lq, u8 flags);
+extern void iwl_rx_reply_rx(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb);
+extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb);
+void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb);
static inline int iwl_send_rxon_assoc(struct iwl_priv *priv)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 81ff4c2..d1289cf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -591,11 +591,6 @@
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 int iwl4965_is_network_packet(struct iwl_priv *priv,
- struct ieee80211_hdr *header);
-extern int iwl4965_is_duplicate_packet(struct iwl_priv *priv,
- struct ieee80211_hdr *header);
-extern int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm);
extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv,
struct ieee80211_hdr *hdr,
const u8 *dest, int left);
@@ -624,11 +619,7 @@
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_hw_rx_statistics(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb);
extern void iwl4965_disable_events(struct iwl_priv *priv);
-extern void iwl4965_rx_reply_rx(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb);
extern int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel);
extern int iwl_queue_space(const struct iwl_queue *q);
@@ -702,7 +693,6 @@
unsigned long stamp_last;
u32 flush_time;
u32 tx_packets;
- u8 lq_ready;
};
/* Sensitivity and chain noise calibration */
@@ -994,7 +984,7 @@
struct iwl_power_mgr power_data;
- struct iwl4965_notif_statistics statistics;
+ struct iwl_notif_statistics statistics;
unsigned long last_statistics_time;
/* context information */
@@ -1026,14 +1016,6 @@
u32 last_beacon_time;
u64 last_tsf;
- /* Duplicate packet detection */
- u16 last_seq_num;
- u16 last_frag_num;
- unsigned long last_packet_time;
-
- /* Hash table for finding stations in IBSS network */
- struct list_head ibss_mac_hash[IWL_IBSS_MAC_HASH_SIZE];
-
/* eeprom */
u8 *eeprom;
struct iwl_eeprom_calib_info *calib_info;
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 6c53736..8fa991b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -93,6 +93,7 @@
IWL_CMD(CALIBRATION_CFG_CMD);
IWL_CMD(CALIBRATION_RES_NOTIFICATION);
IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION);
+ IWL_CMD(REPLY_TX_POWER_DBM_CMD);
default:
return "UNKNOWN";
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
index ffefbb4..aa9f31e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
@@ -50,7 +50,7 @@
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return 0;
- IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state);
+ IWL_DEBUG_RF_KILL("we received soft RFKILL set to state %d\n", state);
mutex_lock(&priv->mutex);
switch (state) {
@@ -98,36 +98,11 @@
priv->rfkill_mngr.rfkill->dev.class->suspend = NULL;
priv->rfkill_mngr.rfkill->dev.class->resume = NULL;
-#if defined(CONFIG_RFKILL_INPUT) || defined(CONFIG_RFKILL_INPUT_MODULE)
- priv->rfkill_mngr.input_dev = input_allocate_device();
- if (!priv->rfkill_mngr.input_dev) {
- IWL_ERROR("Unable to allocate rfkill input device.\n");
- ret = -ENOMEM;
- goto freed_rfkill;
- }
-
- priv->rfkill_mngr.input_dev->name = priv->cfg->name;
- priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy);
- priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST;
- priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor;
- priv->rfkill_mngr.input_dev->dev.parent = device;
- priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY);
- set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit);
-#endif
-
ret = rfkill_register(priv->rfkill_mngr.rfkill);
if (ret) {
IWL_ERROR("Unable to register rfkill: %d\n", ret);
- goto free_input_dev;
- }
-
-#if defined(CONFIG_RFKILL_INPUT) || defined(CONFIG_RFKILL_INPUT_MODULE)
- ret = input_register_device(priv->rfkill_mngr.input_dev);
- if (ret) {
- IWL_ERROR("Unable to register rfkill input device: %d\n", ret);
goto unregister_rfkill;
}
-#endif
IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
return ret;
@@ -136,12 +111,6 @@
rfkill_unregister(priv->rfkill_mngr.rfkill);
priv->rfkill_mngr.rfkill = NULL;
-free_input_dev:
-#if defined(CONFIG_RFKILL_INPUT) || defined(CONFIG_RFKILL_INPUT_MODULE)
- input_free_device(priv->rfkill_mngr.input_dev);
- priv->rfkill_mngr.input_dev = NULL;
-#endif
-
freed_rfkill:
if (priv->rfkill_mngr.rfkill != NULL)
rfkill_free(priv->rfkill_mngr.rfkill);
@@ -156,13 +125,6 @@
void iwl_rfkill_unregister(struct iwl_priv *priv)
{
-#if defined(CONFIG_RFKILL_INPUT) || defined(CONFIG_RFKILL_INPUT_MODULE)
- if (priv->rfkill_mngr.input_dev)
- input_unregister_device(priv->rfkill_mngr.input_dev);
- input_free_device(priv->rfkill_mngr.input_dev);
- priv->rfkill_mngr.input_dev = NULL;
-#endif
-
if (priv->rfkill_mngr.rfkill)
rfkill_unregister(priv->rfkill_mngr.rfkill);
@@ -173,7 +135,6 @@
/* set rf-kill to the right state. */
void iwl_rfkill_set_hw_state(struct iwl_priv *priv)
{
-
if (!priv->rfkill_mngr.rfkill)
return;
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.h b/drivers/net/wireless/iwlwifi/iwl-rfkill.h
index b3c04db..00692d2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rfkill.h
+++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.h
@@ -31,12 +31,10 @@
struct iwl_priv;
#include <linux/rfkill.h>
-#include <linux/input.h>
#ifdef CONFIG_IWLWIFI_RFKILL
struct iwl_rfkill_mngr {
struct rfkill *rfkill;
- struct input_dev *input_dev;
};
void iwl_rfkill_set_hw_state(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index c248448..3e8500e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -27,6 +27,7 @@
*
*****************************************************************************/
+#include <linux/etherdevice.h>
#include <net/mac80211.h>
#include "iwl-eeprom.h"
#include "iwl-dev.h"
@@ -466,3 +467,858 @@
}
}
EXPORT_SYMBOL(iwl_rx_missed_beacon_notif);
+
+int iwl_rx_agg_start(struct iwl_priv *priv, const u8 *addr, int tid, u16 ssn)
+{
+ unsigned long flags;
+ int sta_id;
+
+ sta_id = iwl_find_station(priv, addr);
+ if (sta_id == IWL_INVALID_STATION)
+ return -ENXIO;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].sta.station_flags_msk = 0;
+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
+ priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
+ priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
+ CMD_ASYNC);
+}
+EXPORT_SYMBOL(iwl_rx_agg_start);
+
+int iwl_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid)
+{
+ unsigned long flags;
+ int sta_id;
+
+ sta_id = iwl_find_station(priv, addr);
+ if (sta_id == IWL_INVALID_STATION)
+ return -ENXIO;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].sta.station_flags_msk = 0;
+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
+ priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
+ CMD_ASYNC);
+}
+EXPORT_SYMBOL(iwl_rx_agg_stop);
+
+
+/* Calculate noise level, based on measurements during network silence just
+ * before arriving beacon. This measurement can be done only if we know
+ * exactly when to expect beacons, therefore only when we're associated. */
+static void iwl_rx_calc_noise(struct iwl_priv *priv)
+{
+ struct statistics_rx_non_phy *rx_info
+ = &(priv->statistics.rx.general);
+ int num_active_rx = 0;
+ int total_silence = 0;
+ int bcn_silence_a =
+ le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
+ int bcn_silence_b =
+ le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
+ int bcn_silence_c =
+ le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
+
+ if (bcn_silence_a) {
+ total_silence += bcn_silence_a;
+ num_active_rx++;
+ }
+ if (bcn_silence_b) {
+ total_silence += bcn_silence_b;
+ num_active_rx++;
+ }
+ if (bcn_silence_c) {
+ total_silence += bcn_silence_c;
+ num_active_rx++;
+ }
+
+ /* Average among active antennas */
+ if (num_active_rx)
+ priv->last_rx_noise = (total_silence / num_active_rx) - 107;
+ else
+ priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
+
+ IWL_DEBUG_CALIB("inband silence a %u, b %u, c %u, dBm %d\n",
+ bcn_silence_a, bcn_silence_b, bcn_silence_c,
+ priv->last_rx_noise);
+}
+
+#define REG_RECALIB_PERIOD (60)
+
+void iwl_rx_statistics(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb)
+{
+ int change;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+
+ IWL_DEBUG_RX("Statistics notification received (%d vs %d).\n",
+ (int)sizeof(priv->statistics), pkt->len);
+
+ change = ((priv->statistics.general.temperature !=
+ pkt->u.stats.general.temperature) ||
+ ((priv->statistics.flag &
+ STATISTICS_REPLY_FLG_FAT_MODE_MSK) !=
+ (pkt->u.stats.flag & STATISTICS_REPLY_FLG_FAT_MODE_MSK)));
+
+ memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
+
+ set_bit(STATUS_STATISTICS, &priv->status);
+
+ /* Reschedule the statistics timer to occur in
+ * REG_RECALIB_PERIOD seconds to ensure we get a
+ * thermal update even if the uCode doesn't give
+ * us one */
+ mod_timer(&priv->statistics_periodic, jiffies +
+ msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
+
+ if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
+ (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
+ iwl_rx_calc_noise(priv);
+ queue_work(priv->workqueue, &priv->run_time_calib_work);
+ }
+
+ iwl_leds_background(priv);
+
+ if (priv->cfg->ops->lib->temperature && change)
+ priv->cfg->ops->lib->temperature(priv);
+}
+EXPORT_SYMBOL(iwl_rx_statistics);
+
+#define PERFECT_RSSI (-20) /* dBm */
+#define WORST_RSSI (-95) /* dBm */
+#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)
+
+/* Calculate an indication of rx signal quality (a percentage, not dBm!).
+ * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
+ * about formulas used below. */
+static int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm)
+{
+ int sig_qual;
+ int degradation = PERFECT_RSSI - rssi_dbm;
+
+ /* If we get a noise measurement, use signal-to-noise ratio (SNR)
+ * as indicator; formula is (signal dbm - noise dbm).
+ * SNR at or above 40 is a great signal (100%).
+ * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
+ * Weakest usable signal is usually 10 - 15 dB SNR. */
+ if (noise_dbm) {
+ if (rssi_dbm - noise_dbm >= 40)
+ return 100;
+ else if (rssi_dbm < noise_dbm)
+ return 0;
+ sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;
+
+ /* Else use just the signal level.
+ * This formula is a least squares fit of data points collected and
+ * compared with a reference system that had a percentage (%) display
+ * for signal quality. */
+ } else
+ sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
+ (15 * RSSI_RANGE + 62 * degradation)) /
+ (RSSI_RANGE * RSSI_RANGE);
+
+ if (sig_qual > 100)
+ sig_qual = 100;
+ else if (sig_qual < 1)
+ sig_qual = 0;
+
+ return sig_qual;
+}
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+
+/**
+ * iwl_dbg_report_frame - dump frame to syslog during debug sessions
+ *
+ * You may hack this function to show different aspects of received frames,
+ * including selective frame dumps.
+ * group100 parameter selects whether to show 1 out of 100 good frames.
+ *
+ * TODO: This was originally written for 3945, need to audit for
+ * proper operation with 4965.
+ */
+static void iwl_dbg_report_frame(struct iwl_priv *priv,
+ struct iwl_rx_packet *pkt,
+ struct ieee80211_hdr *header, int group100)
+{
+ u32 to_us;
+ u32 print_summary = 0;
+ u32 print_dump = 0; /* set to 1 to dump all frames' contents */
+ u32 hundred = 0;
+ u32 dataframe = 0;
+ __le16 fc;
+ u16 seq_ctl;
+ u16 channel;
+ u16 phy_flags;
+ int rate_sym;
+ u16 length;
+ u16 status;
+ u16 bcn_tmr;
+ u32 tsf_low;
+ u64 tsf;
+ u8 rssi;
+ u8 agc;
+ u16 sig_avg;
+ u16 noise_diff;
+ struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
+ struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
+ struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt);
+ u8 *data = IWL_RX_DATA(pkt);
+
+ if (likely(!(priv->debug_level & IWL_DL_RX)))
+ return;
+
+ /* MAC header */
+ fc = header->frame_control;
+ seq_ctl = le16_to_cpu(header->seq_ctrl);
+
+ /* metadata */
+ channel = le16_to_cpu(rx_hdr->channel);
+ phy_flags = le16_to_cpu(rx_hdr->phy_flags);
+ rate_sym = rx_hdr->rate;
+ length = le16_to_cpu(rx_hdr->len);
+
+ /* end-of-frame status and timestamp */
+ status = le32_to_cpu(rx_end->status);
+ bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
+ tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
+ tsf = le64_to_cpu(rx_end->timestamp);
+
+ /* signal statistics */
+ rssi = rx_stats->rssi;
+ agc = rx_stats->agc;
+ sig_avg = le16_to_cpu(rx_stats->sig_avg);
+ noise_diff = le16_to_cpu(rx_stats->noise_diff);
+
+ to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
+
+ /* if data frame is to us and all is good,
+ * (optionally) print summary for only 1 out of every 100 */
+ if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) ==
+ cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
+ dataframe = 1;
+ if (!group100)
+ print_summary = 1; /* print each frame */
+ else if (priv->framecnt_to_us < 100) {
+ priv->framecnt_to_us++;
+ print_summary = 0;
+ } else {
+ priv->framecnt_to_us = 0;
+ print_summary = 1;
+ hundred = 1;
+ }
+ } else {
+ /* print summary for all other frames */
+ print_summary = 1;
+ }
+
+ if (print_summary) {
+ char *title;
+ int rate_idx;
+ u32 bitrate;
+
+ if (hundred)
+ title = "100Frames";
+ else if (ieee80211_has_retry(fc))
+ title = "Retry";
+ else if (ieee80211_is_assoc_resp(fc))
+ title = "AscRsp";
+ else if (ieee80211_is_reassoc_resp(fc))
+ title = "RasRsp";
+ else if (ieee80211_is_probe_resp(fc)) {
+ title = "PrbRsp";
+ print_dump = 1; /* dump frame contents */
+ } else if (ieee80211_is_beacon(fc)) {
+ title = "Beacon";
+ print_dump = 1; /* dump frame contents */
+ } else if (ieee80211_is_atim(fc))
+ title = "ATIM";
+ else if (ieee80211_is_auth(fc))
+ title = "Auth";
+ else if (ieee80211_is_deauth(fc))
+ title = "DeAuth";
+ else if (ieee80211_is_disassoc(fc))
+ title = "DisAssoc";
+ else
+ title = "Frame";
+
+ rate_idx = iwl_hwrate_to_plcp_idx(rate_sym);
+ if (unlikely(rate_idx == -1))
+ bitrate = 0;
+ else
+ bitrate = iwl_rates[rate_idx].ieee / 2;
+
+ /* print frame summary.
+ * MAC addresses show just the last byte (for brevity),
+ * but you can hack it to show more, if you'd like to. */
+ if (dataframe)
+ IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
+ "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
+ title, le16_to_cpu(fc), header->addr1[5],
+ length, rssi, channel, bitrate);
+ else {
+ /* src/dst addresses assume managed mode */
+ IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
+ "src=0x%02x, rssi=%u, tim=%lu usec, "
+ "phy=0x%02x, chnl=%d\n",
+ title, le16_to_cpu(fc), header->addr1[5],
+ header->addr3[5], rssi,
+ tsf_low - priv->scan_start_tsf,
+ phy_flags, channel);
+ }
+ }
+ if (print_dump)
+ iwl_print_hex_dump(priv, IWL_DL_RX, data, length);
+}
+#else
+static inline void iwl_dbg_report_frame(struct iwl_priv *priv,
+ struct iwl_rx_packet *pkt,
+ struct ieee80211_hdr *header,
+ int group100)
+{
+}
+#endif
+
+static void iwl_add_radiotap(struct iwl_priv *priv,
+ struct sk_buff *skb,
+ struct iwl4965_rx_phy_res *rx_start,
+ struct ieee80211_rx_status *stats,
+ u32 ampdu_status)
+{
+ s8 signal = stats->signal;
+ s8 noise = 0;
+ int rate = stats->rate_idx;
+ u64 tsf = stats->mactime;
+ __le16 antenna;
+ __le16 phy_flags_hw = rx_start->phy_flags;
+ struct iwl4965_rt_rx_hdr {
+ struct ieee80211_radiotap_header rt_hdr;
+ __le64 rt_tsf; /* TSF */
+ u8 rt_flags; /* radiotap packet flags */
+ u8 rt_rate; /* rate in 500kb/s */
+ __le16 rt_channelMHz; /* channel in MHz */
+ __le16 rt_chbitmask; /* channel bitfield */
+ s8 rt_dbmsignal; /* signal in dBm, kluged to signed */
+ s8 rt_dbmnoise;
+ u8 rt_antenna; /* antenna number */
+ } __attribute__ ((packed)) *iwl4965_rt;
+
+ /* TODO: We won't have enough headroom for HT frames. Fix it later. */
+ if (skb_headroom(skb) < sizeof(*iwl4965_rt)) {
+ if (net_ratelimit())
+ printk(KERN_ERR "not enough headroom [%d] for "
+ "radiotap head [%zd]\n",
+ skb_headroom(skb), sizeof(*iwl4965_rt));
+ return;
+ }
+
+ /* put radiotap header in front of 802.11 header and data */
+ iwl4965_rt = (void *)skb_push(skb, sizeof(*iwl4965_rt));
+
+ /* initialise radiotap header */
+ iwl4965_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
+ iwl4965_rt->rt_hdr.it_pad = 0;
+
+ /* total header + data */
+ put_unaligned(cpu_to_le16(sizeof(*iwl4965_rt)),
+ &iwl4965_rt->rt_hdr.it_len);
+
+ /* Indicate all the fields we add to the radiotap header */
+ put_unaligned(cpu_to_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(cpu_to_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(cpu_to_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(cpu_to_le16(IEEE80211_CHAN_CCK |
+ IEEE80211_CHAN_2GHZ),
+ &iwl4965_rt->rt_chbitmask);
+ else /* 802.11g */
+ put_unaligned(cpu_to_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 */
+ int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
+ priv->rx_stats[idx].cnt++;
+ priv->rx_stats[idx].bytes += len;
+}
+
+/*
+ * returns non-zero if packet should be dropped
+ */
+static int iwl_set_decrypted_flag(struct iwl_priv *priv,
+ struct ieee80211_hdr *hdr,
+ u32 decrypt_res,
+ struct ieee80211_rx_status *stats)
+{
+ u16 fc = le16_to_cpu(hdr->frame_control);
+
+ if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK)
+ return 0;
+
+ if (!(fc & IEEE80211_FCTL_PROTECTED))
+ return 0;
+
+ IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res);
+ switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) {
+ case RX_RES_STATUS_SEC_TYPE_TKIP:
+ /* The uCode has got a bad phase 1 Key, pushes the packet.
+ * Decryption will be done in SW. */
+ if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
+ RX_RES_STATUS_BAD_KEY_TTAK)
+ break;
+
+ case RX_RES_STATUS_SEC_TYPE_WEP:
+ if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
+ RX_RES_STATUS_BAD_ICV_MIC) {
+ /* bad ICV, the packet is destroyed since the
+ * decryption is inplace, drop it */
+ IWL_DEBUG_RX("Packet destroyed\n");
+ return -1;
+ }
+ case RX_RES_STATUS_SEC_TYPE_CCMP:
+ if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
+ RX_RES_STATUS_DECRYPT_OK) {
+ IWL_DEBUG_RX("hw decrypt successfully!!!\n");
+ stats->flag |= RX_FLAG_DECRYPTED;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
+{
+ u32 decrypt_out = 0;
+
+ if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) ==
+ RX_RES_STATUS_STATION_FOUND)
+ decrypt_out |= (RX_RES_STATUS_STATION_FOUND |
+ RX_RES_STATUS_NO_STATION_INFO_MISMATCH);
+
+ decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK);
+
+ /* packet was not encrypted */
+ if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
+ RX_RES_STATUS_SEC_TYPE_NONE)
+ return decrypt_out;
+
+ /* packet was encrypted with unknown alg */
+ if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
+ RX_RES_STATUS_SEC_TYPE_ERR)
+ return decrypt_out;
+
+ /* decryption was not done in HW */
+ if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) !=
+ RX_MPDU_RES_STATUS_DEC_DONE_MSK)
+ return decrypt_out;
+
+ switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) {
+
+ case RX_RES_STATUS_SEC_TYPE_CCMP:
+ /* alg is CCM: check MIC only */
+ if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK))
+ /* Bad MIC */
+ decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
+ else
+ decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
+
+ break;
+
+ case RX_RES_STATUS_SEC_TYPE_TKIP:
+ if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) {
+ /* Bad TTAK */
+ decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
+ break;
+ }
+ /* fall through if TTAK OK */
+ default:
+ if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
+ decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
+ else
+ decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
+ break;
+ };
+
+ IWL_DEBUG_RX("decrypt_in:0x%x decrypt_out = 0x%x\n",
+ decrypt_in, decrypt_out);
+
+ return decrypt_out;
+}
+
+static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
+ int include_phy,
+ struct iwl_rx_mem_buffer *rxb,
+ struct ieee80211_rx_status *stats)
+{
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+ struct iwl4965_rx_phy_res *rx_start = (include_phy) ?
+ (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) : NULL;
+ struct ieee80211_hdr *hdr;
+ u16 len;
+ __le32 *rx_end;
+ unsigned int skblen;
+ u32 ampdu_status;
+ u32 ampdu_status_legacy;
+
+ if (!include_phy && priv->last_phy_res[0])
+ rx_start = (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1];
+
+ if (!rx_start) {
+ IWL_ERROR("MPDU frame without a PHY data\n");
+ return;
+ }
+ if (include_phy) {
+ hdr = (struct ieee80211_hdr *)((u8 *) &rx_start[1] +
+ rx_start->cfg_phy_cnt);
+
+ len = le16_to_cpu(rx_start->byte_count);
+
+ rx_end = (__le32 *) ((u8 *) &pkt->u.raw[0] +
+ sizeof(struct iwl4965_rx_phy_res) +
+ rx_start->cfg_phy_cnt + len);
+
+ } else {
+ struct iwl4965_rx_mpdu_res_start *amsdu =
+ (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw;
+
+ hdr = (struct ieee80211_hdr *)(pkt->u.raw +
+ sizeof(struct iwl4965_rx_mpdu_res_start));
+ len = le16_to_cpu(amsdu->byte_count);
+ rx_start->byte_count = amsdu->byte_count;
+ rx_end = (__le32 *) (((u8 *) hdr) + len);
+ }
+
+ ampdu_status = le32_to_cpu(*rx_end);
+ skblen = ((u8 *) rx_end - (u8 *) &pkt->u.raw[0]) + sizeof(u32);
+
+ if (!include_phy) {
+ /* New status scheme, need to translate */
+ ampdu_status_legacy = ampdu_status;
+ ampdu_status = iwl_translate_rx_status(priv, ampdu_status);
+ }
+
+ /* start from MAC */
+ skb_reserve(rxb->skb, (void *)hdr - (void *)pkt);
+ skb_put(rxb->skb, len); /* end where data ends */
+
+ /* We only process data packets if the interface is open */
+ if (unlikely(!priv->is_open)) {
+ IWL_DEBUG_DROP_LIMIT
+ ("Dropping packet while interface is not open.\n");
+ return;
+ }
+
+ hdr = (struct ieee80211_hdr *)rxb->skb->data;
+
+ /* in case of HW accelerated crypto and bad decryption, drop */
+ if (!priv->hw_params.sw_crypto &&
+ 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--;
+ rxb->skb = NULL;
+}
+
+/* Calc max signal level (dBm) among 3 possible receivers */
+static int iwl_calc_rssi(struct iwl_priv *priv,
+ struct iwl4965_rx_phy_res *rx_resp)
+{
+ /* data from PHY/DSP regarding signal strength, etc.,
+ * contents are always there, not configurable by host. */
+ struct iwl4965_rx_non_cfg_phy *ncphy =
+ (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy;
+ u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL_AGC_DB_MASK)
+ >> IWL_AGC_DB_POS;
+
+ u32 valid_antennae =
+ (le16_to_cpu(rx_resp->phy_flags) & RX_PHY_FLAGS_ANTENNAE_MASK)
+ >> RX_PHY_FLAGS_ANTENNAE_OFFSET;
+ u8 max_rssi = 0;
+ u32 i;
+
+ /* Find max rssi among 3 possible receivers.
+ * These values are measured by the digital signal processor (DSP).
+ * They should stay fairly constant even as the signal strength varies,
+ * if the radio's automatic gain control (AGC) is working right.
+ * AGC value (see below) will provide the "interesting" info. */
+ for (i = 0; i < 3; i++)
+ if (valid_antennae & (1 << i))
+ max_rssi = max(ncphy->rssi_info[i << 1], max_rssi);
+
+ IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n",
+ ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4],
+ max_rssi, agc);
+
+ /* dBm = max_rssi dB - agc dB - constant.
+ * Higher AGC (higher radio gain) means lower signal. */
+ return max_rssi - agc - IWL_RSSI_OFFSET;
+}
+
+static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
+ priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
+ priv->stations[sta_id].sta.sta.modify_mask = 0;
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+}
+
+static void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr)
+{
+ /* FIXME: need locking over ps_status ??? */
+ u8 sta_id = iwl_find_station(priv, addr);
+
+ if (sta_id != IWL_INVALID_STATION) {
+ u8 sta_awake = priv->stations[sta_id].
+ ps_status == STA_PS_STATUS_WAKE;
+
+ if (sta_awake && ps_bit)
+ priv->stations[sta_id].ps_status = STA_PS_STATUS_SLEEP;
+ else if (!sta_awake && !ps_bit) {
+ iwl_sta_modify_ps_wake(priv, sta_id);
+ priv->stations[sta_id].ps_status = STA_PS_STATUS_WAKE;
+ }
+ }
+}
+
+/* This is necessary only for a number of statistics, see the caller. */
+static int iwl_is_network_packet(struct iwl_priv *priv,
+ struct ieee80211_hdr *header)
+{
+ /* 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 */
+ /* packets to our IBSS update information */
+ return !compare_ether_addr(header->addr3, priv->bssid);
+ case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */
+ /* packets to our IBSS update information */
+ return !compare_ether_addr(header->addr2, priv->bssid);
+ default:
+ return 1;
+ }
+}
+
+/* Called for REPLY_RX (legacy ABG frames), or
+ * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
+void iwl_rx_reply_rx(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb)
+{
+ struct ieee80211_hdr *header;
+ struct ieee80211_rx_status rx_status;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+ /* Use phy data (Rx signal strength, etc.) contained within
+ * this rx packet for legacy frames,
+ * or phy data cached from REPLY_RX_PHY_CMD for HT frames. */
+ int include_phy = (pkt->hdr.cmd == REPLY_RX);
+ struct iwl4965_rx_phy_res *rx_start = (include_phy) ?
+ (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) :
+ (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1];
+ __le32 *rx_end;
+ unsigned int len = 0;
+ u16 fc;
+ u8 network_packet;
+
+ rx_status.mactime = le64_to_cpu(rx_start->timestamp);
+ rx_status.freq =
+ ieee80211_channel_to_frequency(le16_to_cpu(rx_start->channel));
+ rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
+ IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+ rx_status.rate_idx =
+ iwl_hwrate_to_plcp_idx(le32_to_cpu(rx_start->rate_n_flags));
+ if (rx_status.band == IEEE80211_BAND_5GHZ)
+ rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
+
+ rx_status.antenna = 0;
+ rx_status.flag = 0;
+ rx_status.flag |= RX_FLAG_TSFT;
+
+ if ((unlikely(rx_start->cfg_phy_cnt > 20))) {
+ IWL_DEBUG_DROP("dsp size out of range [0,20]: %d/n",
+ rx_start->cfg_phy_cnt);
+ return;
+ }
+
+ if (!include_phy) {
+ if (priv->last_phy_res[0])
+ rx_start = (struct iwl4965_rx_phy_res *)
+ &priv->last_phy_res[1];
+ else
+ rx_start = NULL;
+ }
+
+ if (!rx_start) {
+ IWL_ERROR("MPDU frame without a PHY data\n");
+ return;
+ }
+
+ if (include_phy) {
+ header = (struct ieee80211_hdr *)((u8 *) &rx_start[1]
+ + rx_start->cfg_phy_cnt);
+
+ len = le16_to_cpu(rx_start->byte_count);
+ rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt +
+ sizeof(struct iwl4965_rx_phy_res) + len);
+ } else {
+ struct iwl4965_rx_mpdu_res_start *amsdu =
+ (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw;
+
+ header = (void *)(pkt->u.raw +
+ sizeof(struct iwl4965_rx_mpdu_res_start));
+ len = le16_to_cpu(amsdu->byte_count);
+ rx_end = (__le32 *) (pkt->u.raw +
+ sizeof(struct iwl4965_rx_mpdu_res_start) + len);
+ }
+
+ if (!(*rx_end & RX_RES_STATUS_NO_CRC32_ERROR) ||
+ !(*rx_end & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
+ IWL_DEBUG_RX("Bad CRC or FIFO: 0x%08X.\n",
+ le32_to_cpu(*rx_end));
+ return;
+ }
+
+ priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp);
+
+ /* Find max signal strength (dBm) among 3 antenna/receiver chains */
+ rx_status.signal = iwl_calc_rssi(priv, rx_start);
+
+ /* Meaningful noise values are available only from beacon statistics,
+ * which are gathered only when associated, and indicate noise
+ * only for the associated network channel ...
+ * Ignore these noise values while scanning (other channels) */
+ if (iwl_is_associated(priv) &&
+ !test_bit(STATUS_SCANNING, &priv->status)) {
+ rx_status.noise = priv->last_rx_noise;
+ rx_status.qual = iwl_calc_sig_qual(rx_status.signal,
+ rx_status.noise);
+ } else {
+ rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
+ rx_status.qual = iwl_calc_sig_qual(rx_status.signal, 0);
+ }
+
+ /* Reset beacon noise level if not associated. */
+ if (!iwl_is_associated(priv))
+ priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
+
+ /* Set "1" to report good data frames in groups of 100 */
+ /* FIXME: need to optimze the call: */
+ iwl_dbg_report_frame(priv, pkt, header, 1);
+
+ IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n",
+ rx_status.signal, rx_status.noise, rx_status.signal,
+ (unsigned long long)rx_status.mactime);
+
+ /* Take shortcut when only in monitor mode */
+ if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
+ iwl_pass_packet_to_mac80211(priv, include_phy,
+ rxb, &rx_status);
+ return;
+ }
+
+ network_packet = iwl_is_network_packet(priv, header);
+ if (network_packet) {
+ priv->last_rx_rssi = rx_status.signal;
+ priv->last_beacon_time = priv->ucode_beacon_time;
+ priv->last_tsf = le64_to_cpu(rx_start->timestamp);
+ }
+
+ fc = le16_to_cpu(header->frame_control);
+ switch (fc & IEEE80211_FCTL_FTYPE) {
+ case IEEE80211_FTYPE_MGMT:
+ case IEEE80211_FTYPE_DATA:
+ if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
+ iwl_update_ps_mode(priv, fc & IEEE80211_FCTL_PM,
+ header->addr2);
+ /* fall through */
+ default:
+ iwl_pass_packet_to_mac80211(priv, include_phy, rxb,
+ &rx_status);
+ break;
+
+ }
+}
+EXPORT_SYMBOL(iwl_rx_reply_rx);
+
+/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
+ * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
+void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+ priv->last_phy_res[0] = 1;
+ memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
+ sizeof(struct iwl4965_rx_phy_res));
+}
+EXPORT_SYMBOL(iwl_rx_reply_rx_phy);
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index f874e7d..6d1467d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -36,8 +36,8 @@
#include "iwl-helpers.h"
-#define IWL_STA_DRIVER_ACTIVE 0x1 /* ucode entry is active */
-#define IWL_STA_UCODE_ACTIVE 0x2 /* ucode entry is active */
+#define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */
+#define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */
u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
{
@@ -83,10 +83,28 @@
}
EXPORT_SYMBOL(iwl_get_ra_sta_id);
+static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
+{
+ unsigned long flags;
+ DECLARE_MAC_BUF(mac);
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+
+ if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE))
+ IWL_ERROR("ACTIVATE a non DRIVER active station %d\n", sta_id);
+
+ priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE;
+ IWL_DEBUG_ASSOC("Added STA to Ucode: %s\n",
+ print_mac(mac, priv->stations[sta_id].sta.sta.addr));
+
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+}
+
static int iwl_add_sta_callback(struct iwl_priv *priv,
struct iwl_cmd *cmd, struct sk_buff *skb)
{
struct iwl_rx_packet *res = NULL;
+ u8 sta_id = cmd->cmd.addsta.sta.sta_id;
if (!skb) {
IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n");
@@ -102,8 +120,8 @@
switch (res->u.add_sta.status) {
case ADD_STA_SUCCESS_MSK:
- /* FIXME: implement iwl_sta_ucode_activate(priv, addr); */
- /* fail through */
+ iwl_sta_ucode_activate(priv, sta_id);
+ /* fall through */
default:
IWL_DEBUG_HC("Received REPLY_ADD_STA:(0x%08X)\n",
res->u.add_sta.status);
@@ -147,6 +165,7 @@
if (ret == 0) {
switch (res->u.add_sta.status) {
case ADD_STA_SUCCESS_MSK:
+ iwl_sta_ucode_activate(priv, sta->sta.sta_id);
IWL_DEBUG_INFO("REPLY_ADD_STA PASSED\n");
break;
default:
@@ -215,88 +234,92 @@
u8 flags, struct ieee80211_ht_info *ht_info)
{
int i;
- int index = IWL_INVALID_STATION;
+ int sta_id = IWL_INVALID_STATION;
struct iwl_station_entry *station;
unsigned long flags_spin;
DECLARE_MAC_BUF(mac);
spin_lock_irqsave(&priv->sta_lock, flags_spin);
if (is_ap)
- index = IWL_AP_ID;
+ sta_id = IWL_AP_ID;
else if (is_broadcast_ether_addr(addr))
- index = priv->hw_params.bcast_sta_id;
+ sta_id = priv->hw_params.bcast_sta_id;
else
for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
addr)) {
- index = i;
+ sta_id = i;
break;
}
if (!priv->stations[i].used &&
- index == IWL_INVALID_STATION)
- index = i;
+ sta_id == IWL_INVALID_STATION)
+ sta_id = i;
}
-
/* These two conditions have the same outcome, but keep them separate
- since they have different meanings */
- if (unlikely(index == IWL_INVALID_STATION)) {
+ since they have different meanings */
+ if (unlikely(sta_id == IWL_INVALID_STATION)) {
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- return index;
+ return sta_id;
}
- if (priv->stations[index].used &&
- !compare_ether_addr(priv->stations[index].sta.sta.addr, addr)) {
+ if (priv->stations[sta_id].used &&
+ !compare_ether_addr(priv->stations[sta_id].sta.sta.addr, addr)) {
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- return index;
+ return sta_id;
}
- IWL_DEBUG_ASSOC("Add STA ID %d: %s\n", index, print_mac(mac, addr));
- station = &priv->stations[index];
- station->used = 1;
+ station = &priv->stations[sta_id];
+ station->used = IWL_STA_DRIVER_ACTIVE;
+ IWL_DEBUG_ASSOC("Add STA to driver ID %d: %s\n",
+ sta_id, print_mac(mac, addr));
priv->num_stations++;
/* Set up the REPLY_ADD_STA command to send to device */
memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd));
memcpy(station->sta.sta.addr, addr, ETH_ALEN);
station->sta.mode = 0;
- station->sta.sta.sta_id = index;
+ station->sta.sta.sta_id = sta_id;
station->sta.station_flags = 0;
/* BCAST station and IBSS stations do not work in HT mode */
- if (index != priv->hw_params.bcast_sta_id &&
+ if (sta_id != priv->hw_params.bcast_sta_id &&
priv->iw_mode != IEEE80211_IF_TYPE_IBSS)
- iwl_set_ht_add_station(priv, index, ht_info);
+ iwl_set_ht_add_station(priv, sta_id, ht_info);
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
/* Add station to device's station table */
iwl_send_add_sta(priv, &station->sta, flags);
- return index;
+ return sta_id;
}
EXPORT_SYMBOL(iwl_add_station_flags);
-static int iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
+static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
{
unsigned long flags;
- u8 sta_id;
DECLARE_MAC_BUF(mac);
- sta_id = iwl_find_station(priv, addr);
- if (sta_id != IWL_INVALID_STATION) {
- IWL_DEBUG_ASSOC("Removed STA from Ucode: %s\n",
- print_mac(mac, addr));
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE;
- memset(&priv->stations[sta_id], 0,
- sizeof(struct iwl_station_entry));
- spin_unlock_irqrestore(&priv->sta_lock, flags);
- return 0;
- }
- return -EINVAL;
+ u8 sta_id = iwl_find_station(priv, addr);
+
+ BUG_ON(sta_id == IWL_INVALID_STATION);
+
+ IWL_DEBUG_ASSOC("Removed STA from Ucode: %s\n",
+ print_mac(mac, addr));
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+
+ /* Ucode must be active and driver must be non active */
+ if (priv->stations[sta_id].used != IWL_STA_UCODE_ACTIVE)
+ IWL_ERROR("removed non active STA %d\n", sta_id);
+
+ priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE;
+
+ memset(&priv->stations[sta_id], 0, sizeof(struct iwl_station_entry));
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
}
static int iwl_remove_sta_callback(struct iwl_priv *priv,
@@ -322,6 +345,7 @@
iwl_sta_ucode_deactivate(priv, addr);
break;
default:
+ IWL_ERROR("REPLY_REMOVE_STA failed\n");
break;
}
@@ -386,44 +410,63 @@
/**
* iwl_remove_station - Remove driver's knowledge of station.
*/
-u8 iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
+int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
{
- int index = IWL_INVALID_STATION;
- int i;
+ int sta_id = IWL_INVALID_STATION;
+ int i, ret = -EINVAL;
unsigned long flags;
+ DECLARE_MAC_BUF(mac);
spin_lock_irqsave(&priv->sta_lock, flags);
if (is_ap)
- index = IWL_AP_ID;
+ sta_id = IWL_AP_ID;
else if (is_broadcast_ether_addr(addr))
- index = priv->hw_params.bcast_sta_id;
+ sta_id = priv->hw_params.bcast_sta_id;
else
for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
if (priv->stations[i].used &&
!compare_ether_addr(priv->stations[i].sta.sta.addr,
addr)) {
- index = i;
+ sta_id = i;
break;
}
- if (unlikely(index == IWL_INVALID_STATION))
+ if (unlikely(sta_id == IWL_INVALID_STATION))
goto out;
- if (priv->stations[index].used) {
- priv->stations[index].used = 0;
- priv->num_stations--;
+ IWL_DEBUG_ASSOC("Removing STA from driver:%d %s\n",
+ sta_id, print_mac(mac, addr));
+
+ if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
+ IWL_ERROR("Removing %s but non DRIVER active\n",
+ print_mac(mac, addr));
+ goto out;
}
+ if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
+ IWL_ERROR("Removing %s but non UCODE active\n",
+ print_mac(mac, addr));
+ goto out;
+ }
+
+
+ priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
+
+ priv->num_stations--;
+
BUG_ON(priv->num_stations < 0);
+
spin_unlock_irqrestore(&priv->sta_lock, flags);
- iwl_send_remove_station(priv, addr, CMD_ASYNC);
- return index;
+
+ ret = iwl_send_remove_station(priv, addr, CMD_ASYNC);
+ return ret;
out:
spin_unlock_irqrestore(&priv->sta_lock, flags);
- return 0;
+ return ret;
}
EXPORT_SYMBOL(iwl_remove_station);
+
static int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
{
int i;
@@ -782,8 +825,7 @@
iwl_dump_lq_cmd(priv,lq);
- if (iwl_is_associated(priv) && priv->assoc_station_added &&
- priv->lq_mngr.lq_ready)
+ if (iwl_is_associated(priv) && priv->assoc_station_added)
return iwl_send_cmd(priv, &cmd);
return 0;
@@ -845,6 +887,7 @@
iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD,
sizeof(link_cmd), &link_cmd, NULL);
}
+
/**
* iwl_rxon_add_station - add station into station table.
*
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index b6bb209..221b93e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -48,7 +48,7 @@
int iwl_remove_dynamic_key(struct iwl_priv *priv,
struct ieee80211_key_conf *key, u8 sta_id);
int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap);
-u8 iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap);
+int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap);
int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid);
int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 7296e28..032641d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -1350,6 +1350,149 @@
}
EXPORT_SYMBOL(iwl_txq_check_empty);
+/**
+ * iwl_tx_status_reply_compressed_ba - Update tx status from block-ack
+ *
+ * Go through block-ack's bitmap of ACK'd frames, update driver's record of
+ * ACK vs. not. This gets sent to mac80211, then to rate scaling algo.
+ */
+static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv,
+ struct iwl_ht_agg *agg,
+ struct iwl_compressed_ba_resp *ba_resp)
+
+{
+ int i, sh, ack;
+ u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
+ u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
+ u64 bitmap;
+ int successes = 0;
+ struct ieee80211_tx_info *info;
+
+ if (unlikely(!agg->wait_for_ba)) {
+ IWL_ERROR("Received BA when not expected\n");
+ return -EINVAL;
+ }
+
+ /* Mark that the expected block-ack response arrived */
+ agg->wait_for_ba = 0;
+ IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->seq_ctl);
+
+ /* Calculate shift to align block-ack bits with our Tx window bits */
+ sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl>>4);
+ if (sh < 0) /* tbw something is wrong with indices */
+ sh += 0x100;
+
+ /* don't use 64-bit values for now */
+ bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
+
+ if (agg->frame_count > (64 - sh)) {
+ IWL_DEBUG_TX_REPLY("more frames than bitmap size");
+ return -1;
+ }
+
+ /* check for success or failure according to the
+ * transmitted bitmap and block-ack bitmap */
+ bitmap &= agg->bitmap;
+
+ /* For each frame attempted in aggregation,
+ * update driver's record of tx frame's status. */
+ for (i = 0; i < agg->frame_count ; i++) {
+ ack = bitmap & (1 << i);
+ successes += !!ack;
+ IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n",
+ ack? "ACK":"NACK", i, (agg->start_idx + i) & 0xff,
+ agg->start_idx + i);
+ }
+
+ info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]);
+ memset(&info->status, 0, sizeof(info->status));
+ info->flags = IEEE80211_TX_STAT_ACK;
+ info->flags |= IEEE80211_TX_STAT_AMPDU;
+ info->status.ampdu_ack_map = successes;
+ info->status.ampdu_ack_len = agg->frame_count;
+ iwl_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
+
+ IWL_DEBUG_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap);
+
+ return 0;
+}
+
+/**
+ * iwl_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA
+ *
+ * Handles block-acknowledge notification from device, which reports success
+ * of frames sent via aggregation.
+ */
+void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+ struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
+ int index;
+ struct iwl_tx_queue *txq = NULL;
+ struct iwl_ht_agg *agg;
+ DECLARE_MAC_BUF(mac);
+
+ /* "flow" corresponds to Tx queue */
+ u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
+
+ /* "ssn" is start of block-ack Tx window, corresponds to index
+ * (in Tx queue's circular buffer) of first TFD/frame in window */
+ u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
+
+ if (scd_flow >= priv->hw_params.max_txq_num) {
+ IWL_ERROR("BUG_ON scd_flow is bigger than number of queues");
+ return;
+ }
+
+ txq = &priv->txq[scd_flow];
+ agg = &priv->stations[ba_resp->sta_id].tid[ba_resp->tid].agg;
+
+ /* Find index just before block-ack window */
+ index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
+
+ /* TODO: Need to get this copy more safely - now good for debug */
+
+ IWL_DEBUG_TX_REPLY("REPLY_COMPRESSED_BA [%d]Received from %s, "
+ "sta_id = %d\n",
+ agg->wait_for_ba,
+ print_mac(mac, (u8 *) &ba_resp->sta_addr_lo32),
+ ba_resp->sta_id);
+ IWL_DEBUG_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = "
+ "%d, scd_ssn = %d\n",
+ ba_resp->tid,
+ ba_resp->seq_ctl,
+ (unsigned long long)le64_to_cpu(ba_resp->bitmap),
+ ba_resp->scd_flow,
+ ba_resp->scd_ssn);
+ IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx \n",
+ agg->start_idx,
+ (unsigned long long)agg->bitmap);
+
+ /* Update driver's record of ACK vs. not for each frame in window */
+ iwl_tx_status_reply_compressed_ba(priv, agg, ba_resp);
+
+ /* Release all TFDs before the SSN, i.e. all TFDs in front of
+ * block-ack window (we assume that they've been successfully
+ * transmitted ... if not, it's too late anyway). */
+ if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
+ /* calculate mac80211 ampdu sw queue to wake */
+ int ampdu_q =
+ scd_flow - priv->hw_params.first_ampdu_q + priv->hw->queues;
+ int freed = iwl_tx_queue_reclaim(priv, scd_flow, index);
+ priv->stations[ba_resp->sta_id].
+ tid[ba_resp->tid].tfds_in_queue -= freed;
+ if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
+ priv->mac80211_registered &&
+ agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)
+ ieee80211_wake_queue(priv->hw, ampdu_q);
+
+ iwl_txq_check_empty(priv, ba_resp->sta_id,
+ ba_resp->tid, scd_flow);
+ }
+}
+EXPORT_SYMBOL(iwl_rx_reply_compressed_ba);
+
#ifdef CONFIG_IWLWIF_DEBUG
#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 92d1b2e..3bc2644 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -970,7 +970,7 @@
{
/* These items are only settable from the full RXON command */
- if (!(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ||
+ if (!(iwl3945_is_associated(priv)) ||
compare_ether_addr(priv->staging_rxon.bssid_addr,
priv->active_rxon.bssid_addr) ||
compare_ether_addr(priv->staging_rxon.node_addr,
@@ -2312,7 +2312,7 @@
#endif
ch_info = iwl3945_get_channel_info(priv, priv->band,
- le16_to_cpu(priv->staging_rxon.channel));
+ le16_to_cpu(priv->active_rxon.channel));
if (!ch_info)
ch_info = &priv->channel_info[0];
@@ -2539,6 +2539,11 @@
iwl3945_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
return priv->hw_setting.bcast_sta_id;
}
+ /* If we are in monitor mode, use BCAST. This is required for
+ * packet injection. */
+ case IEEE80211_IF_TYPE_MNTR:
+ return priv->hw_setting.bcast_sta_id;
+
default:
IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode);
return priv->hw_setting.bcast_sta_id;
@@ -2578,11 +2583,6 @@
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");
goto drop_unlock;
@@ -2603,9 +2603,10 @@
#endif
/* drop all data frame if we are not associated */
- if ((!iwl3945_is_associated(priv) ||
- ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id)) &&
- ieee80211_is_data(fc)) {
+ if (ieee80211_is_data(fc) &&
+ (priv->iw_mode != IEEE80211_IF_TYPE_MNTR) && /* packet injection */
+ (!iwl3945_is_associated(priv) ||
+ ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id))) {
IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n");
goto drop_unlock;
}
@@ -5921,7 +5922,9 @@
test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
STATUS_GEO_CONFIGURED |
test_bit(STATUS_IN_SUSPEND, &priv->status) <<
- STATUS_IN_SUSPEND;
+ STATUS_IN_SUSPEND |
+ test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+ STATUS_EXIT_PENDING;
goto exit;
}
@@ -5936,7 +5939,9 @@
test_bit(STATUS_IN_SUSPEND, &priv->status) <<
STATUS_IN_SUSPEND |
test_bit(STATUS_FW_ERROR, &priv->status) <<
- STATUS_FW_ERROR;
+ STATUS_FW_ERROR |
+ test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+ STATUS_EXIT_PENDING;
spin_lock_irqsave(&priv->lock, flags);
iwl3945_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
@@ -6008,11 +6013,12 @@
else {
set_bit(STATUS_RF_KILL_HW, &priv->status);
if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
+ iwl3945_rfkill_set_hw_state(priv);
IWL_WARNING("Radio disabled by HW RF Kill switch\n");
return -ENODEV;
}
}
-
+ iwl3945_rfkill_set_hw_state(priv);
iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF);
rc = iwl3945_hw_nic_init(priv);
@@ -6068,6 +6074,7 @@
set_bit(STATUS_EXIT_PENDING, &priv->status);
__iwl3945_down(priv);
+ clear_bit(STATUS_EXIT_PENDING, &priv->status);
/* tried to restart and config the device for as long as our
* patience could withstand */
@@ -6135,6 +6142,8 @@
"Kill switch must be turned off for "
"wireless networking to work.\n");
}
+
+ iwl3945_rfkill_set_hw_state(priv);
mutex_unlock(&priv->mutex);
}
@@ -6685,11 +6694,6 @@
IWL_DEBUG_MAC80211("enter\n");
- if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
- IWL_DEBUG_MAC80211("leave - monitor\n");
- return -1;
- }
-
IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
@@ -6836,7 +6840,7 @@
return;
/* The following should be done only at AP bring up */
- if ((priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) == 0) {
+ if (!(iwl3945_is_associated(priv))) {
/* RXON - unassoc (to set timing command) */
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
@@ -6998,26 +7002,18 @@
unsigned int *total_flags,
int mc_count, struct dev_addr_list *mc_list)
{
- /*
- * XXX: dummy
- * see also iwl3945_connection_init_rx_config
- */
struct iwl3945_priv *priv = hw->priv;
- int new_flags = 0;
- if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
- if (*total_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
- IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
- IEEE80211_IF_TYPE_MNTR,
- changed_flags, *total_flags);
- /* queue work 'cuz mac80211 is holding a lock which
- * prevents us from issuing (synchronous) f/w cmds */
- queue_work(priv->workqueue, &priv->set_monitor);
- new_flags &= FIF_PROMISC_IN_BSS |
- FIF_OTHER_BSS |
- FIF_ALLMULTI;
- }
+
+ if (changed_flags & (*total_flags) & FIF_OTHER_BSS) {
+ IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
+ IEEE80211_IF_TYPE_MNTR,
+ changed_flags, *total_flags);
+ /* queue work 'cuz mac80211 is holding a lock which
+ * prevents us from issuing (synchronous) f/w cmds */
+ queue_work(priv->workqueue, &priv->set_monitor);
}
- *total_flags = new_flags;
+ *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI |
+ FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
}
static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
@@ -7412,37 +7408,6 @@
#endif /* CONFIG_IWL3945_DEBUG */
-static ssize_t show_rf_kill(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- /*
- * 0 - RF kill not enabled
- * 1 - SW based RF kill active (sysfs)
- * 2 - HW based RF kill active
- * 3 - Both HW and SW based RF kill active
- */
- struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
- int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) |
- (test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0);
-
- return sprintf(buf, "%i\n", val);
-}
-
-static ssize_t store_rf_kill(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
-
- mutex_lock(&priv->mutex);
- iwl3945_radio_kill_sw(priv, buf[0] == '1');
- mutex_unlock(&priv->mutex);
-
- return count;
-}
-
-static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill);
-
static ssize_t show_temperature(struct device *d,
struct device_attribute *attr, char *buf)
{
@@ -7928,7 +7893,6 @@
#endif
&dev_attr_power_level.attr,
&dev_attr_retry_rate.attr,
- &dev_attr_rf_kill.attr,
&dev_attr_rs_window.attr,
&dev_attr_statistics.attr,
&dev_attr_status.attr,
@@ -8169,6 +8133,11 @@
pci_save_state(pdev);
pci_disable_device(pdev);
+ err = iwl3945_rfkill_init(priv);
+ if (err)
+ IWL_ERROR("Unable to initialize RFKILL system. "
+ "Ignoring error: %d\n", err);
+
return 0;
out_free_geos:
@@ -8231,6 +8200,7 @@
sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
+ iwl3945_rfkill_unregister(priv);
iwl3945_dealloc_ucode_pci(priv);
if (priv->rxq.bd)
@@ -8299,6 +8269,143 @@
#endif /* CONFIG_PM */
+/*************** RFKILL FUNCTIONS **********/
+#ifdef CONFIG_IWLWIFI_RFKILL
+/* software rf-kill from user */
+static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
+{
+ struct iwl3945_priv *priv = data;
+ int err = 0;
+
+ if (!priv->rfkill_mngr.rfkill)
+ return 0;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return 0;
+
+ IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state);
+ mutex_lock(&priv->mutex);
+
+ switch (state) {
+ case RFKILL_STATE_UNBLOCKED:
+ iwl3945_radio_kill_sw(priv, 0);
+ /* if HW rf-kill is set dont allow ON state */
+ if (iwl3945_is_rfkill(priv))
+ err = -EBUSY;
+ break;
+ case RFKILL_STATE_SOFT_BLOCKED:
+ iwl3945_radio_kill_sw(priv, 1);
+ if (!iwl3945_is_rfkill(priv))
+ err = -EBUSY;
+ break;
+ default:
+ IWL_WARNING("we recieved unexpected RFKILL state %d\n", state);
+ break;
+ }
+ mutex_unlock(&priv->mutex);
+
+ return err;
+}
+
+int iwl3945_rfkill_init(struct iwl3945_priv *priv)
+{
+ struct device *device = wiphy_dev(priv->hw->wiphy);
+ int ret = 0;
+
+ BUG_ON(device == NULL);
+
+ IWL_DEBUG_RF_KILL("Initializing RFKILL.\n");
+ priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
+ if (!priv->rfkill_mngr.rfkill) {
+ IWL_ERROR("Unable to allocate rfkill device.\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ priv->rfkill_mngr.rfkill->name = priv->cfg->name;
+ priv->rfkill_mngr.rfkill->data = priv;
+ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON;
+ priv->rfkill_mngr.rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill;
+ priv->rfkill_mngr.rfkill->user_claim_unsupported = 1;
+
+ priv->rfkill_mngr.rfkill->dev.class->suspend = NULL;
+ priv->rfkill_mngr.rfkill->dev.class->resume = NULL;
+
+ priv->rfkill_mngr.input_dev = input_allocate_device();
+ if (!priv->rfkill_mngr.input_dev) {
+ IWL_ERROR("Unable to allocate rfkill input device.\n");
+ ret = -ENOMEM;
+ goto freed_rfkill;
+ }
+
+ priv->rfkill_mngr.input_dev->name = priv->cfg->name;
+ priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy);
+ priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST;
+ priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor;
+ priv->rfkill_mngr.input_dev->dev.parent = device;
+ priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY);
+ set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit);
+
+ ret = rfkill_register(priv->rfkill_mngr.rfkill);
+ if (ret) {
+ IWL_ERROR("Unable to register rfkill: %d\n", ret);
+ goto free_input_dev;
+ }
+
+ ret = input_register_device(priv->rfkill_mngr.input_dev);
+ if (ret) {
+ IWL_ERROR("Unable to register rfkill input device: %d\n", ret);
+ goto unregister_rfkill;
+ }
+
+ IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
+ return ret;
+
+unregister_rfkill:
+ rfkill_unregister(priv->rfkill_mngr.rfkill);
+ priv->rfkill_mngr.rfkill = NULL;
+
+free_input_dev:
+ input_free_device(priv->rfkill_mngr.input_dev);
+ priv->rfkill_mngr.input_dev = NULL;
+
+freed_rfkill:
+ if (priv->rfkill_mngr.rfkill != NULL)
+ rfkill_free(priv->rfkill_mngr.rfkill);
+ priv->rfkill_mngr.rfkill = NULL;
+
+error:
+ IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
+ return ret;
+}
+
+void iwl3945_rfkill_unregister(struct iwl3945_priv *priv)
+{
+
+ if (priv->rfkill_mngr.input_dev)
+ input_unregister_device(priv->rfkill_mngr.input_dev);
+
+ if (priv->rfkill_mngr.rfkill)
+ rfkill_unregister(priv->rfkill_mngr.rfkill);
+
+ priv->rfkill_mngr.input_dev = NULL;
+ priv->rfkill_mngr.rfkill = NULL;
+}
+
+/* set rf-kill to the right state. */
+void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv)
+{
+
+ if (!priv->rfkill_mngr.rfkill)
+ return;
+
+ if (!iwl3945_is_rfkill(priv))
+ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON;
+ else
+ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF;
+}
+#endif
+
/*****************************************************************************
*
* driver and module entry point
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index f591168..ba0f289 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -192,7 +192,7 @@
{
/* These items are only settable from the full RXON command */
- if (!(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ||
+ if (!(iwl_is_associated(priv)) ||
compare_ether_addr(priv->staging_rxon.bssid_addr,
priv->active_rxon.bssid_addr) ||
compare_ether_addr(priv->staging_rxon.node_addr,
@@ -241,16 +241,18 @@
/* cast away the const for active_rxon in this function */
struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
DECLARE_MAC_BUF(mac);
- int rc = 0;
+ int ret;
+ bool new_assoc =
+ !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
if (!iwl_is_alive(priv))
- return -1;
+ return -EBUSY;
/* always get timestamp with Rx frame */
priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
- rc = iwl4965_check_rxon_cmd(&priv->staging_rxon);
- if (rc) {
+ ret = iwl4965_check_rxon_cmd(&priv->staging_rxon);
+ if (ret) {
IWL_ERROR("Invalid RXON configuration. Not committing.\n");
return -EINVAL;
}
@@ -259,15 +261,13 @@
* iwl4965_rxon_assoc_cmd which is used to reconfigure filter
* and other flags for the current radio configuration. */
if (!iwl4965_full_rxon_required(priv)) {
- rc = iwl_send_rxon_assoc(priv);
- if (rc) {
- IWL_ERROR("Error setting RXON_ASSOC "
- "configuration (%d).\n", rc);
- return rc;
+ ret = iwl_send_rxon_assoc(priv);
+ if (ret) {
+ IWL_ERROR("Error setting RXON_ASSOC (%d)\n", ret);
+ return ret;
}
memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
-
return 0;
}
@@ -278,22 +278,20 @@
* an RXON_ASSOC and the new config wants the associated mask enabled,
* we must clear the associated from the active configuration
* before we apply the new config */
- if (iwl_is_associated(priv) &&
- (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) {
+ if (iwl_is_associated(priv) && new_assoc) {
IWL_DEBUG_INFO("Toggling associated bit on current RXON\n");
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
+ ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
sizeof(struct iwl_rxon_cmd),
&priv->active_rxon);
/* If the mask clearing failed then we set
* active_rxon back to what it was previously */
- if (rc) {
+ if (ret) {
active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
- IWL_ERROR("Error clearing ASSOC_MSK on current "
- "configuration (%d).\n", rc);
- return rc;
+ IWL_ERROR("Error clearing ASSOC_MSK (%d)\n", ret);
+ return ret;
}
}
@@ -301,58 +299,75 @@
"* with%s RXON_FILTER_ASSOC_MSK\n"
"* channel = %d\n"
"* bssid = %s\n",
- ((priv->staging_rxon.filter_flags &
- RXON_FILTER_ASSOC_MSK) ? "" : "out"),
+ (new_assoc ? "" : "out"),
le16_to_cpu(priv->staging_rxon.channel),
print_mac(mac, priv->staging_rxon.bssid_addr));
iwl4965_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
- /* Apply the new configuration */
- rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
+
+ /* Apply the new configuration
+ * RXON unassoc clears the station table in uCode, send it before
+ * we add the bcast station. If assoc bit is set, we will send RXON
+ * after having added the bcast and bssid station.
+ */
+ if (!new_assoc) {
+ ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
- if (rc) {
- IWL_ERROR("Error setting new configuration (%d).\n", rc);
- return rc;
+ if (ret) {
+ IWL_ERROR("Error setting new RXON (%d)\n", ret);
+ return ret;
+ }
+ memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
}
- iwl_remove_station(priv, iwl_bcast_addr, 0);
- iwlcore_clear_stations_table(priv);
+ iwl_clear_stations_table(priv);
if (!priv->error_recovering)
priv->start_calib = 0;
iwl_init_sensitivity(priv);
- memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
-
/* If we issue a new RXON command which required a tune then we must
* send a new TXPOWER command or we won't be able to Tx any frames */
- rc = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
- if (rc) {
- IWL_ERROR("Error sending TX power (%d).\n", rc);
- return rc;
+ ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+ if (ret) {
+ IWL_ERROR("Error sending TX power (%d)\n", ret);
+ return ret;
}
/* Add the broadcast address so we can send broadcast frames */
if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
- IWL_INVALID_STATION) {
+ IWL_INVALID_STATION) {
IWL_ERROR("Error adding BROADCAST address for transmit.\n");
return -EIO;
}
/* 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 (iwl_is_associated(priv) &&
- (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
- if (iwl_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1)
- == IWL_INVALID_STATION) {
- IWL_ERROR("Error adding AP address for transmit.\n");
- return -EIO;
+ if (new_assoc) {
+ if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
+ ret = iwl_rxon_add_station(priv,
+ priv->active_rxon.bssid_addr, 1);
+ if (ret == IWL_INVALID_STATION) {
+ IWL_ERROR("Error adding AP address for TX.\n");
+ return -EIO;
+ }
+ priv->assoc_station_added = 1;
+ if (priv->default_wep_key &&
+ iwl_send_static_wepkey_cmd(priv, 0))
+ IWL_ERROR("Could not send WEP static key.\n");
}
- priv->assoc_station_added = 1;
- if (priv->default_wep_key &&
- iwl_send_static_wepkey_cmd(priv, 0))
- IWL_ERROR("Could not send WEP static key.\n");
+
+ /* Apply the new configuration
+ * RXON assoc doesn't clear the station table in uCode,
+ */
+ ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
+ sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
+ if (ret) {
+ IWL_ERROR("Error setting new RXON (%d)\n", ret);
+ return ret;
+ }
+ memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
}
return 0;
@@ -601,50 +616,6 @@
}
}
-int iwl4965_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
-{
- /* 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 */
- /* packets from our adapter are dropped (echo) */
- if (!compare_ether_addr(header->addr2, priv->mac_addr))
- return 0;
- /* {broad,multi}cast packets to our IBSS go through */
- if (is_multicast_ether_addr(header->addr1))
- return !compare_ether_addr(header->addr3, priv->bssid);
- /* packets to our adapter go through */
- return !compare_ether_addr(header->addr1, priv->mac_addr);
- case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */
- /* packets from our adapter are dropped (echo) */
- if (!compare_ether_addr(header->addr3, priv->mac_addr))
- return 0;
- /* {broad,multi}cast packets to our BSS go through */
- if (is_multicast_ether_addr(header->addr1))
- return !compare_ether_addr(header->addr2, priv->bssid);
- /* packets to our adapter go through */
- return !compare_ether_addr(header->addr1, priv->mac_addr);
- default:
- break;
- }
-
- return 1;
-}
-
-static void iwl4965_sequence_reset(struct iwl_priv *priv)
-{
- /* Reset ieee stats */
-
- /* We don't reset the net_device_stats (ieee->stats) on
- * re-association */
-
- priv->last_seq_num = -1;
- priv->last_frag_num = -1;
- priv->last_packet_time = 0;
-
- iwl_scan_cancel(priv);
-}
-
#define MAX_UCODE_BEACON_INTERVAL 4096
#define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA)
@@ -787,7 +758,7 @@
#endif
ch_info = iwl_get_channel_info(priv, priv->band,
- le16_to_cpu(priv->staging_rxon.channel));
+ le16_to_cpu(priv->active_rxon.channel));
if (!ch_info)
ch_info = &priv->channel_info[0];
@@ -823,13 +794,10 @@
{
priv->iw_mode = mode;
- /* init channel/phymode to values given at driver init */
- iwl_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
-
iwl4965_connection_init_rx_config(priv);
memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
- iwlcore_clear_stations_table(priv);
+ iwl_clear_stations_table(priv);
/* dont commit rxon if rf-kill is on*/
if (!iwl_is_ready_rf(priv))
@@ -894,72 +862,6 @@
(IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
}
-#define IWL_PACKET_RETRY_TIME HZ
-
-int iwl4965_is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
-{
- u16 sc = le16_to_cpu(header->seq_ctrl);
- u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
- u16 frag = sc & IEEE80211_SCTL_FRAG;
- u16 *last_seq, *last_frag;
- unsigned long *last_time;
-
- switch (priv->iw_mode) {
- case IEEE80211_IF_TYPE_IBSS:{
- struct list_head *p;
- struct iwl4965_ibss_seq *entry = NULL;
- u8 *mac = header->addr2;
- int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1);
-
- __list_for_each(p, &priv->ibss_mac_hash[index]) {
- entry = list_entry(p, struct iwl4965_ibss_seq, list);
- if (!compare_ether_addr(entry->mac, mac))
- break;
- }
- if (p == &priv->ibss_mac_hash[index]) {
- entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
- if (!entry) {
- IWL_ERROR("Cannot malloc new mac entry\n");
- return 0;
- }
- memcpy(entry->mac, mac, ETH_ALEN);
- entry->seq_num = seq;
- entry->frag_num = frag;
- entry->packet_time = jiffies;
- list_add(&entry->list, &priv->ibss_mac_hash[index]);
- return 0;
- }
- last_seq = &entry->seq_num;
- last_frag = &entry->frag_num;
- last_time = &entry->packet_time;
- break;
- }
- case IEEE80211_IF_TYPE_STA:
- last_seq = &priv->last_seq_num;
- last_frag = &priv->last_frag_num;
- last_time = &priv->last_packet_time;
- break;
- default:
- return 0;
- }
- if ((*last_seq == seq) &&
- time_after(*last_time + IWL_PACKET_RETRY_TIME, jiffies)) {
- if (*last_frag == frag)
- goto drop;
- if (*last_frag + 1 != frag)
- /* out-of-order fragment */
- goto drop;
- } else
- *last_seq = seq;
-
- *last_frag = frag;
- *last_time = jiffies;
- return 0;
-
- drop:
- return 1;
-}
-
#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
#include "iwl-spectrum.h"
@@ -1338,17 +1240,6 @@
wake_up_interruptible(&priv->wait_command_queue);
}
-/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
- * This will be used later in iwl4965_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
-static void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
-{
- struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
- priv->last_phy_res[0] = 1;
- memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
- sizeof(struct iwl4965_rx_phy_res));
-}
-
/**
* iwl4965_setup_rx_handlers - Initialize Rx handler callbacks
*
@@ -1358,7 +1249,7 @@
* This function chains into the hardware specific files for them to setup
* any hardware specific handlers as well.
*/
-static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
+static void iwl_setup_rx_handlers(struct iwl_priv *priv)
{
priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
priv->rx_handlers[REPLY_ERROR] = iwl4965_rx_reply_error;
@@ -1375,8 +1266,8 @@
* statistics request from the host as well as for the periodic
* statistics notifications (after received beacons) from the uCode.
*/
- priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl4965_hw_rx_statistics;
- priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl4965_hw_rx_statistics;
+ priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_rx_statistics;
+ priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics;
iwl_setup_rx_scan_handlers(priv);
@@ -1386,8 +1277,10 @@
priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
iwl_rx_missed_beacon_notif;
/* Rx handlers */
- priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl4965_rx_reply_rx_phy;
- priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl4965_rx_reply_rx;
+ priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy;
+ priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx;
+ /* block ack */
+ priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl_rx_reply_compressed_ba;
/* Set up hardware specific Rx handlers */
priv->cfg->ops->lib->rx_handler_setup(priv);
}
@@ -1518,47 +1411,6 @@
iwl_rx_queue_restock(priv);
}
-#define PERFECT_RSSI (-20) /* dBm */
-#define WORST_RSSI (-95) /* dBm */
-#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)
-
-/* Calculate an indication of rx signal quality (a percentage, not dBm!).
- * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
- * about formulas used below. */
-int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm)
-{
- int sig_qual;
- int degradation = PERFECT_RSSI - rssi_dbm;
-
- /* If we get a noise measurement, use signal-to-noise ratio (SNR)
- * as indicator; formula is (signal dbm - noise dbm).
- * SNR at or above 40 is a great signal (100%).
- * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
- * Weakest usable signal is usually 10 - 15 dB SNR. */
- if (noise_dbm) {
- if (rssi_dbm - noise_dbm >= 40)
- return 100;
- else if (rssi_dbm < noise_dbm)
- return 0;
- sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;
-
- /* Else use just the signal level.
- * This formula is a least squares fit of data points collected and
- * compared with a reference system that had a percentage (%) display
- * for signal quality. */
- } else
- sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
- (15 * RSSI_RANGE + 62 * degradation)) /
- (RSSI_RANGE * RSSI_RANGE);
-
- if (sig_qual > 100)
- sig_qual = 100;
- else if (sig_qual < 1)
- sig_qual = 0;
-
- return sig_qual;
-}
-
#ifdef CONFIG_IWLWIFI_DEBUG
static void iwl4965_print_rx_config_cmd(struct iwl_priv *priv)
{
@@ -1751,14 +1603,12 @@
IWL_DEBUG(IWL_DL_RF_KILL, "RF_KILL bit toggled to %s.\n",
hw_rf_kill ? "disable radio":"enable radio");
- /* Queue restart only if RF_KILL switch was set to "kill"
- * when we loaded driver, and is now set to "enable".
- * After we're Alive, RF_KILL gets handled by
- * iwl4965_rx_card_state_notif() */
- if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) {
+ /* driver only loads ucode once setting the interface up.
+ * the driver as well won't allow loading if RFKILL is set
+ * therefore no need to restart the driver from this handler
+ */
+ if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status))
clear_bit(STATUS_RF_KILL_HW, &priv->status);
- queue_work(priv->workqueue, &priv->restart);
- }
handled |= CSR_INT_BIT_RF_KILL;
}
@@ -2138,7 +1988,7 @@
goto restart;
}
- iwlcore_clear_stations_table(priv);
+ iwl_clear_stations_table(priv);
ret = priv->cfg->ops->lib->alive_notify(priv);
if (ret) {
IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n",
@@ -2216,7 +2066,7 @@
iwl_leds_unregister(priv);
- iwlcore_clear_stations_table(priv);
+ iwl_clear_stations_table(priv);
/* Unblock any waiting calls */
wake_up_interruptible_all(&priv->wait_command_queue);
@@ -2248,7 +2098,9 @@
test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
STATUS_GEO_CONFIGURED |
test_bit(STATUS_IN_SUSPEND, &priv->status) <<
- STATUS_IN_SUSPEND;
+ STATUS_IN_SUSPEND |
+ test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+ STATUS_EXIT_PENDING;
goto exit;
}
@@ -2263,7 +2115,9 @@
test_bit(STATUS_IN_SUSPEND, &priv->status) <<
STATUS_IN_SUSPEND |
test_bit(STATUS_FW_ERROR, &priv->status) <<
- STATUS_FW_ERROR;
+ STATUS_FW_ERROR |
+ test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+ STATUS_EXIT_PENDING;
spin_lock_irqsave(&priv->lock, flags);
iwl_clear_bit(priv, CSR_GP_CNTRL,
@@ -2328,13 +2182,15 @@
if (iwl_read32(priv, CSR_GP_CNTRL) &
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
clear_bit(STATUS_RF_KILL_HW, &priv->status);
- else {
+ else
set_bit(STATUS_RF_KILL_HW, &priv->status);
- if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
- iwl_rfkill_set_hw_state(priv);
- IWL_WARNING("Radio disabled by HW RF Kill switch\n");
- return -ENODEV;
- }
+
+ if (!test_bit(STATUS_IN_SUSPEND, &priv->status) &&
+ iwl_is_rfkill(priv)) {
+ iwl_rfkill_set_hw_state(priv);
+ IWL_WARNING("Radio disabled by %s RF Kill switch\n",
+ test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW");
+ return -ENODEV;
}
iwl_rfkill_set_hw_state(priv);
@@ -2378,7 +2234,7 @@
for (i = 0; i < MAX_HW_RESTARTS; i++) {
- iwlcore_clear_stations_table(priv);
+ iwl_clear_stations_table(priv);
/* load bootstrap state machine,
* load bootstrap program into processor's memory,
@@ -2631,7 +2487,6 @@
switch (priv->iw_mode) {
case IEEE80211_IF_TYPE_STA:
- iwl4965_rate_scale_init(priv->hw, IWL_AP_ID);
break;
case IEEE80211_IF_TYPE_IBSS:
@@ -2640,7 +2495,6 @@
priv->assoc_id = 1;
iwl_rxon_add_station(priv, priv->bssid, 0);
- iwl4965_rate_scale_init(priv->hw, IWL_STA_ID);
iwl4965_send_beacon_cmd(priv);
break;
@@ -2651,8 +2505,6 @@
break;
}
- iwl4965_sequence_reset(priv);
-
/* Enable Rx differential gain and sensitivity calibrations */
iwl_chain_noise_reset(priv);
priv->start_calib = 1;
@@ -2709,7 +2561,7 @@
*
*****************************************************************************/
-#define UCODE_READY_TIMEOUT (2 * HZ)
+#define UCODE_READY_TIMEOUT (4 * HZ)
static int iwl4965_mac_start(struct ieee80211_hw *hw)
{
@@ -2762,21 +2614,19 @@
/* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
* mac80211 will not be run successfully. */
- if (priv->ucode_type == UCODE_RT) {
- ret = wait_event_interruptible_timeout(priv->wait_command_queue,
- test_bit(STATUS_READY, &priv->status),
- UCODE_READY_TIMEOUT);
- if (!ret) {
- if (!test_bit(STATUS_READY, &priv->status)) {
- IWL_ERROR("START_ALIVE timeout after %dms.\n",
- jiffies_to_msecs(UCODE_READY_TIMEOUT));
- ret = -ETIMEDOUT;
- goto out_release_irq;
- }
+ ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+ test_bit(STATUS_READY, &priv->status),
+ UCODE_READY_TIMEOUT);
+ if (!ret) {
+ if (!test_bit(STATUS_READY, &priv->status)) {
+ IWL_ERROR("START_ALIVE timeout after %dms.\n",
+ jiffies_to_msecs(UCODE_READY_TIMEOUT));
+ ret = -ETIMEDOUT;
+ goto out_release_irq;
}
-
- priv->is_open = 1;
}
+
+ priv->is_open = 1;
IWL_DEBUG_MAC80211("leave\n");
return 0;
@@ -3009,7 +2859,7 @@
return;
/* The following should be done only at AP bring up */
- if ((priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) == 0) {
+ if (!(iwl_is_associated(priv))) {
/* RXON - unassoc (to set timing command) */
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
@@ -3172,26 +3022,18 @@
unsigned int *total_flags,
int mc_count, struct dev_addr_list *mc_list)
{
- /*
- * XXX: dummy
- * see also iwl4965_connection_init_rx_config
- */
struct iwl_priv *priv = hw->priv;
- int new_flags = 0;
- if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
- if (*total_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
- IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
- IEEE80211_IF_TYPE_MNTR,
- changed_flags, *total_flags);
- /* queue work 'cuz mac80211 is holding a lock which
- * prevents us from issuing (synchronous) f/w cmds */
- queue_work(priv->workqueue, &priv->set_monitor);
- new_flags &= FIF_PROMISC_IN_BSS |
- FIF_OTHER_BSS |
- FIF_ALLMULTI;
- }
+
+ if (changed_flags & (*total_flags) & FIF_OTHER_BSS) {
+ IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
+ IEEE80211_IF_TYPE_MNTR,
+ changed_flags, *total_flags);
+ /* queue work 'cuz mac80211 is holding a lock which
+ * prevents us from issuing (synchronous) f/w cmds */
+ queue_work(priv->workqueue, &priv->set_monitor);
}
- *total_flags = new_flags;
+ *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI |
+ FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
}
static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw,
@@ -3556,17 +3398,6 @@
return 0;
}
-static u64 iwl4965_mac_get_tsf(struct ieee80211_hw *hw)
-{
- struct iwl_priv *priv;
-
- priv = hw->priv;
- IWL_DEBUG_MAC80211("enter\n");
- IWL_DEBUG_MAC80211("leave\n");
-
- return 0;
-}
-
static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = hw->priv;
@@ -3575,7 +3406,6 @@
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter\n");
- priv->lq_mngr.lq_ready = 0;
spin_lock_irqsave(&priv->lock, flags);
memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info));
spin_unlock_irqrestore(&priv->lock, flags);
@@ -3638,6 +3468,7 @@
{
struct iwl_priv *priv = hw->priv;
unsigned long flags;
+ __le64 timestamp;
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter\n");
@@ -3662,6 +3493,8 @@
priv->ibss_beacon = skb;
priv->assoc_id = 0;
+ timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
+ priv->timestamp = le64_to_cpu(timestamp) + (priv->beacon_int * 1000);
IWL_DEBUG_MAC80211("leave\n");
spin_unlock_irqrestore(&priv->lock, flags);
@@ -3728,16 +3561,28 @@
{
struct iwl_priv *priv = d->driver_data;
struct iwl_alive_resp *palive = &priv->card_alive;
+ ssize_t pos = 0;
+ u16 eeprom_ver;
if (palive->is_valid)
- return sprintf(buf, "fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n"
- "fw type: 0x%01X 0x%01X\n",
+ pos += sprintf(buf + pos,
+ "fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n"
+ "fw type: 0x%01X 0x%01X\n",
palive->ucode_major, palive->ucode_minor,
palive->sw_rev[0], palive->sw_rev[1],
palive->ver_type, palive->ver_subtype);
-
else
- return sprintf(buf, "fw not loaded\n");
+ pos += sprintf(buf + pos, "fw not loaded\n");
+
+ if (priv->eeprom) {
+ eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
+ pos += sprintf(buf + pos, "EEPROM version: 0x%x\n",
+ eeprom_ver);
+ } else {
+ pos += sprintf(buf + pos, "EEPROM not initialzed\n");
+ }
+
+ return pos;
}
static DEVICE_ATTR(version, S_IWUSR | S_IRUGO, show_version, NULL);
@@ -4106,7 +3951,7 @@
struct device_attribute *attr, char *buf)
{
struct iwl_priv *priv = dev_get_drvdata(d);
- u32 size = sizeof(struct iwl4965_notif_statistics);
+ u32 size = sizeof(struct iwl_notif_statistics);
u32 len = 0, ofs = 0;
u8 *data = (u8 *) & priv->statistics;
int rc = 0;
@@ -4243,7 +4088,6 @@
.get_stats = iwl4965_mac_get_stats,
.get_tx_stats = iwl4965_mac_get_tx_stats,
.conf_tx = iwl4965_mac_conf_tx,
- .get_tsf = iwl4965_mac_get_tsf,
.reset_tsf = iwl4965_mac_reset_tsf,
.beacon_update = iwl4965_mac_beacon_update,
.bss_info_changed = iwl4965_bss_info_changed,
@@ -4372,8 +4216,7 @@
/************************
* 5. Setup HW constants
************************/
- /* Device-specific setup */
- if (priv->cfg->ops->lib->set_hw_params(priv)) {
+ if (iwl_set_hw_params(priv)) {
IWL_ERROR("failed to set hw parameters\n");
goto out_free_eeprom;
}
@@ -4412,7 +4255,7 @@
iwl_setup_deferred_work(priv);
- iwl4965_setup_rx_handlers(priv);
+ iwl_setup_rx_handlers(priv);
/********************
* 9. Conclude
@@ -4461,8 +4304,6 @@
static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
{
struct iwl_priv *priv = pci_get_drvdata(pdev);
- struct list_head *p, *q;
- int i;
unsigned long flags;
if (!priv)
@@ -4491,14 +4332,6 @@
iwl_synchronize_irq(priv);
- /* Free MAC hash list for ADHOC */
- for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) {
- list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
- list_del(p);
- kfree(list_entry(p, struct iwl4965_ibss_seq, list));
- }
- }
-
iwl_rfkill_unregister(priv);
iwl4965_dealloc_ucode_pci(priv);
@@ -4506,7 +4339,7 @@
iwl_rx_queue_free(priv, &priv->rxq);
iwl_hw_txq_ctx_free(priv);
- iwlcore_clear_stations_table(priv);
+ iwl_clear_stations_table(priv);
iwl_eeprom_free(priv);
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
index 9f7224d..ffaf7a6 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -357,6 +357,7 @@
rx_status.signal = hdr->rssi;
/* XX correct? */
+ rx_status.qual = (100 * hdr->rssi) / 127;
rx_status.rate_idx = hdr->rate & 0xf;
rx_status.freq = freq;
rx_status.band = IEEE80211_BAND_2GHZ;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 02c79e6..a704495 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -710,6 +710,10 @@
* @IEEE80211_HW_NOISE_DBM:
* Hardware can provide noise (radio interference) values in units dBm,
* decibel difference from one milliwatt.
+ *
+ * @IEEE80211_HW_SPECTRUM_MGMT:
+ * Hardware supports spectrum management defined in 802.11h
+ * Measurement, Channel Switch, Quieting, TPC
*/
enum ieee80211_hw_flags {
IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE = 1<<0,
@@ -721,6 +725,7 @@
IEEE80211_HW_SIGNAL_DB = 1<<6,
IEEE80211_HW_SIGNAL_DBM = 1<<7,
IEEE80211_HW_NOISE_DBM = 1<<8,
+ IEEE80211_HW_SPECTRUM_MGMT = 1<<9,
};
/**
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 0d3661d..11a1e7f 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -27,6 +27,14 @@
menu "Rate control algorithm selection"
depends on MAC80211 != n
+config MAC80211_RC_PID
+ bool "PID controller based rate control algorithm" if EMBEDDED
+ default y
+ ---help---
+ This option enables a TX rate control algorithm for
+ mac80211 that uses a PID controller to select the TX
+ rate.
+
choice
prompt "Default rate control algorithm"
default MAC80211_RC_DEFAULT_PID
@@ -38,40 +46,19 @@
config MAC80211_RC_DEFAULT_PID
bool "PID controller based rate control algorithm"
- select MAC80211_RC_PID
+ depends on MAC80211_RC_PID
---help---
Select the PID controller based rate control as the
default rate control algorithm. You should choose
this unless you know what you are doing.
-config MAC80211_RC_DEFAULT_NONE
- bool "No default algorithm"
- depends on EMBEDDED
- help
- Selecting this option will select no default algorithm
- and allow you to not build any. Do not choose this
- option unless you know your driver comes with another
- suitable algorithm.
endchoice
-comment "Selecting 'y' for an algorithm will"
-comment "build the algorithm into mac80211."
-
config MAC80211_RC_DEFAULT
string
default "pid" if MAC80211_RC_DEFAULT_PID
default ""
-config MAC80211_RC_PID
- tristate "PID controller based rate control algorithm"
- ---help---
- This option enables a TX rate control algorithm for
- mac80211 that uses a PID controller to select the TX
- rate.
-
- Say Y or M unless you're sure you want to use a
- different rate control algorithm.
-
endmenu
config MAC80211_MESH
@@ -101,10 +88,16 @@
Say N unless you know you need this.
+menuconfig MAC80211_DEBUG_MENU
+ bool "Select mac80211 debugging features"
+ depends on MAC80211
+ ---help---
+ This option collects various mac80211 debug settings.
+
config MAC80211_DEBUG_PACKET_ALIGNMENT
bool "Enable packet alignment debugging"
- depends on MAC80211
- help
+ depends on MAC80211_DEBUG_MENU
+ ---help---
This option is recommended for driver authors and strongly
discouraged for everybody else, it will trigger a warning
when a driver hands mac80211 a buffer that is aligned in
@@ -113,33 +106,95 @@
Say N unless you're writing a mac80211 based driver.
-config MAC80211_DEBUG
- bool "Enable debugging output"
- depends on MAC80211
+config MAC80211_NOINLINE
+ bool "Do not inline TX/RX handlers"
+ depends on MAC80211_DEBUG_MENU
---help---
- This option will enable debug tracing output for the
- ieee80211 network stack.
+ This option affects code generation in mac80211, when
+ selected some functions are marked "noinline" to allow
+ easier debugging of problems in the transmit and receive
+ paths.
- If you are not trying to debug or develop the ieee80211
- subsystem, you most likely want to say N here.
+ This option increases code size a bit and inserts a lot
+ of function calls in the code, but is otherwise safe to
+ enable.
+
+ If unsure, say N unless you expect to be finding problems
+ in mac80211.
+
+config MAC80211_VERBOSE_DEBUG
+ bool "Verbose debugging output"
+ depends on MAC80211_DEBUG_MENU
+ ---help---
+ Selecting this option causes mac80211 to print out
+ many debugging messages. It should not be selected
+ on production systems as some of the messages are
+ remotely triggerable.
+
+ Do not select this option.
config MAC80211_HT_DEBUG
- bool "Enable HT debugging output"
- depends on MAC80211_DEBUG
+ bool "Verbose HT debugging"
+ depends on MAC80211_DEBUG_MENU
---help---
This option enables 802.11n High Throughput features
debug tracing output.
- If you are not trying to debug of develop the ieee80211
- subsystem, you most likely want to say N here.
+ It should not be selected on production systems as some
+ of the messages are remotely triggerable.
-config MAC80211_VERBOSE_DEBUG
- bool "Verbose debugging output"
- depends on MAC80211_DEBUG
+ Do not select this option.
+
+config MAC80211_TKIP_DEBUG
+ bool "Verbose TKIP debugging"
+ depends on MAC80211_DEBUG_MENU
+ ---help---
+ Selecting this option causes mac80211 to print out
+ very verbose TKIP debugging messages. It should not
+ be selected on production systems as those messages
+ are remotely triggerable.
+
+ Do not select this option.
+
+config MAC80211_IBSS_DEBUG
+ bool "Verbose IBSS debugging"
+ depends on MAC80211_DEBUG_MENU
+ ---help---
+ Selecting this option causes mac80211 to print out
+ very verbose IBSS debugging messages. It should not
+ be selected on production systems as those messages
+ are remotely triggerable.
+
+ Do not select this option.
+
+config MAC80211_VERBOSE_PS_DEBUG
+ bool "Verbose powersave mode debugging"
+ depends on MAC80211_DEBUG_MENU
+ ---help---
+ Selecting this option causes mac80211 to print out very
+ verbose power save mode debugging messages (when mac80211
+ is an AP and has power saving stations.)
+ It should not be selected on production systems as those
+ messages are remotely triggerable.
+
+ Do not select this option.
+
+config MAC80211_VERBOSE_MPL_DEBUG
+ bool "Verbose mesh peer link debugging"
+ depends on MAC80211_DEBUG_MENU
+ depends on MAC80211_MESH
+ ---help---
+ Selecting this option causes mac80211 to print out very
+ verbose mesh peer link debugging messages (when mac80211
+ is taking part in a mesh network).
+ It should not be selected on production systems as those
+ messages are remotely triggerable.
+
+ Do not select this option.
config MAC80211_LOWTX_FRAME_DUMP
bool "Debug frame dumping"
- depends on MAC80211_DEBUG
+ depends on MAC80211_DEBUG_MENU
---help---
Selecting this option will cause the stack to
print a message for each frame that is handed
@@ -150,30 +205,21 @@
If unsure, say N and insert the debugging code
you require into the driver you are debugging.
-config MAC80211_TKIP_DEBUG
- bool "TKIP debugging"
- depends on MAC80211_DEBUG
-
config MAC80211_DEBUG_COUNTERS
bool "Extra statistics for TX/RX debugging"
depends on MAC80211_DEBUG
+ depends on MAC80211_DEBUG_MENU
+ depends on MAC80211_DEBUGFS
+ ---help---
+ Selecting this option causes mac80211 to keep additional
+ and very verbose statistics about TX and RX handler use
+ and show them in debugfs.
-config MAC80211_IBSS_DEBUG
- bool "Support for IBSS testing"
+ If unsure, say N.
+
+config MAC80211_VERBOSE_SPECT_MGMT_DEBUG
+ bool "Verbose Spectrum Management (IEEE 802.11h)debugging"
depends on MAC80211_DEBUG
---help---
- Say Y here if you intend to debug the IBSS code.
-
-config MAC80211_VERBOSE_PS_DEBUG
- bool "Verbose powersave mode debugging"
- depends on MAC80211_DEBUG
- ---help---
- Say Y here to print out verbose powersave
- mode debug messages.
-
-config MAC80211_VERBOSE_MPL_DEBUG
- bool "Verbose mesh peer link debugging"
- depends on MAC80211_DEBUG && MAC80211_MESH
- ---help---
- Say Y here to print out verbose mesh peer link
+ Say Y here to print out verbose Spectrum Management (IEEE 802.11h)
debug messages.
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 1d2a4e0..fa47438 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -1,13 +1,5 @@
obj-$(CONFIG_MAC80211) += mac80211.o
-# objects for PID algorithm
-rc80211_pid-y := rc80211_pid_algo.o
-rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o
-
-# build helper for PID algorithm
-rc-pid-y := $(rc80211_pid-y)
-rc-pid-m := rc80211_pid.o
-
# mac80211 objects
mac80211-y := \
main.o \
@@ -42,10 +34,8 @@
mesh_plink.o \
mesh_hwmp.o
+# objects for PID algorithm
+rc80211_pid-y := rc80211_pid_algo.o
+rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o
-# Build rate control algorithm(s)
-CFLAGS_rc80211_pid_algo.o += -DRC80211_PID_COMPILE
-mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc-pid-$(CONFIG_MAC80211_RC_PID))
-
-# Modular rate algorithms are assigned to mac80211-m - make separate modules
-obj-m += $(mac80211-m)
+mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc80211_pid-y)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index af352c0..f90da1b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -954,4 +954,10 @@
void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx,
struct ieee80211_hdr *hdr);
+#ifdef CONFIG_MAC80211_NOINLINE
+#define debug_noinline noinline
+#else
+#define debug_noinline
+#endif
+
#endif /* IEEE80211_I_H */
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 9844727..eeb1692 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -184,9 +184,9 @@
sdata->u.mntr_flags = MONITOR_FLAG_CONTROL |
MONITOR_FLAG_OTHER_BSS;
break;
- default:
- printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
- dev->name, __func__, type);
+ case IEEE80211_IF_TYPE_INVALID:
+ BUG();
+ break;
}
ieee80211_debugfs_change_if_type(sdata, oldtype);
}
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index b661ee5..f18cfd7 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -151,9 +151,7 @@
/* FIX: what would be proper limits for MTU?
* This interface uses 802.3 frames. */
if (new_mtu < 256 ||
- new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) {
- printk(KERN_WARNING "%s: invalid MTU %d\n",
- dev->name, new_mtu);
+ new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) {
return -EINVAL;
}
@@ -589,7 +587,9 @@
sta = sta_info_get(local, ra);
if (!sta) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Could not find the station\n");
+#endif
ret = -ENOENT;
goto exit;
}
@@ -617,9 +617,11 @@
sta->ampdu_mlme.tid_tx[tid] =
kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
if (!sta->ampdu_mlme.tid_tx[tid]) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
if (net_ratelimit())
printk(KERN_ERR "allocate tx mlme to tid %d failed\n",
tid);
+#endif
ret = -ENOMEM;
goto err_unlock_sta;
}
@@ -689,7 +691,9 @@
sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires =
jiffies + ADDBA_RESP_INTERVAL;
add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
+#endif
goto exit;
err_unlock_queue:
@@ -771,8 +775,10 @@
DECLARE_MAC_BUF(mac);
if (tid >= STA_TID_NUM) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
tid, STA_TID_NUM);
+#endif
return;
}
@@ -780,8 +786,10 @@
sta = sta_info_get(local, ra);
if (!sta) {
rcu_read_unlock();
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Could not find station: %s\n",
print_mac(mac, ra));
+#endif
return;
}
@@ -789,8 +797,10 @@
spin_lock_bh(&sta->lock);
if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
*state);
+#endif
spin_unlock_bh(&sta->lock);
rcu_read_unlock();
return;
@@ -801,7 +811,9 @@
*state |= HT_ADDBA_DRV_READY_MSK;
if (*state == HT_AGG_STATE_OPERATIONAL) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
+#endif
ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
}
spin_unlock_bh(&sta->lock);
@@ -818,8 +830,10 @@
DECLARE_MAC_BUF(mac);
if (tid >= STA_TID_NUM) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
tid, STA_TID_NUM);
+#endif
return;
}
@@ -831,8 +845,10 @@
rcu_read_lock();
sta = sta_info_get(local, ra);
if (!sta) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Could not find station: %s\n",
print_mac(mac, ra));
+#endif
rcu_read_unlock();
return;
}
@@ -842,7 +858,9 @@
* ieee80211_stop_tx_ba_session will let only
* one stop call to pass through per sta/tid */
if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
+#endif
rcu_read_unlock();
return;
}
@@ -884,9 +902,11 @@
struct sk_buff *skb = dev_alloc_skb(0);
if (unlikely(!skb)) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
if (net_ratelimit())
printk(KERN_WARNING "%s: Not enough memory, "
"dropping start BA session", skb->dev->name);
+#endif
return;
}
ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
@@ -907,9 +927,11 @@
struct sk_buff *skb = dev_alloc_skb(0);
if (unlikely(!skb)) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
if (net_ratelimit())
printk(KERN_WARNING "%s: Not enough memory, "
"dropping stop BA session", skb->dev->name);
+#endif
return;
}
ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
@@ -1236,9 +1258,8 @@
ra_tid->ra, ra_tid->tid);
dev_kfree_skb(skb);
break ;
- default: /* should never get here! */
- printk(KERN_ERR "%s: Unknown message type (%d)\n",
- wiphy_name(local->hw.wiphy), skb->pkt_type);
+ default:
+ WARN_ON(1);
dev_kfree_skb(skb);
break;
}
@@ -1365,12 +1386,14 @@
return;
}
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
if (net_ratelimit())
printk(KERN_DEBUG "%s: dropped TX filtered frame, "
"queue_len=%d PS=%d @%lu\n",
wiphy_name(local->hw.wiphy),
skb_queue_len(&sta->tx_filtered),
!!test_sta_flags(sta, WLAN_STA_PS), jiffies);
+#endif
dev_kfree_skb(skb);
}
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 947b13b4..5f88a2e 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -262,7 +262,6 @@
}
rcu_read_unlock();
}
-EXPORT_SYMBOL(mesh_plink_broken);
/**
* mesh_path_flush_by_nexthop - Deletes mesh paths if their next hop matches
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 7b4d4d4..4a3bddd 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -346,7 +346,7 @@
params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
params.cw_min = ecw2cw(pos[1] & 0x0f);
params.txop = pos[2] | (pos[3] << 8);
-#ifdef CONFIG_MAC80211_DEBUG
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
"cWmin=%d cWmax=%d txop=%d\n",
dev->name, queue, aci, acm, params.aifs, params.cw_min,
@@ -371,6 +371,7 @@
u32 changed = 0;
if (use_protection != bss_conf->use_cts_prot) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
"%s)\n",
@@ -378,11 +379,13 @@
use_protection ? "enabled" : "disabled",
print_mac(mac, ifsta->bssid));
}
+#endif
bss_conf->use_cts_prot = use_protection;
changed |= BSS_CHANGED_ERP_CTS_PROT;
}
if (use_short_preamble != bss_conf->use_short_preamble) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: switched to %s barker preamble"
" (BSSID=%s)\n",
@@ -390,6 +393,7 @@
use_short_preamble ? "short" : "long",
print_mac(mac, ifsta->bssid));
}
+#endif
bss_conf->use_short_preamble = use_short_preamble;
changed |= BSS_CHANGED_ERP_PREAMBLE;
}
@@ -747,6 +751,10 @@
* b-only mode) */
rates_len = ieee80211_compatible_rates(bss, sband, &rates);
+ if ((bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
+ (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
+ capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
+
ieee80211_rx_bss_put(dev, bss);
} else {
rates = ~0;
@@ -814,6 +822,26 @@
}
}
+ if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) {
+ /* 1. power capabilities */
+ pos = skb_put(skb, 4);
+ *pos++ = WLAN_EID_PWR_CAPABILITY;
+ *pos++ = 2;
+ *pos++ = 0; /* min tx power */
+ *pos++ = local->hw.conf.channel->max_power; /* max tx power */
+
+ /* 2. supported channels */
+ /* TODO: get this in reg domain format */
+ pos = skb_put(skb, 2 * sband->n_channels + 2);
+ *pos++ = WLAN_EID_SUPPORTED_CHANNELS;
+ *pos++ = 2 * sband->n_channels;
+ for (i = 0; i < sband->n_channels; i++) {
+ *pos++ = ieee80211_frequency_to_channel(
+ sband->channels[i].center_freq);
+ *pos++ = 1; /* one channel in the subband*/
+ }
+ }
+
if (ifsta->extra_ie) {
pos = skb_put(skb, ifsta->extra_ie_len);
memcpy(pos, ifsta->extra_ie, ifsta->extra_ie_len);
@@ -1151,14 +1179,10 @@
u8 *pos;
struct ieee802_11_elems elems;
- printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name);
pos = mgmt->u.auth.variable;
ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
- if (!elems.challenge) {
- printk(KERN_DEBUG "%s: no challenge IE in shared key auth "
- "frame\n", dev->name);
+ if (!elems.challenge)
return;
- }
ieee80211_send_auth(dev, ifsta, 3, elems.challenge - 2,
elems.challenge_len + 2, 1);
}
@@ -1340,9 +1364,11 @@
sta->ampdu_mlme.tid_rx[tid] =
kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC);
if (!sta->ampdu_mlme.tid_rx[tid]) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
if (net_ratelimit())
printk(KERN_ERR "allocate rx mlme to tid %d failed\n",
tid);
+#endif
goto end;
}
/* rx timer */
@@ -1358,9 +1384,11 @@
tid_agg_rx->reorder_buf =
kmalloc(buf_size * sizeof(struct sk_buff *), GFP_ATOMIC);
if (!tid_agg_rx->reorder_buf) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
if (net_ratelimit())
printk(KERN_ERR "can not allocate reordering buffer "
"to tid %d\n", tid);
+#endif
kfree(sta->ampdu_mlme.tid_rx[tid]);
goto end;
}
@@ -1427,8 +1455,6 @@
if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
spin_unlock_bh(&sta->lock);
- printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:"
- "%d\n", *state);
goto addba_resp_exit;
}
@@ -1447,22 +1473,14 @@
#endif /* CONFIG_MAC80211_HT_DEBUG */
if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
== WLAN_STATUS_SUCCESS) {
- if (*state & HT_ADDBA_RECEIVED_MSK)
- printk(KERN_DEBUG "double addBA response\n");
-
*state |= HT_ADDBA_RECEIVED_MSK;
sta->ampdu_mlme.addba_req_num[tid] = 0;
- if (*state == HT_AGG_STATE_OPERATIONAL) {
- printk(KERN_DEBUG "Aggregation on for tid %d \n", tid);
+ if (*state == HT_AGG_STATE_OPERATIONAL)
ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
- }
spin_unlock_bh(&sta->lock);
- printk(KERN_DEBUG "recipient accepted agg: tid %d \n", tid);
} else {
- printk(KERN_DEBUG "recipient rejected agg: tid %d \n", tid);
-
sta->ampdu_mlme.addba_req_num[tid]++;
/* this will allow the state check in stop_BA_session */
*state = HT_AGG_STATE_OPERATIONAL;
@@ -1561,7 +1579,7 @@
ra, tid, NULL);
if (ret)
printk(KERN_DEBUG "HW problem - can not stop rx "
- "aggergation for tid %d\n", tid);
+ "aggregation for tid %d\n", tid);
/* shutdown timer has not expired */
if (initiator != WLAN_BACK_TIMER)
@@ -1667,12 +1685,16 @@
if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
spin_unlock_bh(&sta->lock);
*state = HT_AGG_STATE_IDLE;
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "timer expired on tid %d but we are not "
"expecting addBA response there", tid);
+#endif
goto timer_expired_exit;
}
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid);
+#endif
/* go through the state check in stop_BA_session */
*state = HT_AGG_STATE_OPERATIONAL;
@@ -1700,7 +1722,9 @@
struct sta_info *sta = container_of(timer_to_id, struct sta_info,
timer_to_tid[0]);
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
+#endif
ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr,
(u16)*ptid, WLAN_BACK_TIMER,
WLAN_REASON_QSTA_TIMEOUT);
@@ -1795,47 +1819,24 @@
DECLARE_MAC_BUF(mac);
if (ifsta->state != IEEE80211_AUTHENTICATE &&
- sdata->vif.type != IEEE80211_IF_TYPE_IBSS) {
- printk(KERN_DEBUG "%s: authentication frame received from "
- "%s, but not in authenticate state - ignored\n",
- dev->name, print_mac(mac, mgmt->sa));
+ sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
return;
- }
- if (len < 24 + 6) {
- printk(KERN_DEBUG "%s: too short (%zd) authentication frame "
- "received from %s - ignored\n",
- dev->name, len, print_mac(mac, mgmt->sa));
+ if (len < 24 + 6)
return;
- }
if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
- memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
- printk(KERN_DEBUG "%s: authentication frame received from "
- "unknown AP (SA=%s BSSID=%s) - "
- "ignored\n", dev->name, print_mac(mac, mgmt->sa),
- print_mac(mac, mgmt->bssid));
+ memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0)
return;
- }
if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
- memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) {
- printk(KERN_DEBUG "%s: authentication frame received from "
- "unknown BSSID (SA=%s BSSID=%s) - "
- "ignored\n", dev->name, print_mac(mac, mgmt->sa),
- print_mac(mac, mgmt->bssid));
+ memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
return;
- }
auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
status_code = le16_to_cpu(mgmt->u.auth.status_code);
- printk(KERN_DEBUG "%s: RX authentication from %s (alg=%d "
- "transaction=%d status=%d)\n",
- dev->name, print_mac(mac, mgmt->sa), auth_alg,
- auth_transaction, status_code);
-
if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
/*
* IEEE 802.11 standard does not require authentication in IBSS
@@ -1843,26 +1844,16 @@
* However, try to reply to authentication attempts if someone
* has actually implemented this.
*/
- if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) {
- printk(KERN_DEBUG "%s: unexpected IBSS authentication "
- "frame (alg=%d transaction=%d)\n",
- dev->name, auth_alg, auth_transaction);
+ if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1)
return;
- }
ieee80211_send_auth(dev, ifsta, 2, NULL, 0, 0);
}
if (auth_alg != ifsta->auth_alg ||
- auth_transaction != ifsta->auth_transaction) {
- printk(KERN_DEBUG "%s: unexpected authentication frame "
- "(alg=%d transaction=%d)\n",
- dev->name, auth_alg, auth_transaction);
+ auth_transaction != ifsta->auth_transaction)
return;
- }
if (status_code != WLAN_STATUS_SUCCESS) {
- printk(KERN_DEBUG "%s: AP denied authentication (auth_alg=%d "
- "code=%d)\n", dev->name, ifsta->auth_alg, status_code);
if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
u8 algs[3];
const int num_algs = ARRAY_SIZE(algs);
@@ -1891,9 +1882,6 @@
!ieee80211_sta_wep_configured(dev))
continue;
ifsta->auth_alg = algs[pos];
- printk(KERN_DEBUG "%s: set auth_alg=%d for "
- "next try\n",
- dev->name, ifsta->auth_alg);
break;
}
}
@@ -1923,27 +1911,14 @@
u16 reason_code;
DECLARE_MAC_BUF(mac);
- if (len < 24 + 2) {
- printk(KERN_DEBUG "%s: too short (%zd) deauthentication frame "
- "received from %s - ignored\n",
- dev->name, len, print_mac(mac, mgmt->sa));
+ if (len < 24 + 2)
return;
- }
- if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
- printk(KERN_DEBUG "%s: deauthentication frame received from "
- "unknown AP (SA=%s BSSID=%s) - "
- "ignored\n", dev->name, print_mac(mac, mgmt->sa),
- print_mac(mac, mgmt->bssid));
+ if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN))
return;
- }
reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
- printk(KERN_DEBUG "%s: RX deauthentication from %s"
- " (reason=%d)\n",
- dev->name, print_mac(mac, mgmt->sa), reason_code);
-
if (ifsta->flags & IEEE80211_STA_AUTHENTICATED)
printk(KERN_DEBUG "%s: deauthenticated\n", dev->name);
@@ -1968,27 +1943,14 @@
u16 reason_code;
DECLARE_MAC_BUF(mac);
- if (len < 24 + 2) {
- printk(KERN_DEBUG "%s: too short (%zd) disassociation frame "
- "received from %s - ignored\n",
- dev->name, len, print_mac(mac, mgmt->sa));
+ if (len < 24 + 2)
return;
- }
- if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
- printk(KERN_DEBUG "%s: disassociation frame received from "
- "unknown AP (SA=%s BSSID=%s) - "
- "ignored\n", dev->name, print_mac(mac, mgmt->sa),
- print_mac(mac, mgmt->bssid));
+ if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN))
return;
- }
reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
- printk(KERN_DEBUG "%s: RX disassociation from %s"
- " (reason=%d)\n",
- dev->name, print_mac(mac, mgmt->sa), reason_code);
-
if (ifsta->flags & IEEE80211_STA_ASSOCIATED)
printk(KERN_DEBUG "%s: disassociated\n", dev->name);
@@ -2024,27 +1986,14 @@
/* AssocResp and ReassocResp have identical structure, so process both
* of them in this function. */
- if (ifsta->state != IEEE80211_ASSOCIATE) {
- printk(KERN_DEBUG "%s: association frame received from "
- "%s, but not in associate state - ignored\n",
- dev->name, print_mac(mac, mgmt->sa));
+ if (ifsta->state != IEEE80211_ASSOCIATE)
return;
- }
- if (len < 24 + 6) {
- printk(KERN_DEBUG "%s: too short (%zd) association frame "
- "received from %s - ignored\n",
- dev->name, len, print_mac(mac, mgmt->sa));
+ if (len < 24 + 6)
return;
- }
- if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
- printk(KERN_DEBUG "%s: association frame received from "
- "unknown AP (SA=%s BSSID=%s) - "
- "ignored\n", dev->name, print_mac(mac, mgmt->sa),
- print_mac(mac, mgmt->bssid));
+ if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0)
return;
- }
capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
@@ -2479,6 +2428,7 @@
memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
mgmt->u.beacon.beacon_int =
cpu_to_le16(local->hw.conf.beacon_int);
+ mgmt->u.beacon.timestamp = cpu_to_le64(bss->timestamp);
mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability);
pos = skb_put(skb, 2 + ifsta->ssid_len);
@@ -2622,11 +2572,10 @@
struct ieee80211_mgmt *mgmt,
size_t len,
struct ieee80211_rx_status *rx_status,
+ struct ieee802_11_elems *elems,
int beacon)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee802_11_elems elems;
- size_t baselen;
int freq, clen;
struct ieee80211_sta_bss *bss;
struct sta_info *sta;
@@ -2639,35 +2588,24 @@
if (!beacon && memcmp(mgmt->da, dev->dev_addr, ETH_ALEN))
return; /* ignore ProbeResp to foreign address */
-#if 0
- printk(KERN_DEBUG "%s: RX %s from %s to %s\n",
- dev->name, beacon ? "Beacon" : "Probe Response",
- print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da));
-#endif
-
- baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
- if (baselen > len)
- return;
-
beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
- ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
- if (ieee80211_vif_is_mesh(&sdata->vif) && elems.mesh_id &&
- elems.mesh_config && mesh_matches_local(&elems, dev)) {
- u64 rates = ieee80211_sta_get_rates(local, &elems,
+ if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id &&
+ elems->mesh_config && mesh_matches_local(elems, dev)) {
+ u64 rates = ieee80211_sta_get_rates(local, elems,
rx_status->band);
mesh_neighbour_update(mgmt->sa, rates, dev,
- mesh_peer_accepts_plinks(&elems, dev));
+ mesh_peer_accepts_plinks(elems, dev));
}
rcu_read_lock();
- if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
+ if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates &&
memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
(sta = sta_info_get(local, mgmt->sa))) {
u64 prev_rates;
- u64 supp_rates = ieee80211_sta_get_rates(local, &elems,
+ u64 supp_rates = ieee80211_sta_get_rates(local, elems,
rx_status->band);
prev_rates = sta->supp_rates[rx_status->band];
@@ -2679,21 +2617,12 @@
sta->supp_rates[rx_status->band] =
sdata->u.sta.supp_rates_bits[rx_status->band];
}
- if (sta->supp_rates[rx_status->band] != prev_rates) {
- printk(KERN_DEBUG "%s: updated supp_rates set for "
- "%s based on beacon info (0x%llx & 0x%llx -> "
- "0x%llx)\n",
- dev->name, print_mac(mac, sta->addr),
- (unsigned long long) prev_rates,
- (unsigned long long) supp_rates,
- (unsigned long long) sta->supp_rates[rx_status->band]);
- }
}
rcu_read_unlock();
- if (elems.ds_params && elems.ds_params_len == 1)
- freq = ieee80211_channel_to_frequency(elems.ds_params[0]);
+ if (elems->ds_params && elems->ds_params_len == 1)
+ freq = ieee80211_channel_to_frequency(elems->ds_params[0]);
else
freq = rx_status->freq;
@@ -2703,23 +2632,23 @@
return;
#ifdef CONFIG_MAC80211_MESH
- if (elems.mesh_config)
- bss = ieee80211_rx_mesh_bss_get(dev, elems.mesh_id,
- elems.mesh_id_len, elems.mesh_config, freq);
+ if (elems->mesh_config)
+ bss = ieee80211_rx_mesh_bss_get(dev, elems->mesh_id,
+ elems->mesh_id_len, elems->mesh_config, freq);
else
#endif
bss = ieee80211_rx_bss_get(dev, mgmt->bssid, freq,
- elems.ssid, elems.ssid_len);
+ elems->ssid, elems->ssid_len);
if (!bss) {
#ifdef CONFIG_MAC80211_MESH
- if (elems.mesh_config)
- bss = ieee80211_rx_mesh_bss_add(dev, elems.mesh_id,
- elems.mesh_id_len, elems.mesh_config,
- elems.mesh_config_len, freq);
+ if (elems->mesh_config)
+ bss = ieee80211_rx_mesh_bss_add(dev, elems->mesh_id,
+ elems->mesh_id_len, elems->mesh_config,
+ elems->mesh_config_len, freq);
else
#endif
bss = ieee80211_rx_bss_add(dev, mgmt->bssid, freq,
- elems.ssid, elems.ssid_len);
+ elems->ssid, elems->ssid_len);
if (!bss)
return;
} else {
@@ -2732,43 +2661,43 @@
}
/* save the ERP value so that it is available at association time */
- if (elems.erp_info && elems.erp_info_len >= 1) {
- bss->erp_value = elems.erp_info[0];
+ if (elems->erp_info && elems->erp_info_len >= 1) {
+ bss->erp_value = elems->erp_info[0];
bss->has_erp_value = 1;
}
- if (elems.ht_cap_elem &&
- (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len ||
- memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) {
+ if (elems->ht_cap_elem &&
+ (!bss->ht_ie || bss->ht_ie_len != elems->ht_cap_elem_len ||
+ memcmp(bss->ht_ie, elems->ht_cap_elem, elems->ht_cap_elem_len))) {
kfree(bss->ht_ie);
- bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC);
+ bss->ht_ie = kmalloc(elems->ht_cap_elem_len + 2, GFP_ATOMIC);
if (bss->ht_ie) {
- memcpy(bss->ht_ie, elems.ht_cap_elem - 2,
- elems.ht_cap_elem_len + 2);
- bss->ht_ie_len = elems.ht_cap_elem_len + 2;
+ memcpy(bss->ht_ie, elems->ht_cap_elem - 2,
+ elems->ht_cap_elem_len + 2);
+ bss->ht_ie_len = elems->ht_cap_elem_len + 2;
} else
bss->ht_ie_len = 0;
- } else if (!elems.ht_cap_elem && bss->ht_ie) {
+ } else if (!elems->ht_cap_elem && bss->ht_ie) {
kfree(bss->ht_ie);
bss->ht_ie = NULL;
bss->ht_ie_len = 0;
}
- if (elems.ht_info_elem &&
+ if (elems->ht_info_elem &&
(!bss->ht_add_ie ||
- bss->ht_add_ie_len != elems.ht_info_elem_len ||
- memcmp(bss->ht_add_ie, elems.ht_info_elem,
- elems.ht_info_elem_len))) {
+ bss->ht_add_ie_len != elems->ht_info_elem_len ||
+ memcmp(bss->ht_add_ie, elems->ht_info_elem,
+ elems->ht_info_elem_len))) {
kfree(bss->ht_add_ie);
bss->ht_add_ie =
- kmalloc(elems.ht_info_elem_len + 2, GFP_ATOMIC);
+ kmalloc(elems->ht_info_elem_len + 2, GFP_ATOMIC);
if (bss->ht_add_ie) {
- memcpy(bss->ht_add_ie, elems.ht_info_elem - 2,
- elems.ht_info_elem_len + 2);
- bss->ht_add_ie_len = elems.ht_info_elem_len + 2;
+ memcpy(bss->ht_add_ie, elems->ht_info_elem - 2,
+ elems->ht_info_elem_len + 2);
+ bss->ht_add_ie_len = elems->ht_info_elem_len + 2;
} else
bss->ht_add_ie_len = 0;
- } else if (!elems.ht_info_elem && bss->ht_add_ie) {
+ } else if (!elems->ht_info_elem && bss->ht_add_ie) {
kfree(bss->ht_add_ie);
bss->ht_add_ie = NULL;
bss->ht_add_ie_len = 0;
@@ -2778,20 +2707,20 @@
bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
bss->supp_rates_len = 0;
- if (elems.supp_rates) {
+ if (elems->supp_rates) {
clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
- if (clen > elems.supp_rates_len)
- clen = elems.supp_rates_len;
- memcpy(&bss->supp_rates[bss->supp_rates_len], elems.supp_rates,
+ if (clen > elems->supp_rates_len)
+ clen = elems->supp_rates_len;
+ memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates,
clen);
bss->supp_rates_len += clen;
}
- if (elems.ext_supp_rates) {
+ if (elems->ext_supp_rates) {
clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
- if (clen > elems.ext_supp_rates_len)
- clen = elems.ext_supp_rates_len;
+ if (clen > elems->ext_supp_rates_len)
+ clen = elems->ext_supp_rates_len;
memcpy(&bss->supp_rates[bss->supp_rates_len],
- elems.ext_supp_rates, clen);
+ elems->ext_supp_rates, clen);
bss->supp_rates_len += clen;
}
@@ -2815,33 +2744,33 @@
return;
}
- if (elems.wpa &&
- (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len ||
- memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) {
+ if (elems->wpa &&
+ (!bss->wpa_ie || bss->wpa_ie_len != elems->wpa_len ||
+ memcmp(bss->wpa_ie, elems->wpa, elems->wpa_len))) {
kfree(bss->wpa_ie);
- bss->wpa_ie = kmalloc(elems.wpa_len + 2, GFP_ATOMIC);
+ bss->wpa_ie = kmalloc(elems->wpa_len + 2, GFP_ATOMIC);
if (bss->wpa_ie) {
- memcpy(bss->wpa_ie, elems.wpa - 2, elems.wpa_len + 2);
- bss->wpa_ie_len = elems.wpa_len + 2;
+ memcpy(bss->wpa_ie, elems->wpa - 2, elems->wpa_len + 2);
+ bss->wpa_ie_len = elems->wpa_len + 2;
} else
bss->wpa_ie_len = 0;
- } else if (!elems.wpa && bss->wpa_ie) {
+ } else if (!elems->wpa && bss->wpa_ie) {
kfree(bss->wpa_ie);
bss->wpa_ie = NULL;
bss->wpa_ie_len = 0;
}
- if (elems.rsn &&
- (!bss->rsn_ie || bss->rsn_ie_len != elems.rsn_len ||
- memcmp(bss->rsn_ie, elems.rsn, elems.rsn_len))) {
+ if (elems->rsn &&
+ (!bss->rsn_ie || bss->rsn_ie_len != elems->rsn_len ||
+ memcmp(bss->rsn_ie, elems->rsn, elems->rsn_len))) {
kfree(bss->rsn_ie);
- bss->rsn_ie = kmalloc(elems.rsn_len + 2, GFP_ATOMIC);
+ bss->rsn_ie = kmalloc(elems->rsn_len + 2, GFP_ATOMIC);
if (bss->rsn_ie) {
- memcpy(bss->rsn_ie, elems.rsn - 2, elems.rsn_len + 2);
- bss->rsn_ie_len = elems.rsn_len + 2;
+ memcpy(bss->rsn_ie, elems->rsn - 2, elems->rsn_len + 2);
+ bss->rsn_ie_len = elems->rsn_len + 2;
} else
bss->rsn_ie_len = 0;
- } else if (!elems.rsn && bss->rsn_ie) {
+ } else if (!elems->rsn && bss->rsn_ie) {
kfree(bss->rsn_ie);
bss->rsn_ie = NULL;
bss->rsn_ie_len = 0;
@@ -2861,20 +2790,21 @@
* inclusion of the WMM Parameters in beacons, however, is optional.
*/
- if (elems.wmm_param &&
- (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len ||
- memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) {
+ if (elems->wmm_param &&
+ (!bss->wmm_ie || bss->wmm_ie_len != elems->wmm_param_len ||
+ memcmp(bss->wmm_ie, elems->wmm_param, elems->wmm_param_len))) {
kfree(bss->wmm_ie);
- bss->wmm_ie = kmalloc(elems.wmm_param_len + 2, GFP_ATOMIC);
+ bss->wmm_ie = kmalloc(elems->wmm_param_len + 2, GFP_ATOMIC);
if (bss->wmm_ie) {
- memcpy(bss->wmm_ie, elems.wmm_param - 2,
- elems.wmm_param_len + 2);
- bss->wmm_ie_len = elems.wmm_param_len + 2;
+ memcpy(bss->wmm_ie, elems->wmm_param - 2,
+ elems->wmm_param_len + 2);
+ bss->wmm_ie_len = elems->wmm_param_len + 2;
} else
bss->wmm_ie_len = 0;
- } else if (elems.wmm_info &&
- (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_info_len ||
- memcmp(bss->wmm_ie, elems.wmm_info, elems.wmm_info_len))) {
+ } else if (elems->wmm_info &&
+ (!bss->wmm_ie || bss->wmm_ie_len != elems->wmm_info_len ||
+ memcmp(bss->wmm_ie, elems->wmm_info,
+ elems->wmm_info_len))) {
/* As for certain AP's Fifth bit is not set in WMM IE in
* beacon frames.So while parsing the beacon frame the
* wmm_info structure is used instead of wmm_param.
@@ -2884,14 +2814,14 @@
* n-band association.
*/
kfree(bss->wmm_ie);
- bss->wmm_ie = kmalloc(elems.wmm_info_len + 2, GFP_ATOMIC);
+ bss->wmm_ie = kmalloc(elems->wmm_info_len + 2, GFP_ATOMIC);
if (bss->wmm_ie) {
- memcpy(bss->wmm_ie, elems.wmm_info - 2,
- elems.wmm_info_len + 2);
- bss->wmm_ie_len = elems.wmm_info_len + 2;
+ memcpy(bss->wmm_ie, elems->wmm_info - 2,
+ elems->wmm_info_len + 2);
+ bss->wmm_ie_len = elems->wmm_info_len + 2;
} else
bss->wmm_ie_len = 0;
- } else if (!elems.wmm_param && !elems.wmm_info && bss->wmm_ie) {
+ } else if (!elems->wmm_param && !elems->wmm_info && bss->wmm_ie) {
kfree(bss->wmm_ie);
bss->wmm_ie = NULL;
bss->wmm_ie_len = 0;
@@ -2902,8 +2832,9 @@
!local->sta_sw_scanning && !local->sta_hw_scanning &&
bss->capability & WLAN_CAPABILITY_IBSS &&
bss->freq == local->oper_channel->center_freq &&
- elems.ssid_len == sdata->u.sta.ssid_len &&
- memcmp(elems.ssid, sdata->u.sta.ssid, sdata->u.sta.ssid_len) == 0) {
+ elems->ssid_len == sdata->u.sta.ssid_len &&
+ memcmp(elems->ssid, sdata->u.sta.ssid,
+ sdata->u.sta.ssid_len) == 0) {
if (rx_status->flag & RX_FLAG_TSFT) {
/* in order for correct IBSS merging we need mactime
*
@@ -2941,11 +2872,10 @@
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
if (beacon_timestamp > rx_timestamp) {
#ifndef CONFIG_MAC80211_IBSS_DEBUG
- if (net_ratelimit())
+ printk(KERN_DEBUG "%s: beacon TSF higher than "
+ "local TSF - IBSS merge with BSSID %s\n",
+ dev->name, print_mac(mac, mgmt->bssid));
#endif
- printk(KERN_DEBUG "%s: beacon TSF higher than "
- "local TSF - IBSS merge with BSSID %s\n",
- dev->name, print_mac(mac, mgmt->bssid));
ieee80211_sta_join_ibss(dev, &sdata->u.sta, bss);
ieee80211_ibss_add_sta(dev, NULL,
mgmt->bssid, mgmt->sa,
@@ -2962,7 +2892,17 @@
size_t len,
struct ieee80211_rx_status *rx_status)
{
- ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 0);
+ size_t baselen;
+ struct ieee802_11_elems elems;
+
+ baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
+ if (baselen > len)
+ return;
+
+ ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
+ &elems);
+
+ ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 0);
}
@@ -2979,7 +2919,14 @@
struct ieee80211_conf *conf = &local->hw.conf;
u32 changed = 0;
- ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 1);
+ /* Process beacon from the current BSS */
+ baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
+ if (baselen > len)
+ return;
+
+ ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
+
+ ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 1);
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
@@ -2990,13 +2937,6 @@
memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
return;
- /* Process beacon from the current BSS */
- baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
- if (baselen > len)
- return;
-
- ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
-
ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
elems.wmm_param_len);
@@ -3075,11 +3015,11 @@
pos = mgmt->u.probe_req.variable;
if (pos[0] != WLAN_EID_SSID ||
pos + 2 + pos[1] > end) {
- if (net_ratelimit()) {
- printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq "
- "from %s\n",
- dev->name, print_mac(mac, mgmt->sa));
- }
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
+ printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq "
+ "from %s\n",
+ dev->name, print_mac(mac, mgmt->sa));
+#endif
return;
}
if (pos[1] != 0 &&
@@ -3148,11 +3088,6 @@
break;
ieee80211_sta_process_delba(dev, mgmt, len);
break;
- default:
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: Rx unknown A-MPDU action\n",
- dev->name);
- break;
}
break;
case PLINK_CATEGORY:
@@ -3163,11 +3098,6 @@
if (ieee80211_vif_is_mesh(&sdata->vif))
mesh_rx_path_sel_frame(dev, mgmt, len);
break;
- default:
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: Rx unknown action frame - "
- "category=%d\n", dev->name, mgmt->u.action.category);
- break;
}
}
@@ -3203,11 +3133,6 @@
skb_queue_tail(&ifsta->skb_queue, skb);
queue_work(local->hw.workqueue, &ifsta->work);
return;
- default:
- printk(KERN_DEBUG "%s: received unknown management frame - "
- "stype=%d\n", dev->name,
- (fc & IEEE80211_FCTL_STYPE) >> 4);
- break;
}
fail:
@@ -3336,8 +3261,10 @@
spin_lock_irqsave(&local->sta_lock, flags);
list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
if (time_after(jiffies, sta->last_rx + exp_time)) {
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
printk(KERN_DEBUG "%s: expiring inactive STA %s\n",
dev->name, print_mac(mac, sta->addr));
+#endif
__sta_info_unlink(&sta);
if (sta)
list_add(&sta->list, &tmp_list);
@@ -3420,13 +3347,10 @@
if (local->sta_sw_scanning || local->sta_hw_scanning)
return;
- if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
- sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
- sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) {
- printk(KERN_DEBUG "%s: ieee80211_sta_work: non-STA interface "
- "(type=%d)\n", dev->name, sdata->vif.type);
+ if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA &&
+ sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
+ sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT))
return;
- }
ifsta = &sdata->u.sta;
while ((skb = skb_dequeue(&ifsta->skb_queue)))
@@ -3480,8 +3404,7 @@
break;
#endif
default:
- printk(KERN_DEBUG "ieee80211_sta_work: Unknown state %d\n",
- ifsta->state);
+ WARN_ON(1);
break;
}
@@ -3516,8 +3439,6 @@
ifsta->auth_alg = WLAN_AUTH_LEAP;
else
ifsta->auth_alg = WLAN_AUTH_OPEN;
- printk(KERN_DEBUG "%s: Initial auth_alg=%d\n", dev->name,
- ifsta->auth_alg);
ifsta->auth_transaction = -1;
ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
ifsta->auth_tries = ifsta->assoc_tries = 0;
@@ -4316,6 +4237,13 @@
current_ev = iwe_stream_add_point(info, current_ev,
end_buf,
&iwe, buf);
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+ sprintf(buf, " Last beacon: %dms ago",
+ jiffies_to_msecs(jiffies - bss->last_update));
+ iwe.u.data.length = strlen(buf);
+ current_ev = iwe_stream_add_point(info, current_ev,
+ end_buf, &iwe, buf);
kfree(buf);
}
}
@@ -4436,8 +4364,10 @@
if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid))
return NULL;
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n",
wiphy_name(local->hw.wiphy), print_mac(mac, addr), dev->name);
+#endif
sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
if (!sta)
@@ -4464,7 +4394,7 @@
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
- printk(KERN_DEBUG "%s: deauthenticate(reason=%d)\n",
+ printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n",
dev->name, reason);
if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
@@ -4482,7 +4412,7 @@
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
- printk(KERN_DEBUG "%s: disassociate(reason=%d)\n",
+ printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n",
dev->name, reason);
if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index 0ed9c8a..ede7ab5 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -162,9 +162,7 @@
/* Rate control algorithms */
-#if defined(RC80211_PID_COMPILE) || \
- (defined(CONFIG_MAC80211_RC_PID) && \
- !defined(CONFIG_MAC80211_RC_PID_MODULE))
+#ifdef CONFIG_MAC80211_RC_PID
extern int rc80211_pid_init(void);
extern void rc80211_pid_exit(void);
#else
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c
index e894541..62388f8 100644
--- a/net/mac80211/rc80211_pid_algo.c
+++ b/net/mac80211/rc80211_pid_algo.c
@@ -540,11 +540,6 @@
#endif
};
-MODULE_DESCRIPTION("PID controller based rate control algorithm");
-MODULE_AUTHOR("Stefano Brivio");
-MODULE_AUTHOR("Mattias Nissler");
-MODULE_LICENSE("GPL");
-
int __init rc80211_pid_init(void)
{
return ieee80211_rate_control_register(&mac80211_rcpid);
@@ -554,8 +549,3 @@
{
ieee80211_rate_control_unregister(&mac80211_rcpid);
}
-
-#ifdef CONFIG_MAC80211_RC_PID_MODULE
-module_init(rc80211_pid_init);
-module_exit(rc80211_pid_exit);
-#endif
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 8962d13..6a88e8f 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -386,7 +386,7 @@
/* rx handlers */
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
{
struct ieee80211_local *local = rx->local;
@@ -463,7 +463,7 @@
}
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr;
@@ -522,7 +522,7 @@
}
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
@@ -613,11 +613,6 @@
rx->key->tx_rx_count++;
/* TODO: add threshold stuff again */
} else {
-#ifdef CONFIG_MAC80211_DEBUG
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: RX protected frame,"
- " but have no key\n", rx->dev->name);
-#endif /* CONFIG_MAC80211_DEBUG */
return RX_DROP_MONITOR;
}
@@ -710,7 +705,7 @@
return sent;
}
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
{
struct sta_info *sta = rx->sta;
@@ -789,7 +784,7 @@
sdata->fragment_next = 0;
if (!skb_queue_empty(&entry->skb_list)) {
-#ifdef CONFIG_MAC80211_DEBUG
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
struct ieee80211_hdr *hdr =
(struct ieee80211_hdr *) entry->skb_list.next->data;
DECLARE_MAC_BUF(mac);
@@ -801,7 +796,7 @@
jiffies - entry->first_frag_time, entry->seq,
entry->last_frag, print_mac(mac, hdr->addr1),
print_mac(mac2, hdr->addr2));
-#endif /* CONFIG_MAC80211_DEBUG */
+#endif
__skb_queue_purge(&entry->skb_list);
}
@@ -858,7 +853,7 @@
return NULL;
}
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr;
@@ -922,18 +917,8 @@
break;
}
rpn = rx->key->u.ccmp.rx_pn[rx->queue];
- if (memcmp(pn, rpn, CCMP_PN_LEN) != 0) {
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: defrag: CCMP PN not "
- "sequential A2=%s"
- " PN=%02x%02x%02x%02x%02x%02x "
- "(expected %02x%02x%02x%02x%02x%02x)\n",
- rx->dev->name, print_mac(mac, hdr->addr2),
- rpn[0], rpn[1], rpn[2], rpn[3], rpn[4],
- rpn[5], pn[0], pn[1], pn[2], pn[3],
- pn[4], pn[5]);
+ if (memcmp(pn, rpn, CCMP_PN_LEN))
return RX_DROP_UNUSABLE;
- }
memcpy(entry->last_pn, pn, CCMP_PN_LEN);
}
@@ -974,7 +959,7 @@
return RX_CONTINUE;
}
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
@@ -1037,7 +1022,7 @@
* have nothing buffered for it?
*/
printk(KERN_DEBUG "%s: STA %s sent PS Poll even "
- "though there is no buffered frames for it\n",
+ "though there are no buffered frames for it\n",
rx->dev->name, print_mac(mac, rx->sta->addr));
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
}
@@ -1049,7 +1034,7 @@
return RX_QUEUED;
}
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx)
{
u16 fc = rx->fc;
@@ -1073,14 +1058,8 @@
ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
{
if (unlikely(!rx->sta ||
- !test_sta_flags(rx->sta, WLAN_STA_AUTHORIZED))) {
-#ifdef CONFIG_MAC80211_DEBUG
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: dropped frame "
- "(unauthorized port)\n", rx->dev->name);
-#endif /* CONFIG_MAC80211_DEBUG */
+ !test_sta_flags(rx->sta, WLAN_STA_AUTHORIZED)))
return -EACCES;
- }
return 0;
}
@@ -1160,16 +1139,8 @@
memcpy(src, hdr->addr2, ETH_ALEN);
if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_AP &&
- sdata->vif.type != IEEE80211_IF_TYPE_VLAN)) {
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: dropped ToDS frame "
- "(BSSID=%s SA=%s DA=%s)\n",
- dev->name,
- print_mac(mac, hdr->addr1),
- print_mac(mac2, hdr->addr2),
- print_mac(mac3, hdr->addr3));
+ sdata->vif.type != IEEE80211_IF_TYPE_VLAN))
return -1;
- }
break;
case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
/* RA TA DA SA */
@@ -1177,17 +1148,8 @@
memcpy(src, hdr->addr4, ETH_ALEN);
if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS &&
- sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) {
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: dropped FromDS&ToDS "
- "frame (RA=%s TA=%s DA=%s SA=%s)\n",
- rx->dev->name,
- print_mac(mac, hdr->addr1),
- print_mac(mac2, hdr->addr2),
- print_mac(mac3, hdr->addr3),
- print_mac(mac4, hdr->addr4));
+ sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT))
return -1;
- }
break;
case IEEE80211_FCTL_FROMDS:
/* DA BSSID SA */
@@ -1204,27 +1166,13 @@
memcpy(dst, hdr->addr1, ETH_ALEN);
memcpy(src, hdr->addr2, ETH_ALEN);
- if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS) {
- if (net_ratelimit()) {
- printk(KERN_DEBUG "%s: dropped IBSS frame "
- "(DA=%s SA=%s BSSID=%s)\n",
- dev->name,
- print_mac(mac, hdr->addr1),
- print_mac(mac2, hdr->addr2),
- print_mac(mac3, hdr->addr3));
- }
+ if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
return -1;
- }
break;
}
- if (unlikely(skb->len - hdrlen < 8)) {
- if (net_ratelimit()) {
- printk(KERN_DEBUG "%s: RX too short data frame "
- "payload\n", dev->name);
- }
+ if (unlikely(skb->len - hdrlen < 8))
return -1;
- }
payload = skb->data + hdrlen;
ethertype = (payload[6] << 8) | payload[7];
@@ -1367,7 +1315,7 @@
}
}
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
{
struct net_device *dev = rx->dev;
@@ -1416,10 +1364,8 @@
padding = ((4 - subframe_len) & 0x3);
/* the last MSDU has no padding */
- if (subframe_len > remaining) {
- printk(KERN_DEBUG "%s: wrong buffer size\n", dev->name);
+ if (subframe_len > remaining)
return RX_DROP_UNUSABLE;
- }
skb_pull(skb, sizeof(struct ethhdr));
/* if last subframe reuse skb */
@@ -1440,8 +1386,6 @@
eth = (struct ethhdr *) skb_pull(skb, ntohs(len) +
padding);
if (!eth) {
- printk(KERN_DEBUG "%s: wrong buffer size\n",
- dev->name);
dev_kfree_skb(frame);
return RX_DROP_UNUSABLE;
}
@@ -1484,7 +1428,7 @@
return RX_QUEUED;
}
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
{
struct net_device *dev = rx->dev;
@@ -1515,7 +1459,7 @@
return RX_QUEUED;
}
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
{
struct ieee80211_local *local = rx->local;
@@ -1559,7 +1503,7 @@
return RX_CONTINUE;
}
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
{
struct ieee80211_sub_if_data *sdata;
@@ -1593,31 +1537,16 @@
else
keyidx = -1;
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: TKIP hwaccel reported Michael MIC "
- "failure from %s to %s keyidx=%d\n",
- dev->name, print_mac(mac, hdr->addr2),
- print_mac(mac2, hdr->addr1), keyidx);
-
if (!rx->sta) {
/*
* Some hardware seem to generate incorrect Michael MIC
* reports; ignore them to avoid triggering countermeasures.
*/
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: ignored spurious Michael MIC "
- "error for unknown address %s\n",
- dev->name, print_mac(mac, hdr->addr2));
goto ignore;
}
- if (!(rx->fc & IEEE80211_FCTL_PROTECTED)) {
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: ignored spurious Michael MIC "
- "error for a frame with no PROTECTED flag (src "
- "%s)\n", dev->name, print_mac(mac, hdr->addr2));
+ if (!(rx->fc & IEEE80211_FCTL_PROTECTED))
goto ignore;
- }
if (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP && keyidx) {
/*
@@ -1626,24 +1555,13 @@
* group keys and only the AP is sending real multicast
* frames in the BSS.
*/
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: ignored Michael MIC error for "
- "a frame with non-zero keyidx (%d)"
- " (src %s)\n", dev->name, keyidx,
- print_mac(mac, hdr->addr2));
goto ignore;
}
if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA &&
((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
- (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)) {
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: ignored spurious Michael MIC "
- "error for a frame that cannot be encrypted "
- "(fc=0x%04x) (src %s)\n",
- dev->name, rx->fc, print_mac(mac, hdr->addr2));
+ (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH))
goto ignore;
- }
mac80211_ev_michael_mic_failure(rx->dev, keyidx, hdr);
ignore:
@@ -1732,66 +1650,57 @@
dev_kfree_skb(skb);
}
-typedef ieee80211_rx_result (*ieee80211_rx_handler)(struct ieee80211_rx_data *);
-static ieee80211_rx_handler ieee80211_rx_handlers[] =
-{
- ieee80211_rx_h_passive_scan,
- ieee80211_rx_h_check,
- ieee80211_rx_h_decrypt,
- ieee80211_rx_h_sta_process,
- ieee80211_rx_h_defragment,
- ieee80211_rx_h_ps_poll,
- ieee80211_rx_h_michael_mic_verify,
- /* this must be after decryption - so header is counted in MPDU mic
- * must be before pae and data, so QOS_DATA format frames
- * are not passed to user space by these functions
- */
- ieee80211_rx_h_remove_qos_control,
- ieee80211_rx_h_amsdu,
- ieee80211_rx_h_data,
- ieee80211_rx_h_ctrl,
- ieee80211_rx_h_mgmt,
- NULL
-};
static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
struct ieee80211_rx_data *rx,
struct sk_buff *skb)
{
- ieee80211_rx_handler *handler;
ieee80211_rx_result res = RX_DROP_MONITOR;
rx->skb = skb;
rx->sdata = sdata;
rx->dev = sdata->dev;
- for (handler = ieee80211_rx_handlers; *handler != NULL; handler++) {
- res = (*handler)(rx);
+#define CALL_RXH(rxh) \
+ res = rxh(rx); \
+ if (res != RX_CONTINUE) \
+ goto rxh_done;
- switch (res) {
- case RX_CONTINUE:
- continue;
- case RX_DROP_UNUSABLE:
- case RX_DROP_MONITOR:
- I802_DEBUG_INC(sdata->local->rx_handlers_drop);
- if (rx->sta)
- rx->sta->rx_dropped++;
- break;
- case RX_QUEUED:
- I802_DEBUG_INC(sdata->local->rx_handlers_queued);
- break;
- }
- break;
- }
+ CALL_RXH(ieee80211_rx_h_passive_scan)
+ CALL_RXH(ieee80211_rx_h_check)
+ CALL_RXH(ieee80211_rx_h_decrypt)
+ CALL_RXH(ieee80211_rx_h_sta_process)
+ CALL_RXH(ieee80211_rx_h_defragment)
+ CALL_RXH(ieee80211_rx_h_ps_poll)
+ CALL_RXH(ieee80211_rx_h_michael_mic_verify)
+ /* must be after MMIC verify so header is counted in MPDU mic */
+ CALL_RXH(ieee80211_rx_h_remove_qos_control)
+ CALL_RXH(ieee80211_rx_h_amsdu)
+ CALL_RXH(ieee80211_rx_h_data)
+ CALL_RXH(ieee80211_rx_h_ctrl)
+ CALL_RXH(ieee80211_rx_h_mgmt)
+#undef CALL_RXH
+
+ rxh_done:
switch (res) {
- case RX_CONTINUE:
case RX_DROP_MONITOR:
+ I802_DEBUG_INC(sdata->local->rx_handlers_drop);
+ if (rx->sta)
+ rx->sta->rx_dropped++;
+ /* fall through */
+ case RX_CONTINUE:
ieee80211_rx_cooked_monitor(rx);
break;
case RX_DROP_UNUSABLE:
+ I802_DEBUG_INC(sdata->local->rx_handlers_drop);
+ if (rx->sta)
+ rx->sta->rx_dropped++;
dev_kfree_skb(rx->skb);
break;
+ case RX_QUEUED:
+ I802_DEBUG_INC(sdata->local->rx_handlers_queued);
+ break;
}
}
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index b3c7331..d8a16b7 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -554,8 +554,10 @@
sdata = sta->sdata;
local->total_ps_buffered--;
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "Buffered frame expired (STA "
"%s)\n", print_mac(mac, sta->addr));
+#endif
dev_kfree_skb(skb);
if (skb_queue_empty(&sta->ps_tx_buf))
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 52ab85c..9bd9faa 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -220,7 +220,7 @@
/* tx handlers */
-static ieee80211_tx_result
+static ieee80211_tx_result debug_noinline
ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
{
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
@@ -274,7 +274,7 @@
return TX_CONTINUE;
}
-static ieee80211_tx_result
+static ieee80211_tx_result debug_noinline
ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
@@ -327,8 +327,10 @@
rcu_read_unlock();
local->total_ps_buffered = total;
+#ifdef MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n",
wiphy_name(local->hw.wiphy), purged);
+#endif
}
static ieee80211_tx_result
@@ -358,11 +360,13 @@
purge_old_ps_buffers(tx->local);
if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >=
AP_MAX_BC_BUFFER) {
+#ifdef MAC80211_VERBOSE_PS_DEBUG
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: BC TX buffer full - "
"dropping the oldest frame\n",
tx->dev->name);
}
+#endif
dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf));
} else
tx->local->total_ps_buffered++;
@@ -403,11 +407,13 @@
purge_old_ps_buffers(tx->local);
if (skb_queue_len(&sta->ps_tx_buf) >= STA_MAX_TX_BUFFER) {
struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf);
+#ifdef MAC80211_VERBOSE_PS_DEBUG
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: STA %s TX "
"buffer full - dropping oldest frame\n",
tx->dev->name, print_mac(mac, sta->addr));
}
+#endif
dev_kfree_skb(old);
} else
tx->local->total_ps_buffered++;
@@ -432,7 +438,7 @@
return TX_CONTINUE;
}
-static ieee80211_tx_result
+static ieee80211_tx_result debug_noinline
ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
{
if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED))
@@ -444,7 +450,7 @@
return ieee80211_tx_h_multicast_ps_buf(tx);
}
-static ieee80211_tx_result
+static ieee80211_tx_result debug_noinline
ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
{
struct ieee80211_key *key;
@@ -493,7 +499,7 @@
return TX_CONTINUE;
}
-static ieee80211_tx_result
+static ieee80211_tx_result debug_noinline
ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
{
struct rate_selection rsel;
@@ -537,7 +543,7 @@
return TX_CONTINUE;
}
-static ieee80211_tx_result
+static ieee80211_tx_result debug_noinline
ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
@@ -632,7 +638,7 @@
return TX_CONTINUE;
}
-static ieee80211_tx_result
+static ieee80211_tx_result debug_noinline
ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
@@ -713,7 +719,6 @@
return TX_CONTINUE;
fail:
- printk(KERN_DEBUG "%s: failed to fragment frame\n", tx->dev->name);
if (frags) {
for (i = 0; i < num_fragm - 1; i++)
if (frags[i])
@@ -724,7 +729,7 @@
return TX_DROP;
}
-static ieee80211_tx_result
+static ieee80211_tx_result debug_noinline
ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
{
if (!tx->key)
@@ -744,7 +749,7 @@
return TX_DROP;
}
-static ieee80211_tx_result
+static ieee80211_tx_result debug_noinline
ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
@@ -774,7 +779,7 @@
return TX_CONTINUE;
}
-static ieee80211_tx_result
+static ieee80211_tx_result debug_noinline
ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
{
int i;
@@ -795,24 +800,6 @@
}
-typedef ieee80211_tx_result (*ieee80211_tx_handler)(struct ieee80211_tx_data *);
-static ieee80211_tx_handler ieee80211_tx_handlers[] =
-{
- ieee80211_tx_h_check_assoc,
- ieee80211_tx_h_sequence,
- ieee80211_tx_h_ps_buf,
- ieee80211_tx_h_select_key,
- ieee80211_tx_h_michael_mic_add,
- ieee80211_tx_h_rate_ctrl,
- ieee80211_tx_h_misc,
- ieee80211_tx_h_fragment,
- /* handlers after fragment must be aware of tx info fragmentation! */
- ieee80211_tx_h_encrypt,
- ieee80211_tx_h_calculate_duration,
- ieee80211_tx_h_stats,
- NULL
-};
-
/* actual transmit path */
/*
@@ -1110,20 +1097,32 @@
*/
static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
{
- struct ieee80211_local *local = tx->local;
struct sk_buff *skb = tx->skb;
- ieee80211_tx_handler *handler;
ieee80211_tx_result res = TX_DROP;
int i;
- for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) {
- res = (*handler)(tx);
- if (res != TX_CONTINUE)
- break;
- }
+#define CALL_TXH(txh) \
+ res = txh(tx); \
+ if (res != TX_CONTINUE) \
+ goto txh_done;
+ CALL_TXH(ieee80211_tx_h_check_assoc)
+ CALL_TXH(ieee80211_tx_h_sequence)
+ CALL_TXH(ieee80211_tx_h_ps_buf)
+ CALL_TXH(ieee80211_tx_h_select_key)
+ CALL_TXH(ieee80211_tx_h_michael_mic_add)
+ CALL_TXH(ieee80211_tx_h_rate_ctrl)
+ CALL_TXH(ieee80211_tx_h_misc)
+ CALL_TXH(ieee80211_tx_h_fragment)
+ /* handlers after fragment must be aware of tx info fragmentation! */
+ CALL_TXH(ieee80211_tx_h_encrypt)
+ CALL_TXH(ieee80211_tx_h_calculate_duration)
+ CALL_TXH(ieee80211_tx_h_stats)
+#undef CALL_TXH
+
+ txh_done:
if (unlikely(res == TX_DROP)) {
- I802_DEBUG_INC(local->tx_handlers_drop);
+ I802_DEBUG_INC(tx->local->tx_handlers_drop);
dev_kfree_skb(skb);
for (i = 0; i < tx->num_extra_frag; i++)
if (tx->extra_frag[i])
@@ -1131,7 +1130,7 @@
kfree(tx->extra_frag);
return -1;
} else if (unlikely(res == TX_QUEUED)) {
- I802_DEBUG_INC(local->tx_handlers_queued);
+ I802_DEBUG_INC(tx->local->tx_handlers_queued);
return -1;
}
@@ -1410,8 +1409,6 @@
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (unlikely(skb->len < ETH_HLEN)) {
- printk(KERN_DEBUG "%s: short skb (len=%d)\n",
- dev->name, skb->len);
ret = 0;
goto fail;
}
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index 35b664d..872d2fc 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -253,11 +253,8 @@
if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen,
skb->data + hdrlen + WEP_IV_LEN,
- len)) {
- if (net_ratelimit())
- printk(KERN_DEBUG "WEP decrypt failed (ICV)\n");
+ len))
ret = -1;
- }
kfree(rc4key);
@@ -301,14 +298,8 @@
return RX_CONTINUE;
if (!(rx->status->flag & RX_FLAG_DECRYPTED)) {
- if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) {
-#ifdef CONFIG_MAC80211_DEBUG
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: RX WEP frame, decrypt "
- "failed\n", rx->dev->name);
-#endif /* CONFIG_MAC80211_DEBUG */
+ if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key))
return RX_DROP_UNUSABLE;
- }
} else if (!(rx->status->flag & RX_FLAG_IV_STRIPPED)) {
ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
/* remove ICV */
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index cfa8fbb..f23b5a4 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -680,7 +680,6 @@
if (!qdisc || !qdisc->dequeue)
return;
- printk(KERN_DEBUG "requeue: qlen = %d\n", qdisc->q.qlen);
for (len = qdisc->q.qlen; len > 0; len--) {
skb = qdisc->dequeue(qdisc);
root_qd->q.qlen--;
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index f809761..b414d5d 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -146,9 +146,6 @@
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
return RX_DROP_UNUSABLE;
- printk(KERN_DEBUG "%s: invalid Michael MIC in data frame from "
- "%s\n", rx->dev->name, print_mac(mac, sa));
-
mac80211_ev_michael_mic_failure(rx->dev, rx->key->conf.keyidx,
(void *) skb->data);
return RX_DROP_UNUSABLE;
@@ -282,15 +279,8 @@
hdr->addr1, hwaccel, rx->queue,
&rx->tkip_iv32,
&rx->tkip_iv16);
- if (res != TKIP_DECRYPT_OK || wpa_test) {
-#ifdef CONFIG_MAC80211_DEBUG
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: TKIP decrypt failed for RX "
- "frame from %s (res=%d)\n", rx->dev->name,
- print_mac(mac, rx->sta->addr), res);
-#endif /* CONFIG_MAC80211_DEBUG */
+ if (res != TKIP_DECRYPT_OK || wpa_test)
return RX_DROP_UNUSABLE;
- }
/* Trim ICV */
skb_trim(skb, skb->len - TKIP_ICV_LEN);
@@ -512,16 +502,6 @@
(void) ccmp_hdr2pn(pn, skb->data + hdrlen);
if (memcmp(pn, key->u.ccmp.rx_pn[rx->queue], CCMP_PN_LEN) <= 0) {
-#ifdef CONFIG_MAC80211_DEBUG
- u8 *ppn = key->u.ccmp.rx_pn[rx->queue];
-
- printk(KERN_DEBUG "%s: CCMP replay detected for RX frame from "
- "%s (RX PN %02x%02x%02x%02x%02x%02x <= prev. PN "
- "%02x%02x%02x%02x%02x%02x)\n", rx->dev->name,
- print_mac(mac, rx->sta->addr),
- pn[0], pn[1], pn[2], pn[3], pn[4], pn[5],
- ppn[0], ppn[1], ppn[2], ppn[3], ppn[4], ppn[5]);
-#endif /* CONFIG_MAC80211_DEBUG */
key->u.ccmp.replays++;
return RX_DROP_UNUSABLE;
}
@@ -541,12 +521,6 @@
skb->data + hdrlen + CCMP_HDR_LEN, data_len,
skb->data + skb->len - CCMP_MIC_LEN,
skb->data + hdrlen + CCMP_HDR_LEN)) {
-#ifdef CONFIG_MAC80211_DEBUG
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: CCMP decrypt failed "
- "for RX frame from %s\n", rx->dev->name,
- print_mac(mac, rx->sta->addr));
-#endif /* CONFIG_MAC80211_DEBUG */
return RX_DROP_UNUSABLE;
}
}