Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-next-2.6

This commit is contained in:
David S. Miller 2008-07-05 21:41:53 -07:00
commit f3032be921
45 changed files with 2041 additions and 2132 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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)
{

View file

@ -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;

View file

@ -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";

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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.
*

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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,
};
/**

View file

@ -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.

View file

@ -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)

View file

@ -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 */

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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;
}
}

View file

@ -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))

View file

@ -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;
}

View file

@ -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 */

View file

@ -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--;

View file

@ -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;
}
}