mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 19:29:37 +00:00
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
f3032be921
45 changed files with 2041 additions and 2132 deletions
|
@ -43,6 +43,23 @@ static bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
|
|||
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 @@ static void b43_rfkill_poll(struct input_polled_dev *poll_dev)
|
|||
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 @@ void b43_rfkill_init(struct b43_wldev *dev)
|
|||
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;
|
||||
|
|
|
@ -44,6 +44,23 @@ static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
|
|||
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 @@ static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev)
|
|||
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 @@ void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
|
|||
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;
|
||||
|
|
|
@ -78,6 +78,9 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
|
|||
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->f.status = s; hdr->f.len = l; hdr->f.data = d
|
|||
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;
|
||||
|
|
|
@ -3204,6 +3204,7 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,
|
|||
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);
|
||||
|
|
|
@ -897,6 +897,8 @@ static void hostap_monitor_set_type(local_info_t *local)
|
|||
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 @@ static int prism2_ioctl_priv_prism2_param(struct net_device *dev,
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -596,25 +596,7 @@ void hostap_dump_tx_header(const char *name, const struct hfa384x_tx_frame *tx)
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 @@ struct linux_wlan_ng_cap_hdr {
|
|||
__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 @@ struct local_info {
|
|||
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;
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ config IWLCORE
|
|||
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
|
||||
|
|
|
@ -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 @@ enum {
|
|||
|
||||
#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_priv {
|
|||
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;
|
||||
|
|
|
@ -822,9 +822,6 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
|
|||
|
||||
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 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
|
|||
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 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
|
|||
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 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
|
|||
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 @@ static void rs_clear(void *priv_rate)
|
|||
|
||||
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 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
|
|||
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);
|
||||
|
|
|
@ -295,14 +295,6 @@ static inline u8 iwl4965_get_prev_ieee_rate(u8 rate_index)
|
|||
*/
|
||||
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
|
||||
*
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -675,7 +675,7 @@ static void iwl5000_init_alive_start(struct iwl_priv *priv)
|
|||
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 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
|
|||
|
||||
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 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
|
|||
|
||||
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 @@ static int iwl5000_send_tx_power(struct iwl_priv *priv)
|
|||
|
||||
/* 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 @@ static struct iwl_lib_ops iwl5000_lib = {
|
|||
.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_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, 0444);
|
|||
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);
|
||||
|
|
|
@ -470,7 +470,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
|
|||
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 @@ EXPORT_SYMBOL(iwl_sensitivity_calibration);
|
|||
* 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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -336,6 +336,8 @@ struct iwl4965_tx_power_db {
|
|||
* 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 @@ struct iwl5000_tx_resp {
|
|||
*
|
||||
* 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 @@ struct statistics_general {
|
|||
*/
|
||||
#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 @@ struct iwl4965_statistics_cmd {
|
|||
*/
|
||||
#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_rx_packet {
|
|||
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;
|
||||
|
|
|
@ -273,22 +273,27 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
|
|||
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 @@ static int iwlcore_init_geos(struct iwl_priv *priv)
|
|||
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 @@ static int iwlcore_init_geos(struct iwl_priv *priv)
|
|||
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 @@ int iwl_setup_mac(struct iwl_priv *priv)
|
|||
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 @@ int iwl_setup_mac(struct iwl_priv *priv)
|
|||
}
|
||||
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 @@ int iwl_init_drv(struct iwl_priv *priv)
|
|||
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 @@ int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv)
|
|||
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 @@ int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv)
|
|||
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);
|
||||
|
|
|
@ -140,6 +140,7 @@ struct iwl_lib_ops {
|
|||
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 @@ struct iwl_mod_params {
|
|||
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_hw *iwl_alloc_all(struct iwl_cfg *cfg,
|
|||
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 @@ u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
|
|||
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 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
|
|||
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 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
|
|||
/* 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 void iwl_rf_kill_ct_config(struct iwl_priv *priv);
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -591,11 +591,6 @@ extern int iwl_send_add_sta(struct iwl_priv *priv,
|
|||
struct iwl_addsta_cmd *sta, u8 flags);
|
||||
u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
|
||||
u8 flags, struct ieee80211_ht_info *ht_info);
|
||||
extern 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 int iwl_rxq_stop(struct iwl_priv *priv);
|
|||
extern void iwl_txq_ctx_stop(struct iwl_priv *priv);
|
||||
extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
|
||||
struct iwl_frame *frame, u8 rate);
|
||||
extern void iwl4965_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 @@ struct iwl4965_lq_mngr {
|
|||
unsigned long stamp_last;
|
||||
u32 flush_time;
|
||||
u32 tx_packets;
|
||||
u8 lq_ready;
|
||||
};
|
||||
|
||||
/* Sensitivity and chain noise calibration */
|
||||
|
@ -994,7 +984,7 @@ struct iwl_priv {
|
|||
|
||||
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 @@ struct iwl_priv {
|
|||
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;
|
||||
|
|
|
@ -93,6 +93,7 @@ const char *get_cmd_string(u8 cmd)
|
|||
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";
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
|
|||
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 @@ int iwl_rfkill_init(struct iwl_priv *priv)
|
|||
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 @@ int iwl_rfkill_init(struct iwl_priv *priv)
|
|||
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 @@ EXPORT_SYMBOL(iwl_rfkill_init);
|
|||
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 @@ EXPORT_SYMBOL(iwl_rfkill_unregister);
|
|||
/* set rf-kill to the right state. */
|
||||
void iwl_rfkill_set_hw_state(struct iwl_priv *priv)
|
||||
{
|
||||
|
||||
if (!priv->rfkill_mngr.rfkill)
|
||||
return;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
#include <net/mac80211.h>
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-dev.h"
|
||||
|
@ -466,3 +467,858 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
|
|||
}
|
||||
}
|
||||
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);
|
||||
|
|
|
@ -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 @@ int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
|
|||
}
|
||||
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 @@ static int iwl_add_sta_callback(struct iwl_priv *priv,
|
|||
|
||||
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 @@ int iwl_send_add_sta(struct iwl_priv *priv,
|
|||
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 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
|
|||
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 @@ static int iwl_remove_sta_callback(struct iwl_priv *priv,
|
|||
iwl_sta_ucode_deactivate(priv, addr);
|
||||
break;
|
||||
default:
|
||||
IWL_ERROR("REPLY_REMOVE_STA failed\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -386,44 +410,63 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
|
|||
/**
|
||||
* 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 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,
|
|||
|
||||
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 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap)
|
|||
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.
|
||||
*
|
||||
|
|
|
@ -48,7 +48,7 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
|
|||
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);
|
||||
|
|
|
@ -1350,6 +1350,149 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id)
|
|||
}
|
||||
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
|
||||
|
||||
|
|
|
@ -970,7 +970,7 @@ static int iwl3945_full_rxon_required(struct iwl3945_priv *priv)
|
|||
{
|
||||
|
||||
/* 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 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
|
|||
#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 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
|
|||
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 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
|
|||
goto drop_unlock;
|
||||
}
|
||||
|
||||
if (!priv->vif) {
|
||||
IWL_DEBUG_DROP("Dropping - !priv->vif\n");
|
||||
goto drop_unlock;
|
||||
}
|
||||
|
||||
if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) {
|
||||
IWL_ERROR("ERROR: No TX rate available.\n");
|
||||
goto drop_unlock;
|
||||
|
@ -2603,9 +2603,10 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
|
|||
#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 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
|
|||
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 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
|
|||
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 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
|
|||
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 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
|
|||
|
||||
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 @@ static void iwl3945_bg_rf_kill(struct work_struct *work)
|
|||
"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 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
|
||||
IWL_DEBUG_MAC80211("enter\n");
|
||||
|
||||
if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
|
||||
IWL_DEBUG_MAC80211("leave - monitor\n");
|
||||
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 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv)
|
|||
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 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw,
|
|||
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 @@ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
|
|||
|
||||
#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 @@ static struct attribute *iwl3945_sysfs_entries[] = {
|
|||
#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 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
|||
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 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
|
|||
|
||||
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 @@ static int iwl3945_pci_resume(struct pci_dev *pdev)
|
|||
|
||||
#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
|
||||
|
|
|
@ -192,7 +192,7 @@ static int iwl4965_full_rxon_required(struct iwl_priv *priv)
|
|||
{
|
||||
|
||||
/* 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 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
|
|||
/* 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 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
|
|||
* 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 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
|
|||
* 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 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
|
|||
"* 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 @@ static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force)
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ static void iwl4965_connection_init_rx_config(struct iwl_priv *priv)
|
|||
#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 @@ static int iwl4965_set_mode(struct iwl_priv *priv, int mode)
|
|||
{
|
||||
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 @@ static void iwl4965_set_rate(struct iwl_priv *priv)
|
|||
(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 @@ static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
|
|||
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 @@ static void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
|
|||
* 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 @@ static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
|
|||
* 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 @@ static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
|
|||
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 @@ void iwl_rx_handle(struct iwl_priv *priv)
|
|||
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 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
|
|||
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 @@ static void iwl_alive_start(struct iwl_priv *priv)
|
|||
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 @@ static void __iwl4965_down(struct iwl_priv *priv)
|
|||
|
||||
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 @@ static void __iwl4965_down(struct iwl_priv *priv)
|
|||
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 @@ static void __iwl4965_down(struct iwl_priv *priv)
|
|||
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 @@ static int __iwl4965_up(struct iwl_priv *priv)
|
|||
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 @@ static int __iwl4965_up(struct iwl_priv *priv)
|
|||
|
||||
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 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
|
|||
|
||||
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 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
|
|||
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 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
|
|||
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 @@ static void iwl_bg_scan_completed(struct work_struct *work)
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#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 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw)
|
|||
|
||||
/* 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 @@ static void iwl4965_config_ap(struct iwl_priv *priv)
|
|||
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 @@ static void iwl4965_configure_filter(struct ieee80211_hw *hw,
|
|||
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 @@ static int iwl4965_mac_get_stats(struct ieee80211_hw *hw,
|
|||
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 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
|
|||
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 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
|
|||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
unsigned long flags;
|
||||
__le64 timestamp;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211("enter\n");
|
||||
|
@ -3662,6 +3493,8 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
|
|||
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 @@ static ssize_t show_version(struct device *d,
|
|||
{
|
||||
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 @@ static ssize_t show_statistics(struct device *d,
|
|||
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 @@ static struct ieee80211_ops iwl4965_hw_ops = {
|
|||
.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 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
|||
/************************
|
||||
* 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 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
|||
|
||||
|
||||
iwl_setup_deferred_work(priv);
|
||||
iwl4965_setup_rx_handlers(priv);
|
||||
iwl_setup_rx_handlers(priv);
|
||||
|
||||
/********************
|
||||
* 9. Conclude
|
||||
|
@ -4461,8 +4304,6 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
|||
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 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
|
|||
|
||||
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 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
|
|||
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);
|
||||
|
||||
|
||||
|
|
|
@ -357,6 +357,7 @@ static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
|
|||
|
||||
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;
|
||||
|
|
|
@ -710,6 +710,10 @@ enum ieee80211_tkip_key_type {
|
|||
* @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 @@ enum ieee80211_hw_flags {
|
|||
IEEE80211_HW_SIGNAL_DB = 1<<6,
|
||||
IEEE80211_HW_SIGNAL_DBM = 1<<7,
|
||||
IEEE80211_HW_NOISE_DBM = 1<<8,
|
||||
IEEE80211_HW_SPECTRUM_MGMT = 1<<9,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,6 +27,14 @@ comment "QoS/HT support needs CONFIG_NETDEVICES_MULTIQUEUE"
|
|||
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 @@ choice
|
|||
|
||||
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 @@ config MAC80211_DEBUGFS
|
|||
|
||||
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 @@ config MAC80211_DEBUG_PACKET_ALIGNMENT
|
|||
|
||||
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 @@ config MAC80211_LOWTX_FRAME_DUMP
|
|||
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.
|
||||
|
|
|
@ -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 @@ mac80211-$(CONFIG_MAC80211_MESH) += \
|
|||
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)
|
||||
|
|
|
@ -954,4 +954,10 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
|
|||
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 */
|
||||
|
|
|
@ -184,9 +184,9 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -151,9 +151,7 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
|
|||
/* 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 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
|||
|
||||
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 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
|||
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 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
|||
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 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
|||
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 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
|||
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 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
|||
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 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
|||
*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 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
|
|||
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 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
|
|||
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 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
|
|||
* 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 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
|
|||
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 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
|
|||
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 @@ static void ieee80211_tasklet_handler(unsigned long data)
|
|||
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 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -262,7 +262,6 @@ void mesh_plink_broken(struct sta_info *sta)
|
|||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL(mesh_plink_broken);
|
||||
|
||||
/**
|
||||
* mesh_path_flush_by_nexthop - Deletes mesh paths if their next hop matches
|
||||
|
|
|
@ -346,7 +346,7 @@ static void ieee80211_sta_wmm_params(struct net_device *dev,
|
|||
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 @@ static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata,
|
|||
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 @@ static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata,
|
|||
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 @@ static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata,
|
|||
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 @@ static void ieee80211_send_assoc(struct net_device *dev,
|
|||
* 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 @@ static void ieee80211_send_assoc(struct net_device *dev,
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ static void ieee80211_auth_challenge(struct net_device *dev,
|
|||
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 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev,
|
|||
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 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev,
|
|||
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 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev,
|
|||
|
||||
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 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev,
|
|||
#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 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid,
|
|||
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 @@ void sta_addba_resp_timer_expired(unsigned long data)
|
|||
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 @@ static void sta_rx_agg_session_timer_expired(unsigned long data)
|
|||
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 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev,
|
|||
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 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev,
|
|||
* 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 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev,
|
|||
!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 @@ static void ieee80211_rx_mgmt_deauth(struct net_device *dev,
|
|||
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 @@ static void ieee80211_rx_mgmt_disassoc(struct net_device *dev,
|
|||
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 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
|
|||
/* 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 @@ static int ieee80211_sta_join_ibss(struct net_device *dev,
|
|||
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 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
|
|||
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 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
|
|||
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 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
|
|||
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 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
|
|||
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 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
|
|||
}
|
||||
|
||||
/* 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 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
|
|||
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 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
|
|||
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 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
|
|||
* 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 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
|
|||
* 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 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
|
|||
!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 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
|
|||
#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 @@ static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev,
|
|||
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 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
|
|||
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 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
|
|||
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 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev,
|
|||
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 @@ static void ieee80211_rx_mgmt_action(struct net_device *dev,
|
|||
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 @@ static void ieee80211_rx_mgmt_action(struct net_device *dev,
|
|||
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 @@ void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
|
|||
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 @@ static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time)
|
|||
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 @@ void ieee80211_sta_work(struct work_struct *work)
|
|||
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 @@ void ieee80211_sta_work(struct work_struct *work)
|
|||
break;
|
||||
#endif
|
||||
default:
|
||||
printk(KERN_DEBUG "ieee80211_sta_work: Unknown state %d\n",
|
||||
ifsta->state);
|
||||
WARN_ON(1);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3516,8 +3439,6 @@ static void ieee80211_sta_reset_auth(struct net_device *dev,
|
|||
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 @@ ieee80211_sta_scan_result(struct net_device *dev,
|
|||
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 @@ struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev,
|
|||
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 @@ int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason)
|
|||
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 @@ int ieee80211_sta_disassociate(struct net_device *dev, u16 reason)
|
|||
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)
|
||||
|
|
|
@ -162,9 +162,7 @@ void rate_control_deinitialize(struct ieee80211_local *local);
|
|||
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -540,11 +540,6 @@ static struct rate_control_ops mac80211_rcpid = {
|
|||
#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 @@ void rc80211_pid_exit(void)
|
|||
{
|
||||
ieee80211_rate_control_unregister(&mac80211_rcpid);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MAC80211_RC_PID_MODULE
|
||||
module_init(rc80211_pid_init);
|
||||
module_exit(rc80211_pid_exit);
|
||||
#endif
|
||||
|
|
|
@ -386,7 +386,7 @@ static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx)
|
|||
|
||||
/* 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 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
|
|||
}
|
||||
|
||||
|
||||
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 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
|
|||
}
|
||||
|
||||
|
||||
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 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
|||
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 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
|
|||
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 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
|
|||
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 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
|
|||
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 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
|
|||
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 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
|||
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 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
|||
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 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
|
|||
* 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 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
|
|||
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 @@ static int
|
|||
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 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
|
|||
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 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
|
|||
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 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
|
|||
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 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
|
|||
|
||||
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 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
|
|||
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 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
|
|||
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 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
|
|||
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 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
|
|||
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 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
|
|||
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 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
|
|||
* 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 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx)
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -554,8 +554,10 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
|
|||
|
||||
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))
|
||||
|
|
|
@ -220,7 +220,7 @@ static int inline is_ieee80211_device(struct net_device *dev,
|
|||
|
||||
/* 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 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
|
|||
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 @@ static void purge_old_ps_buffers(struct ieee80211_local *local)
|
|||
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 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
|
|||
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 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
|
|||
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 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
|
|||
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 @@ ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
|
|||
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 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
|
|||
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 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
|
|||
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 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
|
|||
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 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
|
|||
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 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
|
|||
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 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
|
|||
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 @@ ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx)
|
|||
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 @@ ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
|
|||
}
|
||||
|
||||
|
||||
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 __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
|
|||
*/
|
||||
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 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
|
|||
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 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -253,11 +253,8 @@ int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb,
|
|||
|
||||
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 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx)
|
|||
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 */
|
||||
|
|
|
@ -680,7 +680,6 @@ void ieee80211_requeue(struct ieee80211_local *local, int queue)
|
|||
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--;
|
||||
|
|
|
@ -146,9 +146,6 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
|
|||
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 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
|
|||
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 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
|
|||
(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 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue