mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-26 14:30:55 +07:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
f8f2109d4f
@ -3272,6 +3272,12 @@ S: Supported
|
||||
F: drivers/net/mv643xx_eth.*
|
||||
F: include/linux/mv643xx.h
|
||||
|
||||
MARVELL MWL8K WIRELESS DRIVER
|
||||
M: Lennert Buytenhek <buytenh@marvell.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/wireless/mwl8k.c
|
||||
|
||||
MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
|
||||
M: Nicolas Pitre <nico@cam.org>
|
||||
S: Maintained
|
||||
|
@ -1328,16 +1328,39 @@ static void adm8211_bss_info_changed(struct ieee80211_hw *dev,
|
||||
}
|
||||
}
|
||||
|
||||
static u64 adm8211_prepare_multicast(struct ieee80211_hw *hw,
|
||||
int mc_count, struct dev_addr_list *mclist)
|
||||
{
|
||||
unsigned int bit_nr, i;
|
||||
u32 mc_filter[2];
|
||||
|
||||
mc_filter[1] = mc_filter[0] = 0;
|
||||
|
||||
for (i = 0; i < mc_count; i++) {
|
||||
if (!mclist)
|
||||
break;
|
||||
bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
|
||||
|
||||
bit_nr &= 0x3F;
|
||||
mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
|
||||
mclist = mclist->next;
|
||||
}
|
||||
|
||||
return mc_filter[0] | ((u64)(mc_filter[1]) << 32);
|
||||
}
|
||||
|
||||
static void adm8211_configure_filter(struct ieee80211_hw *dev,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
int mc_count, struct dev_mc_list *mclist)
|
||||
u64 multicast)
|
||||
{
|
||||
static const u8 bcast[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
struct adm8211_priv *priv = dev->priv;
|
||||
unsigned int bit_nr, new_flags;
|
||||
unsigned int new_flags;
|
||||
u32 mc_filter[2];
|
||||
int i;
|
||||
|
||||
mc_filter[0] = multicast;
|
||||
mc_filter[1] = multicast >> 32;
|
||||
|
||||
new_flags = 0;
|
||||
|
||||
@ -1346,23 +1369,13 @@ static void adm8211_configure_filter(struct ieee80211_hw *dev,
|
||||
priv->nar |= ADM8211_NAR_PR;
|
||||
priv->nar &= ~ADM8211_NAR_MM;
|
||||
mc_filter[1] = mc_filter[0] = ~0;
|
||||
} else if ((*total_flags & FIF_ALLMULTI) || (mc_count > 32)) {
|
||||
} else if (*total_flags & FIF_ALLMULTI || multicast == ~(0ULL)) {
|
||||
new_flags |= FIF_ALLMULTI;
|
||||
priv->nar &= ~ADM8211_NAR_PR;
|
||||
priv->nar |= ADM8211_NAR_MM;
|
||||
mc_filter[1] = mc_filter[0] = ~0;
|
||||
} else {
|
||||
priv->nar &= ~(ADM8211_NAR_MM | ADM8211_NAR_PR);
|
||||
mc_filter[1] = mc_filter[0] = 0;
|
||||
for (i = 0; i < mc_count; i++) {
|
||||
if (!mclist)
|
||||
break;
|
||||
bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
|
||||
|
||||
bit_nr &= 0x3F;
|
||||
mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
|
||||
mclist = mclist->next;
|
||||
}
|
||||
}
|
||||
|
||||
ADM8211_IDLE_RX();
|
||||
@ -1757,6 +1770,7 @@ static const struct ieee80211_ops adm8211_ops = {
|
||||
.remove_interface = adm8211_remove_interface,
|
||||
.config = adm8211_config,
|
||||
.bss_info_changed = adm8211_bss_info_changed,
|
||||
.prepare_multicast = adm8211_prepare_multicast,
|
||||
.configure_filter = adm8211_configure_filter,
|
||||
.get_stats = adm8211_get_stats,
|
||||
.get_tx_stats = adm8211_get_tx_stats,
|
||||
|
@ -1950,9 +1950,8 @@ static int at76_config(struct ieee80211_hw *hw, u32 changed)
|
||||
{
|
||||
struct at76_priv *priv = hw->priv;
|
||||
|
||||
at76_dbg(DBG_MAC80211, "%s(): channel %d radio %d",
|
||||
__func__, hw->conf.channel->hw_value,
|
||||
hw->conf.radio_enabled);
|
||||
at76_dbg(DBG_MAC80211, "%s(): channel %d",
|
||||
__func__, hw->conf.channel->hw_value);
|
||||
at76_dbg_dump(DBG_MAC80211, priv->bssid, ETH_ALEN, "bssid:");
|
||||
|
||||
mutex_lock(&priv->mtx);
|
||||
@ -1997,15 +1996,14 @@ static void at76_bss_info_changed(struct ieee80211_hw *hw,
|
||||
/* must be atomic */
|
||||
static void at76_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags, int mc_count,
|
||||
struct dev_addr_list *mc_list)
|
||||
unsigned int *total_flags, u64 multicast)
|
||||
{
|
||||
struct at76_priv *priv = hw->priv;
|
||||
int flags;
|
||||
|
||||
at76_dbg(DBG_MAC80211, "%s(): changed_flags=0x%08x "
|
||||
"total_flags=0x%08x mc_count=%d",
|
||||
__func__, changed_flags, *total_flags, mc_count);
|
||||
"total_flags=0x%08x",
|
||||
__func__, changed_flags, *total_flags);
|
||||
|
||||
flags = changed_flags & AT76_SUPPORTED_FILTERS;
|
||||
*total_flags = AT76_SUPPORTED_FILTERS;
|
||||
|
@ -157,6 +157,7 @@ struct ar9170_sta_tid {
|
||||
|
||||
struct ar9170 {
|
||||
struct ieee80211_hw *hw;
|
||||
struct ath_common common;
|
||||
struct mutex mutex;
|
||||
enum ar9170_device_state state;
|
||||
unsigned long bad_hw_nagger;
|
||||
@ -184,10 +185,8 @@ struct ar9170 {
|
||||
bool disable_offload;
|
||||
|
||||
/* filter settings */
|
||||
struct work_struct filter_config_work;
|
||||
u64 cur_mc_hash, want_mc_hash;
|
||||
u32 cur_filter, want_filter;
|
||||
unsigned long filter_changed;
|
||||
u64 cur_mc_hash;
|
||||
u32 cur_filter;
|
||||
unsigned int filter_state;
|
||||
bool sniffer_enabled;
|
||||
|
||||
@ -222,7 +221,6 @@ struct ar9170 {
|
||||
|
||||
/* EEPROM */
|
||||
struct ar9170_eeprom eeprom;
|
||||
struct ath_regulatory regulatory;
|
||||
|
||||
/* tx queues - as seen by hw - */
|
||||
struct sk_buff_head tx_pending[__AR9170_NUM_TXQ];
|
||||
@ -261,10 +259,6 @@ struct ar9170_tx_info {
|
||||
#define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED)
|
||||
#define IS_ACCEPTING_CMD(a) (((struct ar9170 *)a)->state >= AR9170_IDLE)
|
||||
|
||||
#define AR9170_FILTER_CHANGED_MODE BIT(0)
|
||||
#define AR9170_FILTER_CHANGED_MULTICAST BIT(1)
|
||||
#define AR9170_FILTER_CHANGED_FRAMEFILTER BIT(2)
|
||||
|
||||
/* exported interface */
|
||||
void *ar9170_alloc(size_t priv_size);
|
||||
int ar9170_register(struct ar9170 *ar, struct device *pdev);
|
||||
@ -278,8 +272,8 @@ int ar9170_nag_limiter(struct ar9170 *ar);
|
||||
int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
int ar9170_init_mac(struct ar9170 *ar);
|
||||
int ar9170_set_qos(struct ar9170 *ar);
|
||||
int ar9170_update_multicast(struct ar9170 *ar);
|
||||
int ar9170_update_frame_filter(struct ar9170 *ar);
|
||||
int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hast);
|
||||
int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter);
|
||||
int ar9170_set_operating_mode(struct ar9170 *ar);
|
||||
int ar9170_set_beacon_timers(struct ar9170 *ar);
|
||||
int ar9170_set_dyn_sifs_ack(struct ar9170 *ar);
|
||||
|
@ -238,39 +238,31 @@ static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac)
|
||||
return ar9170_regwrite_result();
|
||||
}
|
||||
|
||||
int ar9170_update_multicast(struct ar9170 *ar)
|
||||
int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hash)
|
||||
{
|
||||
int err;
|
||||
|
||||
ar9170_regwrite_begin(ar);
|
||||
ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H,
|
||||
ar->want_mc_hash >> 32);
|
||||
ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L,
|
||||
ar->want_mc_hash);
|
||||
|
||||
ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, mc_hash >> 32);
|
||||
ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, mc_hash);
|
||||
ar9170_regwrite_finish();
|
||||
err = ar9170_regwrite_result();
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ar->cur_mc_hash = ar->want_mc_hash;
|
||||
|
||||
ar->cur_mc_hash = mc_hash;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ar9170_update_frame_filter(struct ar9170 *ar)
|
||||
int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER,
|
||||
ar->want_filter);
|
||||
|
||||
err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER, filter);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ar->cur_filter = ar->want_filter;
|
||||
|
||||
ar->cur_filter = filter;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1232,8 +1232,6 @@ static int ar9170_op_start(struct ieee80211_hw *hw)
|
||||
|
||||
mutex_lock(&ar->mutex);
|
||||
|
||||
ar->filter_changed = 0;
|
||||
|
||||
/* reinitialize queues statistics */
|
||||
memset(&ar->tx_stats, 0, sizeof(ar->tx_stats));
|
||||
for (i = 0; i < __AR9170_NUM_TXQ; i++)
|
||||
@ -1296,7 +1294,6 @@ static void ar9170_op_stop(struct ieee80211_hw *hw)
|
||||
#ifdef CONFIG_AR9170_LEDS
|
||||
cancel_delayed_work_sync(&ar->led_work);
|
||||
#endif
|
||||
cancel_work_sync(&ar->filter_config_work);
|
||||
cancel_work_sync(&ar->beacon_work);
|
||||
|
||||
mutex_lock(&ar->mutex);
|
||||
@ -1973,8 +1970,7 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
ar->cur_filter = 0;
|
||||
ar->want_filter = AR9170_MAC_REG_FTF_DEFAULTS;
|
||||
err = ar9170_update_frame_filter(ar);
|
||||
err = ar9170_update_frame_filter(ar, AR9170_MAC_REG_FTF_DEFAULTS);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
@ -1992,8 +1988,7 @@ static void ar9170_op_remove_interface(struct ieee80211_hw *hw,
|
||||
|
||||
mutex_lock(&ar->mutex);
|
||||
ar->vif = NULL;
|
||||
ar->want_filter = 0;
|
||||
ar9170_update_frame_filter(ar);
|
||||
ar9170_update_frame_filter(ar, 0);
|
||||
ar9170_set_beacon_timers(ar);
|
||||
dev_kfree_skb(ar->beacon);
|
||||
ar->beacon = NULL;
|
||||
@ -2065,48 +2060,37 @@ static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ar9170_set_filters(struct work_struct *work)
|
||||
static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
|
||||
struct dev_addr_list *mclist)
|
||||
{
|
||||
struct ar9170 *ar = container_of(work, struct ar9170,
|
||||
filter_config_work);
|
||||
int err;
|
||||
u64 mchash;
|
||||
int i;
|
||||
|
||||
if (unlikely(!IS_STARTED(ar)))
|
||||
return ;
|
||||
/* always get broadcast frames */
|
||||
mchash = 1ULL << (0xff >> 2);
|
||||
|
||||
mutex_lock(&ar->mutex);
|
||||
if (test_and_clear_bit(AR9170_FILTER_CHANGED_MODE,
|
||||
&ar->filter_changed)) {
|
||||
err = ar9170_set_operating_mode(ar);
|
||||
if (err)
|
||||
goto unlock;
|
||||
for (i = 0; i < mc_count; i++) {
|
||||
if (WARN_ON(!mclist))
|
||||
break;
|
||||
mchash |= 1ULL << (mclist->dmi_addr[5] >> 2);
|
||||
mclist = mclist->next;
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(AR9170_FILTER_CHANGED_MULTICAST,
|
||||
&ar->filter_changed)) {
|
||||
err = ar9170_update_multicast(ar);
|
||||
if (err)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(AR9170_FILTER_CHANGED_FRAMEFILTER,
|
||||
&ar->filter_changed)) {
|
||||
err = ar9170_update_frame_filter(ar);
|
||||
if (err)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&ar->mutex);
|
||||
return mchash;
|
||||
}
|
||||
|
||||
static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *new_flags,
|
||||
int mc_count, struct dev_mc_list *mclist)
|
||||
u64 multicast)
|
||||
{
|
||||
struct ar9170 *ar = hw->priv;
|
||||
|
||||
if (unlikely(!IS_ACCEPTING_CMD(ar)))
|
||||
return ;
|
||||
|
||||
mutex_lock(&ar->mutex);
|
||||
|
||||
/* mask supported flags */
|
||||
*new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC |
|
||||
FIF_PROMISC_IN_BSS | FIF_FCSFAIL | FIF_PLCPFAIL;
|
||||
@ -2116,26 +2100,11 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
|
||||
* then checking the error flags, later.
|
||||
*/
|
||||
|
||||
if (changed_flags & FIF_ALLMULTI) {
|
||||
if (*new_flags & FIF_ALLMULTI) {
|
||||
ar->want_mc_hash = ~0ULL;
|
||||
} else {
|
||||
u64 mchash;
|
||||
int i;
|
||||
if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI)
|
||||
multicast = ~0ULL;
|
||||
|
||||
/* always get broadcast frames */
|
||||
mchash = 1ULL << (0xff >> 2);
|
||||
|
||||
for (i = 0; i < mc_count; i++) {
|
||||
if (WARN_ON(!mclist))
|
||||
break;
|
||||
mchash |= 1ULL << (mclist->dmi_addr[5] >> 2);
|
||||
mclist = mclist->next;
|
||||
}
|
||||
ar->want_mc_hash = mchash;
|
||||
}
|
||||
set_bit(AR9170_FILTER_CHANGED_MULTICAST, &ar->filter_changed);
|
||||
}
|
||||
if (multicast != ar->cur_mc_hash)
|
||||
ar9170_update_multicast(ar, multicast);
|
||||
|
||||
if (changed_flags & FIF_CONTROL) {
|
||||
u32 filter = AR9170_MAC_REG_FTF_PSPOLL |
|
||||
@ -2146,24 +2115,22 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
|
||||
AR9170_MAC_REG_FTF_CFE_ACK;
|
||||
|
||||
if (*new_flags & FIF_CONTROL)
|
||||
ar->want_filter = ar->cur_filter | filter;
|
||||
filter |= ar->cur_filter;
|
||||
else
|
||||
ar->want_filter = ar->cur_filter & ~filter;
|
||||
filter &= (~ar->cur_filter);
|
||||
|
||||
set_bit(AR9170_FILTER_CHANGED_FRAMEFILTER,
|
||||
&ar->filter_changed);
|
||||
ar9170_update_frame_filter(ar, filter);
|
||||
}
|
||||
|
||||
if (changed_flags & FIF_PROMISC_IN_BSS) {
|
||||
ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0;
|
||||
set_bit(AR9170_FILTER_CHANGED_MODE,
|
||||
&ar->filter_changed);
|
||||
ar9170_set_operating_mode(ar);
|
||||
}
|
||||
|
||||
if (likely(IS_STARTED(ar)))
|
||||
ieee80211_queue_work(ar->hw, &ar->filter_config_work);
|
||||
mutex_unlock(&ar->mutex);
|
||||
}
|
||||
|
||||
|
||||
static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
@ -2417,9 +2384,6 @@ static void ar9170_sta_notify(struct ieee80211_hw *hw,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (IS_STARTED(ar) && ar->filter_changed)
|
||||
ieee80211_queue_work(ar->hw, &ar->filter_config_work);
|
||||
}
|
||||
|
||||
static int ar9170_get_stats(struct ieee80211_hw *hw,
|
||||
@ -2543,6 +2507,7 @@ static const struct ieee80211_ops ar9170_ops = {
|
||||
.add_interface = ar9170_op_add_interface,
|
||||
.remove_interface = ar9170_op_remove_interface,
|
||||
.config = ar9170_op_config,
|
||||
.prepare_multicast = ar9170_op_prepare_multicast,
|
||||
.configure_filter = ar9170_op_configure_filter,
|
||||
.conf_tx = ar9170_conf_tx,
|
||||
.bss_info_changed = ar9170_op_bss_info_changed,
|
||||
@ -2589,7 +2554,6 @@ void *ar9170_alloc(size_t priv_size)
|
||||
skb_queue_head_init(&ar->tx_pending[i]);
|
||||
}
|
||||
ar9170_rx_reset_rx_mpdu(ar);
|
||||
INIT_WORK(&ar->filter_config_work, ar9170_set_filters);
|
||||
INIT_WORK(&ar->beacon_work, ar9170_new_beacon);
|
||||
INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor);
|
||||
INIT_LIST_HEAD(&ar->tx_ampdu_list);
|
||||
@ -2634,6 +2598,7 @@ static int ar9170_read_eeprom(struct ar9170 *ar)
|
||||
{
|
||||
#define RW 8 /* number of words to read at once */
|
||||
#define RB (sizeof(u32) * RW)
|
||||
struct ath_regulatory *regulatory = &ar->common.regulatory;
|
||||
u8 *eeprom = (void *)&ar->eeprom;
|
||||
u8 *addr = ar->eeprom.mac_address;
|
||||
__le32 offsets[RW];
|
||||
@ -2700,8 +2665,8 @@ static int ar9170_read_eeprom(struct ar9170 *ar)
|
||||
else
|
||||
ar->hw->channel_change_time = 80 * 1000;
|
||||
|
||||
ar->regulatory.current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
|
||||
ar->regulatory.current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]);
|
||||
regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
|
||||
regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]);
|
||||
|
||||
/* second part of wiphy init */
|
||||
SET_IEEE80211_PERM_ADDR(ar->hw, addr);
|
||||
@ -2715,11 +2680,12 @@ static int ar9170_reg_notifier(struct wiphy *wiphy,
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct ar9170 *ar = hw->priv;
|
||||
|
||||
return ath_reg_notifier_apply(wiphy, request, &ar->regulatory);
|
||||
return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory);
|
||||
}
|
||||
|
||||
int ar9170_register(struct ar9170 *ar, struct device *pdev)
|
||||
{
|
||||
struct ath_regulatory *regulatory = &ar->common.regulatory;
|
||||
int err;
|
||||
|
||||
/* try to read EEPROM, init MAC addr */
|
||||
@ -2727,7 +2693,7 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev)
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
err = ath_regd_init(&ar->regulatory, ar->hw->wiphy,
|
||||
err = ath_regd_init(regulatory, ar->hw->wiphy,
|
||||
ar9170_reg_notifier);
|
||||
if (err)
|
||||
goto err_out;
|
||||
@ -2736,8 +2702,8 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev)
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
if (!ath_is_world_regd(&ar->regulatory))
|
||||
regulatory_hint(ar->hw->wiphy, ar->regulatory.alpha2);
|
||||
if (!ath_is_world_regd(regulatory))
|
||||
regulatory_hint(ar->hw->wiphy, regulatory->alpha2);
|
||||
|
||||
err = ar9170_init_leds(ar);
|
||||
if (err)
|
||||
|
@ -19,8 +19,26 @@
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
struct reg_dmn_pair_mapping {
|
||||
u16 regDmnEnum;
|
||||
u16 reg_5ghz_ctl;
|
||||
u16 reg_2ghz_ctl;
|
||||
};
|
||||
|
||||
struct ath_regulatory {
|
||||
char alpha2[2];
|
||||
u16 country_code;
|
||||
u16 max_power_level;
|
||||
u32 tp_scale;
|
||||
u16 current_rd;
|
||||
u16 current_rd_ext;
|
||||
int16_t power_limit;
|
||||
struct reg_dmn_pair_mapping *regpair;
|
||||
};
|
||||
|
||||
struct ath_common {
|
||||
u16 cachelsz;
|
||||
struct ath_regulatory regulatory;
|
||||
};
|
||||
|
||||
struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
|
||||
|
@ -27,8 +27,6 @@
|
||||
#include <linux/types.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "../regd.h"
|
||||
|
||||
/* RX/TX descriptor hw structs
|
||||
* TODO: Driver part should only see sw structs */
|
||||
#include "desc.h"
|
||||
@ -1077,7 +1075,6 @@ struct ath5k_hw {
|
||||
|
||||
int ah_gpio_npins;
|
||||
|
||||
struct ath_regulatory ah_regulatory;
|
||||
struct ath5k_capabilities ah_capabilities;
|
||||
|
||||
struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES];
|
||||
|
@ -229,10 +229,12 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
|
||||
static void ath5k_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf);
|
||||
static int ath5k_config(struct ieee80211_hw *hw, u32 changed);
|
||||
static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw,
|
||||
int mc_count, struct dev_addr_list *mc_list);
|
||||
static void ath5k_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *new_flags,
|
||||
int mc_count, struct dev_mc_list *mclist);
|
||||
u64 multicast);
|
||||
static int ath5k_set_key(struct ieee80211_hw *hw,
|
||||
enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
@ -260,6 +262,7 @@ static const struct ieee80211_ops ath5k_hw_ops = {
|
||||
.add_interface = ath5k_add_interface,
|
||||
.remove_interface = ath5k_remove_interface,
|
||||
.config = ath5k_config,
|
||||
.prepare_multicast = ath5k_prepare_multicast,
|
||||
.configure_filter = ath5k_configure_filter,
|
||||
.set_key = ath5k_set_key,
|
||||
.get_stats = ath5k_get_stats,
|
||||
@ -715,9 +718,9 @@ static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *re
|
||||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
struct ath_regulatory *reg = &sc->ah->ah_regulatory;
|
||||
struct ath_regulatory *regulatory = &sc->common.regulatory;
|
||||
|
||||
return ath_reg_notifier_apply(wiphy, request, reg);
|
||||
return ath_reg_notifier_apply(wiphy, request, regulatory);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -725,6 +728,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
struct ath5k_hw *ah = sc->ah;
|
||||
struct ath_regulatory *regulatory = &sc->common.regulatory;
|
||||
u8 mac[ETH_ALEN] = {};
|
||||
int ret;
|
||||
|
||||
@ -814,9 +818,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
|
||||
memset(sc->bssidmask, 0xff, ETH_ALEN);
|
||||
ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
|
||||
|
||||
ah->ah_regulatory.current_rd =
|
||||
ah->ah_capabilities.cap_eeprom.ee_regdomain;
|
||||
ret = ath_regd_init(&ah->ah_regulatory, hw->wiphy, ath5k_reg_notifier);
|
||||
regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain;
|
||||
ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier);
|
||||
if (ret) {
|
||||
ATH5K_ERR(sc, "can't initialize regulatory system\n");
|
||||
goto err_queues;
|
||||
@ -828,8 +831,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
|
||||
goto err_queues;
|
||||
}
|
||||
|
||||
if (!ath_is_world_regd(&sc->ah->ah_regulatory))
|
||||
regulatory_hint(hw->wiphy, sc->ah->ah_regulatory.alpha2);
|
||||
if (!ath_is_world_regd(regulatory))
|
||||
regulatory_hint(hw->wiphy, regulatory->alpha2);
|
||||
|
||||
ath5k_init_leds(sc);
|
||||
|
||||
@ -2853,6 +2856,37 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw,
|
||||
int mc_count, struct dev_addr_list *mclist)
|
||||
{
|
||||
u32 mfilt[2], val;
|
||||
int i;
|
||||
u8 pos;
|
||||
|
||||
mfilt[0] = 0;
|
||||
mfilt[1] = 1;
|
||||
|
||||
for (i = 0; i < mc_count; i++) {
|
||||
if (!mclist)
|
||||
break;
|
||||
/* calculate XOR of eight 6-bit values */
|
||||
val = get_unaligned_le32(mclist->dmi_addr + 0);
|
||||
pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
|
||||
val = get_unaligned_le32(mclist->dmi_addr + 3);
|
||||
pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
|
||||
pos &= 0x3f;
|
||||
mfilt[pos / 32] |= (1 << (pos % 32));
|
||||
/* XXX: we might be able to just do this instead,
|
||||
* but not sure, needs testing, if we do use this we'd
|
||||
* neet to inform below to not reset the mcast */
|
||||
/* ath5k_hw_set_mcast_filterindex(ah,
|
||||
* mclist->dmi_addr[5]); */
|
||||
mclist = mclist->next;
|
||||
}
|
||||
|
||||
return ((u64)(mfilt[1]) << 32) | mfilt[0];
|
||||
}
|
||||
|
||||
#define SUPPORTED_FIF_FLAGS \
|
||||
FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \
|
||||
FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
|
||||
@ -2878,16 +2912,14 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
|
||||
static void ath5k_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *new_flags,
|
||||
int mc_count, struct dev_mc_list *mclist)
|
||||
u64 multicast)
|
||||
{
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
struct ath5k_hw *ah = sc->ah;
|
||||
u32 mfilt[2], val, rfilt;
|
||||
u8 pos;
|
||||
int i;
|
||||
u32 mfilt[2], rfilt;
|
||||
|
||||
mfilt[0] = 0;
|
||||
mfilt[1] = 0;
|
||||
mfilt[0] = multicast;
|
||||
mfilt[1] = multicast >> 32;
|
||||
|
||||
/* Only deal with supported flags */
|
||||
changed_flags &= SUPPORTED_FIF_FLAGS;
|
||||
@ -2913,24 +2945,6 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
|
||||
if (*new_flags & FIF_ALLMULTI) {
|
||||
mfilt[0] = ~0;
|
||||
mfilt[1] = ~0;
|
||||
} else {
|
||||
for (i = 0; i < mc_count; i++) {
|
||||
if (!mclist)
|
||||
break;
|
||||
/* calculate XOR of eight 6-bit values */
|
||||
val = get_unaligned_le32(mclist->dmi_addr + 0);
|
||||
pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
|
||||
val = get_unaligned_le32(mclist->dmi_addr + 3);
|
||||
pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
|
||||
pos &= 0x3f;
|
||||
mfilt[pos / 32] |= (1 << (pos % 32));
|
||||
/* XXX: we might be able to just do this instead,
|
||||
* but not sure, needs testing, if we do use this we'd
|
||||
* neet to inform below to not reset the mcast */
|
||||
/* ath5k_hw_set_mcast_filterindex(ah,
|
||||
* mclist->dmi_addr[5]); */
|
||||
mclist = mclist->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the best we can do */
|
||||
|
@ -50,6 +50,8 @@
|
||||
|
||||
#include "ath5k.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include "../regd.h"
|
||||
#include "../ath.h"
|
||||
|
||||
#define ATH_RXBUF 40 /* number of RX buffers */
|
||||
@ -200,4 +202,15 @@ struct ath5k_softc {
|
||||
#define ath5k_hw_hasveol(_ah) \
|
||||
(ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0)
|
||||
|
||||
static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah)
|
||||
{
|
||||
return &ah->ah_sc->common;
|
||||
}
|
||||
|
||||
static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah)
|
||||
{
|
||||
return &(ath5k_hw_common(ah)->regulatory);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -2198,6 +2198,7 @@ static void
|
||||
ath5k_get_max_ctl_power(struct ath5k_hw *ah,
|
||||
struct ieee80211_channel *channel)
|
||||
{
|
||||
struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
|
||||
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
||||
struct ath5k_edge_power *rep = ee->ee_ctl_pwr;
|
||||
u8 *ctl_val = ee->ee_ctl;
|
||||
@ -2208,7 +2209,7 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah,
|
||||
u8 ctl_idx = 0xFF;
|
||||
u32 target = channel->center_freq;
|
||||
|
||||
ctl_mode = ath_regd_get_band_ctl(&ah->ah_regulatory, channel->band);
|
||||
ctl_mode = ath_regd_get_band_ctl(regulatory, channel->band);
|
||||
|
||||
switch (channel->hw_value & CHANNEL_MODES) {
|
||||
case CHANNEL_A:
|
||||
|
@ -538,7 +538,6 @@ void ath9k_ani_reset(struct ath_hw *ah)
|
||||
}
|
||||
|
||||
void ath9k_hw_ani_monitor(struct ath_hw *ah,
|
||||
const struct ath9k_node_stats *stats,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct ar5416AniState *aniState;
|
||||
@ -550,7 +549,6 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
|
||||
return;
|
||||
|
||||
aniState = ah->curani;
|
||||
ah->stats.ast_nodestats = *stats;
|
||||
|
||||
listenTime = ath9k_hw_ani_get_listen_time(ah);
|
||||
if (listenTime < 0) {
|
||||
@ -693,8 +691,7 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah,
|
||||
* any of the MIB counters overflow/trigger so don't assume we're
|
||||
* here because a PHY error counter triggered.
|
||||
*/
|
||||
void ath9k_hw_procmibevent(struct ath_hw *ah,
|
||||
const struct ath9k_node_stats *stats)
|
||||
void ath9k_hw_procmibevent(struct ath_hw *ah)
|
||||
{
|
||||
u32 phyCnt1, phyCnt2;
|
||||
|
||||
@ -706,7 +703,6 @@ void ath9k_hw_procmibevent(struct ath_hw *ah,
|
||||
|
||||
/* Clear the mib counters and save them in the stats */
|
||||
ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
|
||||
ah->stats.ast_nodestats = *stats;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
@ -18,15 +18,10 @@
|
||||
#define ANI_H
|
||||
|
||||
#define HAL_PROCESS_ANI 0x00000001
|
||||
#define ATH9K_RSSI_EP_MULTIPLIER (1<<7)
|
||||
|
||||
#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI))
|
||||
|
||||
#define HAL_EP_RND(x, mul) \
|
||||
((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
|
||||
#define BEACON_RSSI(ahp) \
|
||||
HAL_EP_RND(ahp->stats.ast_nodestats.ns_avgbrssi, \
|
||||
ATH9K_RSSI_EP_MULTIPLIER)
|
||||
#define BEACON_RSSI(ahp) (ahp->stats.avgbrssi)
|
||||
|
||||
#define ATH9K_ANI_OFDM_TRIG_HIGH 500
|
||||
#define ATH9K_ANI_OFDM_TRIG_LOW 200
|
||||
@ -65,13 +60,6 @@ struct ath9k_mib_stats {
|
||||
u32 beacons;
|
||||
};
|
||||
|
||||
struct ath9k_node_stats {
|
||||
u32 ns_avgbrssi;
|
||||
u32 ns_avgrssi;
|
||||
u32 ns_avgtxrssi;
|
||||
u32 ns_avgtxrate;
|
||||
};
|
||||
|
||||
struct ar5416AniState {
|
||||
struct ath9k_channel *c;
|
||||
u8 noiseImmunityLevel;
|
||||
@ -115,21 +103,19 @@ struct ar5416Stats {
|
||||
u32 ast_ani_reset;
|
||||
u32 ast_ani_lzero;
|
||||
u32 ast_ani_lneg;
|
||||
u32 avgbrssi;
|
||||
struct ath9k_mib_stats ast_mibstats;
|
||||
struct ath9k_node_stats ast_nodestats;
|
||||
};
|
||||
#define ah_mibStats stats.ast_mibstats
|
||||
|
||||
void ath9k_ani_reset(struct ath_hw *ah);
|
||||
void ath9k_hw_ani_monitor(struct ath_hw *ah,
|
||||
const struct ath9k_node_stats *stats,
|
||||
struct ath9k_channel *chan);
|
||||
void ath9k_enable_mib_counters(struct ath_hw *ah);
|
||||
void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
|
||||
u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt,
|
||||
u32 *rxf_pcnt, u32 *txf_pcnt);
|
||||
void ath9k_hw_procmibevent(struct ath_hw *ah,
|
||||
const struct ath9k_node_stats *stats);
|
||||
void ath9k_hw_procmibevent(struct ath_hw *ah);
|
||||
void ath9k_hw_ani_setup(struct ath_hw *ah);
|
||||
void ath9k_hw_ani_init(struct ath_hw *ah);
|
||||
void ath9k_hw_ani_disable(struct ath_hw *ah);
|
||||
|
@ -454,7 +454,8 @@ struct ath_ani {
|
||||
/* LED Control */
|
||||
/********************/
|
||||
|
||||
#define ATH_LED_PIN 1
|
||||
#define ATH_LED_PIN_DEF 1
|
||||
#define ATH_LED_PIN_9287 8
|
||||
#define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */
|
||||
#define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */
|
||||
|
||||
@ -602,7 +603,6 @@ struct ath_softc {
|
||||
int beacon_interval;
|
||||
|
||||
struct ath_ani ani;
|
||||
struct ath9k_node_stats nodestats;
|
||||
#ifdef CONFIG_ATH9K_DEBUG
|
||||
struct ath9k_debug debug;
|
||||
#endif
|
||||
@ -630,6 +630,16 @@ int ath_get_hal_qnum(u16 queue, struct ath_softc *sc);
|
||||
int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
|
||||
int ath_cabq_update(struct ath_softc *);
|
||||
|
||||
static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
|
||||
{
|
||||
return &ah->ah_sc->common;
|
||||
}
|
||||
|
||||
static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah)
|
||||
{
|
||||
return &(ath9k_hw_common(ah)->regulatory);
|
||||
}
|
||||
|
||||
static inline void ath_read_cachesize(struct ath_softc *sc, int *csz)
|
||||
{
|
||||
sc->bus_ops->read_cachesize(sc, csz);
|
||||
|
@ -729,26 +729,42 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
static void ath9k_olc_temp_compensation(struct ath_hw *ah)
|
||||
{
|
||||
u32 rddata, i;
|
||||
int delta, currPDADC, regval;
|
||||
int delta, currPDADC, regval, slope;
|
||||
|
||||
rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
|
||||
|
||||
currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
|
||||
|
||||
if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
|
||||
delta = (currPDADC - ah->initPDADC + 4) / 8;
|
||||
else
|
||||
delta = (currPDADC - ah->initPDADC + 5) / 10;
|
||||
|
||||
if (delta != ah->PDADCdelta) {
|
||||
ah->PDADCdelta = delta;
|
||||
for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
|
||||
regval = ah->originalGain[i] - delta;
|
||||
if (regval < 0)
|
||||
regval = 0;
|
||||
if (OLC_FOR_AR9287_10_LATER) {
|
||||
if (ah->initPDADC == 0 || currPDADC == 0) {
|
||||
return;
|
||||
} else {
|
||||
slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
|
||||
if (slope == 0)
|
||||
delta = 0;
|
||||
else
|
||||
delta = ((currPDADC - ah->initPDADC)*4) / slope;
|
||||
REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
|
||||
AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
|
||||
REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
|
||||
AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
|
||||
}
|
||||
} else {
|
||||
if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
|
||||
delta = (currPDADC - ah->initPDADC + 4) / 8;
|
||||
else
|
||||
delta = (currPDADC - ah->initPDADC + 5) / 10;
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4,
|
||||
AR_PHY_TX_GAIN, regval);
|
||||
if (delta != ah->PDADCdelta) {
|
||||
ah->PDADCdelta = delta;
|
||||
for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
|
||||
regval = ah->originalGain[i] - delta;
|
||||
if (regval < 0)
|
||||
regval = 0;
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4,
|
||||
AR_PHY_TX_GAIN, regval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -508,6 +508,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
|
||||
|| (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
|
||||
((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
|
||||
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
int i;
|
||||
int16_t twiceLargestAntenna;
|
||||
u16 twiceMinEdgePower;
|
||||
@ -541,9 +542,9 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
|
||||
twiceLargestAntenna, 0);
|
||||
|
||||
maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
|
||||
if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
|
||||
if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
|
||||
maxRegAllowedPower -=
|
||||
(tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
|
||||
(tpScaleReductionTable[(regulatory->tp_scale)] * 2);
|
||||
}
|
||||
|
||||
scaledPower = min(powerLimit, maxRegAllowedPower);
|
||||
@ -707,6 +708,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
|
||||
u8 twiceMaxRegulatoryPower,
|
||||
u8 powerLimit)
|
||||
{
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
|
||||
struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
|
||||
int16_t ratesArray[Ar5416RateSize];
|
||||
@ -744,7 +746,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
|
||||
else if (IS_CHAN_HT20(chan))
|
||||
i = rateHt20_0;
|
||||
|
||||
ah->regulatory.max_power_level = ratesArray[i];
|
||||
regulatory->max_power_level = ratesArray[i];
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
for (i = 0; i < Ar5416RateSize; i++)
|
||||
|
@ -374,7 +374,6 @@ static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah,
|
||||
u8 *pCalChans, u16 availPiers,
|
||||
int8_t *pPwr)
|
||||
{
|
||||
u8 pcdac, i = 0;
|
||||
u16 idxL = 0, idxR = 0, numPiers;
|
||||
bool match;
|
||||
struct chan_centers centers;
|
||||
@ -392,17 +391,12 @@ static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah,
|
||||
&idxL, &idxR);
|
||||
|
||||
if (match) {
|
||||
pcdac = pRawDatasetOpLoop[idxL].pcdac[0][0];
|
||||
*pPwr = pRawDatasetOpLoop[idxL].pwrPdg[0][0];
|
||||
*pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0];
|
||||
} else {
|
||||
pcdac = pRawDatasetOpLoop[idxR].pcdac[0][0];
|
||||
*pPwr = (pRawDatasetOpLoop[idxL].pwrPdg[0][0] +
|
||||
pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
|
||||
*pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] +
|
||||
(int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
|
||||
}
|
||||
|
||||
while ((pcdac > ah->originalGain[i]) &&
|
||||
(i < (AR9280_TX_GAIN_TABLE_SIZE - 1)))
|
||||
i++;
|
||||
}
|
||||
|
||||
static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah,
|
||||
@ -605,7 +599,7 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah,
|
||||
{
|
||||
#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6
|
||||
#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10
|
||||
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
|
||||
static const u16 tpScaleReductionTable[5] =
|
||||
{ 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
|
||||
@ -638,9 +632,9 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah,
|
||||
twiceLargestAntenna, 0);
|
||||
|
||||
maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
|
||||
if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX)
|
||||
if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX)
|
||||
maxRegAllowedPower -=
|
||||
(tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
|
||||
(tpScaleReductionTable[(regulatory->tp_scale)] * 2);
|
||||
|
||||
scaledPower = min(powerLimit, maxRegAllowedPower);
|
||||
|
||||
@ -837,7 +831,7 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah,
|
||||
{
|
||||
#define INCREASE_MAXPOW_BY_TWO_CHAIN 6
|
||||
#define INCREASE_MAXPOW_BY_THREE_CHAIN 10
|
||||
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
|
||||
struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
|
||||
int16_t ratesArray[Ar5416RateSize];
|
||||
@ -955,20 +949,20 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah,
|
||||
i = rate6mb;
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
ah->regulatory.max_power_level =
|
||||
regulatory->max_power_level =
|
||||
ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
|
||||
else
|
||||
ah->regulatory.max_power_level = ratesArray[i];
|
||||
regulatory->max_power_level = ratesArray[i];
|
||||
|
||||
switch (ar5416_get_ntxchains(ah->txchainmask)) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
ah->regulatory.max_power_level +=
|
||||
regulatory->max_power_level +=
|
||||
INCREASE_MAXPOW_BY_TWO_CHAIN;
|
||||
break;
|
||||
case 3:
|
||||
ah->regulatory.max_power_level +=
|
||||
regulatory->max_power_level +=
|
||||
INCREASE_MAXPOW_BY_THREE_CHAIN;
|
||||
break;
|
||||
default:
|
||||
|
@ -904,6 +904,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
|
||||
#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
|
||||
#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
|
||||
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
|
||||
u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
|
||||
static const u16 tpScaleReductionTable[5] =
|
||||
@ -953,9 +954,9 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
|
||||
|
||||
maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
|
||||
|
||||
if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
|
||||
if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
|
||||
maxRegAllowedPower -=
|
||||
(tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
|
||||
(tpScaleReductionTable[(regulatory->tp_scale)] * 2);
|
||||
}
|
||||
|
||||
scaledPower = min(powerLimit, maxRegAllowedPower);
|
||||
@ -1163,6 +1164,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
|
||||
u8 powerLimit)
|
||||
{
|
||||
#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
|
||||
struct modal_eep_header *pModal =
|
||||
&(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
|
||||
@ -1292,19 +1294,19 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
|
||||
i = rateHt20_0;
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
ah->regulatory.max_power_level =
|
||||
regulatory->max_power_level =
|
||||
ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
|
||||
else
|
||||
ah->regulatory.max_power_level = ratesArray[i];
|
||||
regulatory->max_power_level = ratesArray[i];
|
||||
|
||||
switch(ar5416_get_ntxchains(ah->txchainmask)) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
|
||||
regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
|
||||
break;
|
||||
case 3:
|
||||
ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
|
||||
regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
|
||||
break;
|
||||
default:
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
|
@ -439,8 +439,13 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
|
||||
|
||||
static void ath9k_hw_init_defaults(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
|
||||
regulatory->country_code = CTRY_DEFAULT;
|
||||
regulatory->power_limit = MAX_RATE_POWER;
|
||||
regulatory->tp_scale = ATH9K_TP_SCALE_MAX;
|
||||
|
||||
ah->hw_version.magic = AR5416_MAGIC;
|
||||
ah->regulatory.country_code = CTRY_DEFAULT;
|
||||
ah->hw_version.subvendorid = 0;
|
||||
|
||||
ah->ah_flags = 0;
|
||||
@ -449,8 +454,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
|
||||
if (!AR_SREV_9100(ah))
|
||||
ah->ah_flags = AH_USE_EEPROM;
|
||||
|
||||
ah->regulatory.power_limit = MAX_RATE_POWER;
|
||||
ah->regulatory.tp_scale = ATH9K_TP_SCALE_MAX;
|
||||
ah->atim_window = 0;
|
||||
ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE;
|
||||
ah->beacon_interval = 100;
|
||||
@ -1332,11 +1335,21 @@ static void ath9k_olc_init(struct ath_hw *ah)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++)
|
||||
ah->originalGain[i] =
|
||||
MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4),
|
||||
AR_PHY_TX_GAIN);
|
||||
ah->PDADCdelta = 0;
|
||||
if (OLC_FOR_AR9287_10_LATER) {
|
||||
REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9,
|
||||
AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL);
|
||||
ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TXPC0,
|
||||
AR9287_AN_TXPC0_TXPCMODE,
|
||||
AR9287_AN_TXPC0_TXPCMODE_S,
|
||||
AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE);
|
||||
udelay(100);
|
||||
} else {
|
||||
for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++)
|
||||
ah->originalGain[i] =
|
||||
MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4),
|
||||
AR_PHY_TX_GAIN);
|
||||
ah->PDADCdelta = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg,
|
||||
@ -1358,6 +1371,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
enum ath9k_ht_macmode macmode)
|
||||
{
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
int i, regWrites = 0;
|
||||
struct ieee80211_channel *channel = chan->chan;
|
||||
u32 modesIndex, freqIndex;
|
||||
@ -1464,11 +1478,11 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
|
||||
ath9k_olc_init(ah);
|
||||
|
||||
ah->eep_ops->set_txpower(ah, chan,
|
||||
ath9k_regd_get_ctl(&ah->regulatory, chan),
|
||||
ath9k_regd_get_ctl(regulatory, chan),
|
||||
channel->max_antenna_gain * 2,
|
||||
channel->max_power * 2,
|
||||
min((u32) MAX_RATE_POWER,
|
||||
(u32) ah->regulatory.power_limit));
|
||||
(u32) regulatory->power_limit));
|
||||
|
||||
if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
@ -1786,6 +1800,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
enum ath9k_ht_macmode macmode)
|
||||
{
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
struct ieee80211_channel *channel = chan->chan;
|
||||
u32 synthDelay, qnum;
|
||||
|
||||
@ -1818,11 +1833,11 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
|
||||
}
|
||||
|
||||
ah->eep_ops->set_txpower(ah, chan,
|
||||
ath9k_regd_get_ctl(&ah->regulatory, chan),
|
||||
ath9k_regd_get_ctl(regulatory, chan),
|
||||
channel->max_antenna_gain * 2,
|
||||
channel->max_power * 2,
|
||||
min((u32) MAX_RATE_POWER,
|
||||
(u32) ah->regulatory.power_limit));
|
||||
(u32) regulatory->power_limit));
|
||||
|
||||
synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
|
||||
if (IS_CHAN_B(chan))
|
||||
@ -2382,7 +2397,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
|
||||
|
||||
if (AR_SREV_9287_10_OR_LATER(ah)) {
|
||||
if (AR_SREV_9287_12_OR_LATER(ah)) {
|
||||
/* Enable ASYNC FIFO */
|
||||
REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
|
||||
AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
|
||||
@ -2468,7 +2483,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
|
||||
ath9k_hw_init_user_settings(ah);
|
||||
|
||||
if (AR_SREV_9287_10_OR_LATER(ah)) {
|
||||
if (AR_SREV_9287_12_OR_LATER(ah)) {
|
||||
REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
|
||||
AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
|
||||
REG_WRITE(ah, AR_D_GBL_IFS_SLOT,
|
||||
@ -2484,7 +2499,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
|
||||
AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
|
||||
}
|
||||
if (AR_SREV_9287_10_OR_LATER(ah)) {
|
||||
if (AR_SREV_9287_12_OR_LATER(ah)) {
|
||||
REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
|
||||
AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
|
||||
}
|
||||
@ -3063,7 +3078,7 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore)
|
||||
if (ah->config.pcie_waen) {
|
||||
REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
|
||||
} else {
|
||||
if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
|
||||
if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah))
|
||||
REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT);
|
||||
/*
|
||||
* On AR9280 chips bit 22 of 0x4004 needs to be set to
|
||||
@ -3470,27 +3485,29 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
|
||||
void ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
||||
{
|
||||
struct ath9k_hw_capabilities *pCap = &ah->caps;
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
|
||||
u16 capField = 0, eeval;
|
||||
|
||||
eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
|
||||
ah->regulatory.current_rd = eeval;
|
||||
regulatory->current_rd = eeval;
|
||||
|
||||
eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1);
|
||||
if (AR_SREV_9285_10_OR_LATER(ah))
|
||||
eeval |= AR9285_RDEXT_DEFAULT;
|
||||
ah->regulatory.current_rd_ext = eeval;
|
||||
regulatory->current_rd_ext = eeval;
|
||||
|
||||
capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP);
|
||||
|
||||
if (ah->opmode != NL80211_IFTYPE_AP &&
|
||||
ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) {
|
||||
if (ah->regulatory.current_rd == 0x64 ||
|
||||
ah->regulatory.current_rd == 0x65)
|
||||
ah->regulatory.current_rd += 5;
|
||||
else if (ah->regulatory.current_rd == 0x41)
|
||||
ah->regulatory.current_rd = 0x43;
|
||||
if (regulatory->current_rd == 0x64 ||
|
||||
regulatory->current_rd == 0x65)
|
||||
regulatory->current_rd += 5;
|
||||
else if (regulatory->current_rd == 0x41)
|
||||
regulatory->current_rd = 0x43;
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
|
||||
"regdomain mapped to 0x%x\n", ah->regulatory.current_rd);
|
||||
"regdomain mapped to 0x%x\n", regulatory->current_rd);
|
||||
}
|
||||
|
||||
eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
|
||||
@ -3625,7 +3642,7 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
||||
else
|
||||
pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS;
|
||||
|
||||
if (ah->regulatory.current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) {
|
||||
if (regulatory->current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) {
|
||||
pCap->reg_cap =
|
||||
AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
|
||||
AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN |
|
||||
@ -3654,6 +3671,7 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
||||
bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
|
||||
u32 capability, u32 *result)
|
||||
{
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
switch (type) {
|
||||
case ATH9K_CAP_CIPHER:
|
||||
switch (capability) {
|
||||
@ -3702,13 +3720,13 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
*result = ah->regulatory.power_limit;
|
||||
*result = regulatory->power_limit;
|
||||
return 0;
|
||||
case 2:
|
||||
*result = ah->regulatory.max_power_level;
|
||||
*result = regulatory->max_power_level;
|
||||
return 0;
|
||||
case 3:
|
||||
*result = ah->regulatory.tp_scale;
|
||||
*result = regulatory->tp_scale;
|
||||
return 0;
|
||||
}
|
||||
return false;
|
||||
@ -3946,17 +3964,18 @@ bool ath9k_hw_disable(struct ath_hw *ah)
|
||||
|
||||
void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
|
||||
{
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
struct ath9k_channel *chan = ah->curchan;
|
||||
struct ieee80211_channel *channel = chan->chan;
|
||||
|
||||
ah->regulatory.power_limit = min(limit, (u32) MAX_RATE_POWER);
|
||||
regulatory->power_limit = min(limit, (u32) MAX_RATE_POWER);
|
||||
|
||||
ah->eep_ops->set_txpower(ah, chan,
|
||||
ath9k_regd_get_ctl(&ah->regulatory, chan),
|
||||
ath9k_regd_get_ctl(regulatory, chan),
|
||||
channel->max_antenna_gain * 2,
|
||||
channel->max_power * 2,
|
||||
min((u32) MAX_RATE_POWER,
|
||||
(u32) ah->regulatory.power_limit));
|
||||
(u32) regulatory->power_limit));
|
||||
}
|
||||
|
||||
void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac)
|
||||
|
@ -396,7 +396,6 @@ struct ath_hw {
|
||||
struct ath9k_hw_version hw_version;
|
||||
struct ath9k_ops_config config;
|
||||
struct ath9k_hw_capabilities caps;
|
||||
struct ath_regulatory regulatory;
|
||||
struct ath9k_channel channels[38];
|
||||
struct ath9k_channel *curchan;
|
||||
|
||||
@ -522,6 +521,7 @@ struct ath_hw {
|
||||
u32 originalGain[22];
|
||||
int initPDADC;
|
||||
int PDADCdelta;
|
||||
u8 led_pin;
|
||||
|
||||
struct ar5416IniArray iniModes;
|
||||
struct ar5416IniArray iniCommon;
|
||||
|
@ -384,7 +384,7 @@ static void ath_ani_calibrate(unsigned long data)
|
||||
if (longcal || shortcal || aniflag) {
|
||||
/* Call ANI routine if necessary */
|
||||
if (aniflag)
|
||||
ath9k_hw_ani_monitor(ah, &sc->nodestats, ah->curchan);
|
||||
ath9k_hw_ani_monitor(ah, ah->curchan);
|
||||
|
||||
/* Perform calibration if necessary */
|
||||
if (longcal || shortcal) {
|
||||
@ -589,7 +589,7 @@ irqreturn_t ath_isr(int irq, void *dev)
|
||||
* it will clear whatever condition caused
|
||||
* the interrupt.
|
||||
*/
|
||||
ath9k_hw_procmibevent(ah, &sc->nodestats);
|
||||
ath9k_hw_procmibevent(ah);
|
||||
ath9k_hw_set_interrupts(ah, sc->imask);
|
||||
}
|
||||
|
||||
@ -940,10 +940,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
|
||||
ath_beacon_config(sc, vif);
|
||||
|
||||
/* Reset rssi stats */
|
||||
sc->nodestats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
|
||||
sc->nodestats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER;
|
||||
sc->nodestats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
|
||||
sc->nodestats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER;
|
||||
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
|
||||
|
||||
ath_start_ani(sc);
|
||||
} else {
|
||||
@ -968,9 +965,9 @@ static void ath_led_blink_work(struct work_struct *work)
|
||||
|
||||
if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
|
||||
(sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
|
||||
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0);
|
||||
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
|
||||
else
|
||||
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN,
|
||||
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin,
|
||||
(sc->sc_flags & SC_OP_LED_ON) ? 1 : 0);
|
||||
|
||||
ieee80211_queue_delayed_work(sc->hw,
|
||||
@ -1002,7 +999,7 @@ static void ath_led_brightness(struct led_classdev *led_cdev,
|
||||
case LED_OFF:
|
||||
if (led->led_type == ATH_LED_ASSOC ||
|
||||
led->led_type == ATH_LED_RADIO) {
|
||||
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN,
|
||||
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin,
|
||||
(led->led_type == ATH_LED_RADIO));
|
||||
sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
|
||||
if (led->led_type == ATH_LED_RADIO)
|
||||
@ -1017,7 +1014,7 @@ static void ath_led_brightness(struct led_classdev *led_cdev,
|
||||
ieee80211_queue_delayed_work(sc->hw,
|
||||
&sc->ath_led_blink_work, 0);
|
||||
} else if (led->led_type == ATH_LED_RADIO) {
|
||||
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0);
|
||||
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
|
||||
sc->sc_flags |= SC_OP_LED_ON;
|
||||
} else {
|
||||
sc->led_on_cnt++;
|
||||
@ -1062,7 +1059,7 @@ static void ath_deinit_leds(struct ath_softc *sc)
|
||||
ath_unregister_led(&sc->tx_led);
|
||||
ath_unregister_led(&sc->rx_led);
|
||||
ath_unregister_led(&sc->radio_led);
|
||||
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
|
||||
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
|
||||
}
|
||||
|
||||
static void ath_init_leds(struct ath_softc *sc)
|
||||
@ -1070,11 +1067,16 @@ static void ath_init_leds(struct ath_softc *sc)
|
||||
char *trigger;
|
||||
int ret;
|
||||
|
||||
if (AR_SREV_9287(sc->sc_ah))
|
||||
sc->sc_ah->led_pin = ATH_LED_PIN_9287;
|
||||
else
|
||||
sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
|
||||
|
||||
/* Configure gpio 1 for output */
|
||||
ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
|
||||
ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin,
|
||||
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||
/* LED off, active low */
|
||||
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
|
||||
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
|
||||
|
||||
INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work);
|
||||
|
||||
@ -1153,9 +1155,9 @@ void ath_radio_enable(struct ath_softc *sc)
|
||||
ath9k_hw_set_interrupts(ah, sc->imask);
|
||||
|
||||
/* Enable LED */
|
||||
ath9k_hw_cfg_output(ah, ATH_LED_PIN,
|
||||
ath9k_hw_cfg_output(ah, ah->led_pin,
|
||||
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||
ath9k_hw_set_gpio(ah, ATH_LED_PIN, 0);
|
||||
ath9k_hw_set_gpio(ah, ah->led_pin, 0);
|
||||
|
||||
ieee80211_wake_queues(sc->hw);
|
||||
ath9k_ps_restore(sc);
|
||||
@ -1171,8 +1173,8 @@ void ath_radio_disable(struct ath_softc *sc)
|
||||
ieee80211_stop_queues(sc->hw);
|
||||
|
||||
/* Disable LED */
|
||||
ath9k_hw_set_gpio(ah, ATH_LED_PIN, 1);
|
||||
ath9k_hw_cfg_gpio_input(ah, ATH_LED_PIN);
|
||||
ath9k_hw_set_gpio(ah, ah->led_pin, 1);
|
||||
ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
|
||||
|
||||
/* Disable interrupts */
|
||||
ath9k_hw_set_interrupts(ah, 0);
|
||||
@ -1288,7 +1290,7 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
struct ath_regulatory *reg = &sc->sc_ah->regulatory;
|
||||
struct ath_regulatory *reg = &sc->common.regulatory;
|
||||
|
||||
return ath_reg_notifier_apply(wiphy, request, reg);
|
||||
}
|
||||
@ -1581,12 +1583,12 @@ int ath_init_device(u16 devid, struct ath_softc *sc)
|
||||
|
||||
ath_set_hw_capab(sc, hw);
|
||||
|
||||
error = ath_regd_init(&sc->sc_ah->regulatory, sc->hw->wiphy,
|
||||
error = ath_regd_init(&sc->common.regulatory, sc->hw->wiphy,
|
||||
ath9k_reg_notifier);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
reg = &sc->sc_ah->regulatory;
|
||||
reg = &sc->common.regulatory;
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
|
||||
setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
|
||||
@ -2100,6 +2102,8 @@ static void ath9k_stop(struct ieee80211_hw *hw)
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
|
||||
mutex_lock(&sc->mutex);
|
||||
|
||||
aphy->state = ATH_WIPHY_INACTIVE;
|
||||
|
||||
cancel_delayed_work_sync(&sc->ath_led_blink_work);
|
||||
@ -2112,13 +2116,10 @@ static void ath9k_stop(struct ieee80211_hw *hw)
|
||||
|
||||
if (sc->sc_flags & SC_OP_INVALID) {
|
||||
DPRINTF(sc, ATH_DBG_ANY, "Device not present\n");
|
||||
mutex_unlock(&sc->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&sc->mutex);
|
||||
|
||||
cancel_delayed_work_sync(&sc->tx_complete_work);
|
||||
|
||||
if (ath9k_wiphy_started(sc)) {
|
||||
mutex_unlock(&sc->mutex);
|
||||
return; /* another wiphy still in use */
|
||||
@ -2389,8 +2390,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
|
||||
static void ath9k_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
int mc_count,
|
||||
struct dev_mc_list *mclist)
|
||||
u64 multicast)
|
||||
{
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
|
@ -236,7 +236,7 @@ static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
|
||||
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
|
||||
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
|
||||
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
@ -269,9 +269,9 @@ static int ath_pci_resume(struct pci_dev *pdev)
|
||||
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
|
||||
|
||||
/* Enable LED */
|
||||
ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
|
||||
ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin,
|
||||
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
|
||||
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -490,11 +490,18 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
|
||||
#define AR_PHY_TX_PWRCTRL9 0xa27C
|
||||
#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00
|
||||
#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10
|
||||
#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000
|
||||
#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31
|
||||
|
||||
#define AR_PHY_TX_GAIN_TBL1 0xa300
|
||||
#define AR_PHY_TX_GAIN 0x0007F000
|
||||
#define AR_PHY_TX_GAIN_S 12
|
||||
|
||||
#define AR_PHY_CH0_TX_PWRCTRL11 0xa398
|
||||
#define AR_PHY_CH1_TX_PWRCTRL11 0xb398
|
||||
#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00
|
||||
#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10
|
||||
|
||||
#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0
|
||||
#define AR_PHY_MASK2_M_31_45 0xa3a4
|
||||
#define AR_PHY_MASK2_M_16_30 0xa3a8
|
||||
|
@ -222,7 +222,7 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds,
|
||||
|
||||
/* Update Beacon RSSI, this is used by ANI. */
|
||||
if (ieee80211_is_beacon(fc))
|
||||
sc->nodestats.ns_avgbrssi = ds->ds_rxstat.rs_rssi;
|
||||
sc->sc_ah->stats.avgbrssi = ds->ds_rxstat.rs_rssi;
|
||||
|
||||
rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp);
|
||||
rx_status->band = hw->conf.channel->band;
|
||||
|
@ -744,6 +744,7 @@
|
||||
#define AR_SREV_VERSION_9287 0x180
|
||||
#define AR_SREV_REVISION_9287_10 0
|
||||
#define AR_SREV_REVISION_9287_11 1
|
||||
#define AR_SREV_REVISION_9287_12 2
|
||||
#define AR_SREV_VERSION_9271 0x140
|
||||
#define AR_SREV_REVISION_9271_10 0
|
||||
#define AR_SREV_REVISION_9271_11 1
|
||||
@ -817,7 +818,13 @@
|
||||
(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
|
||||
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_11)))
|
||||
|
||||
#define AR_SREV_9287_12(_ah) \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
|
||||
((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_12))
|
||||
#define AR_SREV_9287_12_OR_LATER(_ah) \
|
||||
(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
|
||||
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_12)))
|
||||
#define AR_SREV_9271(_ah) \
|
||||
(((_ah))->hw_version.macVersion == AR_SREV_VERSION_9271)
|
||||
#define AR_SREV_9271_10(_ah) \
|
||||
|
@ -18,9 +18,10 @@
|
||||
#define REGD_H
|
||||
|
||||
#include <linux/nl80211.h>
|
||||
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#include "ath.h"
|
||||
|
||||
#define NO_CTL 0xff
|
||||
#define SD_NO_CTL 0xE0
|
||||
#define NO_CTL 0xff
|
||||
@ -47,29 +48,12 @@
|
||||
#define CHANNEL_HALF_BW 10
|
||||
#define CHANNEL_QUARTER_BW 5
|
||||
|
||||
struct reg_dmn_pair_mapping {
|
||||
u16 regDmnEnum;
|
||||
u16 reg_5ghz_ctl;
|
||||
u16 reg_2ghz_ctl;
|
||||
};
|
||||
|
||||
struct country_code_to_enum_rd {
|
||||
u16 countryCode;
|
||||
u16 regDmnEnum;
|
||||
const char *isoName;
|
||||
};
|
||||
|
||||
struct ath_regulatory {
|
||||
char alpha2[2];
|
||||
u16 country_code;
|
||||
u16 max_power_level;
|
||||
u32 tp_scale;
|
||||
u16 current_rd;
|
||||
u16 current_rd_ext;
|
||||
int16_t power_limit;
|
||||
struct reg_dmn_pair_mapping *regpair;
|
||||
};
|
||||
|
||||
enum CountryCode {
|
||||
CTRY_ALBANIA = 8,
|
||||
CTRY_ALGERIA = 12,
|
||||
|
@ -80,16 +80,16 @@ config B43_NPHY
|
||||
SAY N.
|
||||
|
||||
config B43_PHY_LP
|
||||
bool "IEEE 802.11g LP-PHY support (BROKEN)"
|
||||
depends on B43 && EXPERIMENTAL && BROKEN
|
||||
bool "Support for low-power (LP-PHY) devices (EXPERIMENTAL)"
|
||||
depends on B43 && EXPERIMENTAL
|
||||
---help---
|
||||
Support for the LP-PHY.
|
||||
The LP-PHY is an IEEE 802.11g based PHY built into some notebooks
|
||||
and embedded devices.
|
||||
The LP-PHY is a low-power PHY built into some notebooks
|
||||
and embedded devices. It supports 802.11a/g
|
||||
(802.11a support is optional, and currently disabled).
|
||||
|
||||
THIS IS BROKEN AND DOES NOT WORK YET.
|
||||
|
||||
SAY N.
|
||||
This is heavily experimental, and probably will not work for you.
|
||||
Say N unless you want to help debug the driver.
|
||||
|
||||
# This config option automatically enables b43 LEDS support,
|
||||
# if it's possible.
|
||||
|
@ -1188,7 +1188,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
|
||||
header = &(ring->txhdr_cache[(slot / TX_SLOTS_PER_FRAME) * hdrsize]);
|
||||
cookie = generate_cookie(ring, slot);
|
||||
err = b43_generate_txhdr(ring->dev, header,
|
||||
skb->data, skb->len, info, cookie);
|
||||
skb, info, cookie);
|
||||
if (unlikely(err)) {
|
||||
ring->current_slot = old_top_slot;
|
||||
ring->used_slots = old_used_slots;
|
||||
|
@ -477,7 +477,7 @@ static void lo_measure_setup(struct b43_wldev *dev,
|
||||
} else
|
||||
b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x0802);
|
||||
if (phy->rev >= 2)
|
||||
b43_dummy_transmission(dev);
|
||||
b43_dummy_transmission(dev, false, true);
|
||||
b43_gphy_channel_switch(dev, 6, 0);
|
||||
b43_radio_read16(dev, 0x51); /* dummy read */
|
||||
if (phy->type == B43_PHYTYPE_G)
|
||||
|
@ -80,6 +80,10 @@ static int modparam_nohwcrypt;
|
||||
module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
|
||||
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
|
||||
|
||||
static int modparam_hwtkip;
|
||||
module_param_named(hwtkip, modparam_hwtkip, int, 0444);
|
||||
MODULE_PARM_DESC(hwtkip, "Enable hardware tkip.");
|
||||
|
||||
static int modparam_qos = 1;
|
||||
module_param_named(qos, modparam_qos, int, 0444);
|
||||
MODULE_PARM_DESC(qos, "Enable QOS support (default on)");
|
||||
@ -691,9 +695,9 @@ static void b43_synchronize_irq(struct b43_wldev *dev)
|
||||
}
|
||||
|
||||
/* DummyTransmission function, as documented on
|
||||
* http://bcm-specs.sipsolutions.net/DummyTransmission
|
||||
* http://bcm-v4.sipsolutions.net/802.11/DummyTransmission
|
||||
*/
|
||||
void b43_dummy_transmission(struct b43_wldev *dev)
|
||||
void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on)
|
||||
{
|
||||
struct b43_wl *wl = dev->wl;
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
@ -707,19 +711,12 @@ void b43_dummy_transmission(struct b43_wldev *dev)
|
||||
0x00000000,
|
||||
};
|
||||
|
||||
switch (phy->type) {
|
||||
case B43_PHYTYPE_A:
|
||||
if (ofdm) {
|
||||
max_loop = 0x1E;
|
||||
buffer[0] = 0x000201CC;
|
||||
break;
|
||||
case B43_PHYTYPE_B:
|
||||
case B43_PHYTYPE_G:
|
||||
} else {
|
||||
max_loop = 0xFA;
|
||||
buffer[0] = 0x000B846E;
|
||||
break;
|
||||
default:
|
||||
B43_WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irq(&wl->irq_lock);
|
||||
@ -728,20 +725,35 @@ void b43_dummy_transmission(struct b43_wldev *dev)
|
||||
for (i = 0; i < 5; i++)
|
||||
b43_ram_write(dev, i * 4, buffer[i]);
|
||||
|
||||
/* Commit writes */
|
||||
b43_read32(dev, B43_MMIO_MACCTL);
|
||||
|
||||
b43_write16(dev, 0x0568, 0x0000);
|
||||
b43_write16(dev, 0x07C0, 0x0000);
|
||||
value = ((phy->type == B43_PHYTYPE_A) ? 1 : 0);
|
||||
if (dev->dev->id.revision < 11)
|
||||
b43_write16(dev, 0x07C0, 0x0000);
|
||||
else
|
||||
b43_write16(dev, 0x07C0, 0x0100);
|
||||
value = (ofdm ? 0x41 : 0x40);
|
||||
b43_write16(dev, 0x050C, value);
|
||||
if ((phy->type == B43_PHYTYPE_N) || (phy->type == B43_PHYTYPE_LP))
|
||||
b43_write16(dev, 0x0514, 0x1A02);
|
||||
b43_write16(dev, 0x0508, 0x0000);
|
||||
b43_write16(dev, 0x050A, 0x0000);
|
||||
b43_write16(dev, 0x054C, 0x0000);
|
||||
b43_write16(dev, 0x056A, 0x0014);
|
||||
b43_write16(dev, 0x0568, 0x0826);
|
||||
b43_write16(dev, 0x0500, 0x0000);
|
||||
b43_write16(dev, 0x0502, 0x0030);
|
||||
if (!pa_on && (phy->type == B43_PHYTYPE_N)) {
|
||||
//SPEC TODO
|
||||
}
|
||||
|
||||
switch (phy->type) {
|
||||
case B43_PHYTYPE_N:
|
||||
b43_write16(dev, 0x0502, 0x00D0);
|
||||
break;
|
||||
case B43_PHYTYPE_LP:
|
||||
b43_write16(dev, 0x0502, 0x0050);
|
||||
break;
|
||||
default:
|
||||
b43_write16(dev, 0x0502, 0x0030);
|
||||
}
|
||||
|
||||
if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
|
||||
b43_radio_write16(dev, 0x0051, 0x0017);
|
||||
@ -826,6 +838,85 @@ static void keymac_write(struct b43_wldev *dev, u8 index, const u8 *addr)
|
||||
(index * 2) + 1, addrtmp[1]);
|
||||
}
|
||||
|
||||
/* The ucode will use phase1 key with TEK key to decrypt rx packets.
|
||||
* When a packet is received, the iv32 is checked.
|
||||
* - if it doesn't the packet is returned without modification (and software
|
||||
* decryption can be done). That's what happen when iv16 wrap.
|
||||
* - if it does, the rc4 key is computed, and decryption is tried.
|
||||
* Either it will success and B43_RX_MAC_DEC is returned,
|
||||
* either it fails and B43_RX_MAC_DEC|B43_RX_MAC_DECERR is returned
|
||||
* and the packet is not usable (it got modified by the ucode).
|
||||
* So in order to never have B43_RX_MAC_DECERR, we should provide
|
||||
* a iv32 and phase1key that match. Because we drop packets in case of
|
||||
* B43_RX_MAC_DECERR, if we have a correct iv32 but a wrong phase1key, all
|
||||
* packets will be lost without higher layer knowing (ie no resync possible
|
||||
* until next wrap).
|
||||
*
|
||||
* NOTE : this should support 50 key like RCMTA because
|
||||
* (B43_SHM_SH_KEYIDXBLOCK - B43_SHM_SH_TKIPTSCTTAK)/14 = 50
|
||||
*/
|
||||
static void rx_tkip_phase1_write(struct b43_wldev *dev, u8 index, u32 iv32,
|
||||
u16 *phase1key)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 offset;
|
||||
u8 pairwise_keys_start = B43_NR_GROUP_KEYS * 2;
|
||||
|
||||
if (!modparam_hwtkip)
|
||||
return;
|
||||
|
||||
if (b43_new_kidx_api(dev))
|
||||
pairwise_keys_start = B43_NR_GROUP_KEYS;
|
||||
|
||||
B43_WARN_ON(index < pairwise_keys_start);
|
||||
/* We have four default TX keys and possibly four default RX keys.
|
||||
* Physical mac 0 is mapped to physical key 4 or 8, depending
|
||||
* on the firmware version.
|
||||
* So we must adjust the index here.
|
||||
*/
|
||||
index -= pairwise_keys_start;
|
||||
B43_WARN_ON(index >= B43_NR_PAIRWISE_KEYS);
|
||||
|
||||
if (b43_debug(dev, B43_DBG_KEYS)) {
|
||||
b43dbg(dev->wl, "rx_tkip_phase1_write : idx 0x%x, iv32 0x%x\n",
|
||||
index, iv32);
|
||||
}
|
||||
/* Write the key to the RX tkip shared mem */
|
||||
offset = B43_SHM_SH_TKIPTSCTTAK + index * (10 + 4);
|
||||
for (i = 0; i < 10; i += 2) {
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, offset + i,
|
||||
phase1key ? phase1key[i / 2] : 0);
|
||||
}
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, offset + i, iv32);
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, offset + i + 2, iv32 >> 16);
|
||||
}
|
||||
|
||||
static void b43_op_update_tkip_key(struct ieee80211_hw *hw,
|
||||
struct ieee80211_key_conf *keyconf, const u8 *addr,
|
||||
u32 iv32, u16 *phase1key)
|
||||
{
|
||||
struct b43_wl *wl = hw_to_b43_wl(hw);
|
||||
struct b43_wldev *dev;
|
||||
int index = keyconf->hw_key_idx;
|
||||
|
||||
if (B43_WARN_ON(!modparam_hwtkip))
|
||||
return;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
dev = wl->current_dev;
|
||||
if (!dev || b43_status(dev) < B43_STAT_INITIALIZED)
|
||||
goto out_unlock;
|
||||
|
||||
keymac_write(dev, index, NULL); /* First zero out mac to avoid race */
|
||||
|
||||
rx_tkip_phase1_write(dev, index, iv32, phase1key);
|
||||
keymac_write(dev, index, addr);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
||||
static void do_key_write(struct b43_wldev *dev,
|
||||
u8 index, u8 algorithm,
|
||||
const u8 *key, size_t key_len, const u8 *mac_addr)
|
||||
@ -841,6 +932,19 @@ static void do_key_write(struct b43_wldev *dev,
|
||||
|
||||
if (index >= pairwise_keys_start)
|
||||
keymac_write(dev, index, NULL); /* First zero out mac. */
|
||||
if (algorithm == B43_SEC_ALGO_TKIP) {
|
||||
/*
|
||||
* We should provide an initial iv32, phase1key pair.
|
||||
* We could start with iv32=0 and compute the corresponding
|
||||
* phase1key, but this means calling ieee80211_get_tkip_key
|
||||
* with a fake skb (or export other tkip function).
|
||||
* Because we are lazy we hope iv32 won't start with
|
||||
* 0xffffffff and let's b43_op_update_tkip_key provide a
|
||||
* correct pair.
|
||||
*/
|
||||
rx_tkip_phase1_write(dev, index, 0xffffffff, (u16*)buf);
|
||||
} else if (index >= pairwise_keys_start) /* clear it */
|
||||
rx_tkip_phase1_write(dev, index, 0, NULL);
|
||||
if (key)
|
||||
memcpy(buf, key, key_len);
|
||||
key_write(dev, index, algorithm, buf);
|
||||
@ -859,6 +963,15 @@ static int b43_key_write(struct b43_wldev *dev,
|
||||
int i;
|
||||
int pairwise_keys_start;
|
||||
|
||||
/* For ALG_TKIP the key is encoded as a 256-bit (32 byte) data block:
|
||||
* - Temporal Encryption Key (128 bits)
|
||||
* - Temporal Authenticator Tx MIC Key (64 bits)
|
||||
* - Temporal Authenticator Rx MIC Key (64 bits)
|
||||
*
|
||||
* Hardware only store TEK
|
||||
*/
|
||||
if (algorithm == B43_SEC_ALGO_TKIP && key_len == 32)
|
||||
key_len = 16;
|
||||
if (key_len > B43_SEC_KEYSIZE)
|
||||
return -EINVAL;
|
||||
for (i = 0; i < ARRAY_SIZE(dev->key); i++) {
|
||||
@ -965,6 +1078,14 @@ static void b43_dump_keymemory(struct b43_wldev *dev)
|
||||
printk(" Algo: %04X/%02X", algo, key->algorithm);
|
||||
|
||||
if (index >= pairwise_keys_start) {
|
||||
if (key->algorithm == B43_SEC_ALGO_TKIP) {
|
||||
printk(" TKIP: ");
|
||||
offset = B43_SHM_SH_TKIPTSCTTAK + (index - 4) * (10 + 4);
|
||||
for (i = 0; i < 14; i += 2) {
|
||||
u16 tmp = b43_shm_read16(dev, B43_SHM_SHARED, offset + i);
|
||||
printk("%02X%02X", (tmp & 0xFF), ((tmp >> 8) & 0xFF));
|
||||
}
|
||||
}
|
||||
rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA,
|
||||
((index - pairwise_keys_start) * 2) + 0);
|
||||
rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA,
|
||||
@ -1947,8 +2068,12 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
|
||||
filename = "ucode5";
|
||||
else if ((rev >= 11) && (rev <= 12))
|
||||
filename = "ucode11";
|
||||
else if (rev >= 13)
|
||||
else if (rev == 13)
|
||||
filename = "ucode13";
|
||||
else if (rev == 14)
|
||||
filename = "ucode14";
|
||||
else if (rev >= 15)
|
||||
filename = "ucode15";
|
||||
else
|
||||
goto err_no_ucode;
|
||||
err = b43_do_request_fw(ctx, filename, &fw->ucode);
|
||||
@ -1996,6 +2121,16 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
|
||||
else
|
||||
goto err_no_initvals;
|
||||
break;
|
||||
case B43_PHYTYPE_LP:
|
||||
if (rev == 13)
|
||||
filename = "lp0initvals13";
|
||||
else if (rev == 14)
|
||||
filename = "lp0initvals14";
|
||||
else if (rev >= 15)
|
||||
filename = "lp0initvals15";
|
||||
else
|
||||
goto err_no_initvals;
|
||||
break;
|
||||
default:
|
||||
goto err_no_initvals;
|
||||
}
|
||||
@ -2030,6 +2165,16 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
|
||||
else
|
||||
goto err_no_initvals;
|
||||
break;
|
||||
case B43_PHYTYPE_LP:
|
||||
if (rev == 13)
|
||||
filename = "lp0bsinitvals13";
|
||||
else if (rev == 14)
|
||||
filename = "lp0bsinitvals14";
|
||||
else if (rev >= 15)
|
||||
filename = "lp0bsinitvals15";
|
||||
else
|
||||
goto err_no_initvals;
|
||||
break;
|
||||
default:
|
||||
goto err_no_initvals;
|
||||
}
|
||||
@ -2557,6 +2702,7 @@ static void b43_rate_memory_init(struct b43_wldev *dev)
|
||||
case B43_PHYTYPE_A:
|
||||
case B43_PHYTYPE_G:
|
||||
case B43_PHYTYPE_N:
|
||||
case B43_PHYTYPE_LP:
|
||||
b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1);
|
||||
b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1);
|
||||
b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1);
|
||||
@ -3587,8 +3733,10 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
|
||||
switch (cmd) {
|
||||
case SET_KEY:
|
||||
if (algorithm == B43_SEC_ALGO_TKIP) {
|
||||
/* FIXME: No TKIP hardware encryption for now. */
|
||||
if (algorithm == B43_SEC_ALGO_TKIP &&
|
||||
(!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE) ||
|
||||
!modparam_hwtkip)) {
|
||||
/* We support only pairwise key */
|
||||
err = -EOPNOTSUPP;
|
||||
goto out_unlock;
|
||||
}
|
||||
@ -3618,6 +3766,8 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
b43_hf_read(dev) & ~B43_HF_USEDEFKEYS);
|
||||
}
|
||||
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
|
||||
if (algorithm == B43_SEC_ALGO_TKIP)
|
||||
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
|
||||
break;
|
||||
case DISABLE_KEY: {
|
||||
err = b43_key_clear(dev, key->hw_key_idx);
|
||||
@ -3646,7 +3796,7 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
|
||||
static void b43_op_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed, unsigned int *fflags,
|
||||
int mc_count, struct dev_addr_list *mc_list)
|
||||
u64 multicast)
|
||||
{
|
||||
struct b43_wl *wl = hw_to_b43_wl(hw);
|
||||
struct b43_wldev *dev = wl->current_dev;
|
||||
@ -3785,7 +3935,7 @@ static int b43_phy_versioning(struct b43_wldev *dev)
|
||||
#endif
|
||||
#ifdef CONFIG_B43_PHY_LP
|
||||
case B43_PHYTYPE_LP:
|
||||
if (phy_rev > 1)
|
||||
if (phy_rev > 2)
|
||||
unsupported = 1;
|
||||
break;
|
||||
#endif
|
||||
@ -3842,7 +3992,7 @@ static int b43_phy_versioning(struct b43_wldev *dev)
|
||||
unsupported = 1;
|
||||
break;
|
||||
case B43_PHYTYPE_LP:
|
||||
if (radio_ver != 0x2062)
|
||||
if (radio_ver != 0x2062 && radio_ver != 0x2063)
|
||||
unsupported = 1;
|
||||
break;
|
||||
default:
|
||||
@ -4345,6 +4495,7 @@ static const struct ieee80211_ops b43_hw_ops = {
|
||||
.bss_info_changed = b43_op_bss_info_changed,
|
||||
.configure_filter = b43_op_configure_filter,
|
||||
.set_key = b43_op_set_key,
|
||||
.update_tkip_key = b43_op_update_tkip_key,
|
||||
.get_stats = b43_op_get_stats,
|
||||
.get_tx_stats = b43_op_get_tx_stats,
|
||||
.get_tsf = b43_op_get_tsf,
|
||||
@ -4480,9 +4631,12 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
|
||||
case B43_PHYTYPE_A:
|
||||
have_5ghz_phy = 1;
|
||||
break;
|
||||
case B43_PHYTYPE_LP: //FIXME not always!
|
||||
#if 0 //FIXME enabling 5GHz causes a NULL pointer dereference
|
||||
have_5ghz_phy = 1;
|
||||
#endif
|
||||
case B43_PHYTYPE_G:
|
||||
case B43_PHYTYPE_N:
|
||||
case B43_PHYTYPE_LP:
|
||||
have_2ghz_phy = 1;
|
||||
break;
|
||||
default:
|
||||
@ -4497,7 +4651,8 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
|
||||
}
|
||||
if (1 /* disable A-PHY */) {
|
||||
/* FIXME: For now we disable the A-PHY on multi-PHY devices. */
|
||||
if (dev->phy.type != B43_PHYTYPE_N) {
|
||||
if (dev->phy.type != B43_PHYTYPE_N &&
|
||||
dev->phy.type != B43_PHYTYPE_LP) {
|
||||
have_2ghz_phy = 1;
|
||||
have_5ghz_phy = 0;
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ void __b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value
|
||||
u64 b43_hf_read(struct b43_wldev *dev);
|
||||
void b43_hf_write(struct b43_wldev *dev, u64 value);
|
||||
|
||||
void b43_dummy_transmission(struct b43_wldev *dev);
|
||||
void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on);
|
||||
|
||||
void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags);
|
||||
|
||||
|
@ -333,7 +333,7 @@ static void b43_set_all_gains(struct b43_wldev *dev,
|
||||
b43_phy_maskset(dev, 0x04A1, 0xBFBF, tmp);
|
||||
b43_phy_maskset(dev, 0x04A2, 0xBFBF, tmp);
|
||||
}
|
||||
b43_dummy_transmission(dev);
|
||||
b43_dummy_transmission(dev, false, true);
|
||||
}
|
||||
|
||||
static void b43_set_original_gains(struct b43_wldev *dev)
|
||||
@ -365,7 +365,7 @@ static void b43_set_original_gains(struct b43_wldev *dev)
|
||||
b43_phy_maskset(dev, 0x04A0, 0xBFBF, 0x4040);
|
||||
b43_phy_maskset(dev, 0x04A1, 0xBFBF, 0x4040);
|
||||
b43_phy_maskset(dev, 0x04A2, 0xBFBF, 0x4000);
|
||||
b43_dummy_transmission(dev);
|
||||
b43_dummy_transmission(dev, false, true);
|
||||
}
|
||||
|
||||
/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
|
||||
@ -1964,7 +1964,7 @@ static void b43_phy_init_pctl(struct b43_wldev *dev)
|
||||
}
|
||||
b43_set_txpower_g(dev, &bbatt, &rfatt, 0);
|
||||
}
|
||||
b43_dummy_transmission(dev);
|
||||
b43_dummy_transmission(dev, false, true);
|
||||
gphy->cur_idle_tssi = b43_phy_read(dev, B43_PHY_ITSSI);
|
||||
if (B43_DEBUG) {
|
||||
/* Current-Idle-TSSI sanity check. */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -825,11 +825,11 @@ struct b43_phy_lp {
|
||||
enum b43_lpphy_txpctl_mode txpctl_mode;
|
||||
|
||||
/* Transmit isolation medium band */
|
||||
u8 tx_isolation_med_band; /* FIXME initial value? */
|
||||
u8 tx_isolation_med_band;
|
||||
/* Transmit isolation low band */
|
||||
u8 tx_isolation_low_band; /* FIXME initial value? */
|
||||
u8 tx_isolation_low_band;
|
||||
/* Transmit isolation high band */
|
||||
u8 tx_isolation_hi_band; /* FIXME initial value? */
|
||||
u8 tx_isolation_hi_band;
|
||||
|
||||
/* Max transmit power medium band */
|
||||
u16 max_tx_pwr_med_band;
|
||||
@ -848,7 +848,7 @@ struct b43_phy_lp {
|
||||
s16 txpa[3], txpal[3], txpah[3];
|
||||
|
||||
/* Receive power offset */
|
||||
u8 rx_pwr_offset; /* FIXME initial value? */
|
||||
u8 rx_pwr_offset;
|
||||
|
||||
/* TSSI transmit count */
|
||||
u16 tssi_tx_count;
|
||||
@ -864,16 +864,16 @@ struct b43_phy_lp {
|
||||
s8 tx_pwr_idx_over; /* FIXME initial value? */
|
||||
|
||||
/* RSSI vf */
|
||||
u8 rssi_vf; /* FIXME initial value? */
|
||||
u8 rssi_vf;
|
||||
/* RSSI vc */
|
||||
u8 rssi_vc; /* FIXME initial value? */
|
||||
u8 rssi_vc;
|
||||
/* RSSI gs */
|
||||
u8 rssi_gs; /* FIXME initial value? */
|
||||
u8 rssi_gs;
|
||||
|
||||
/* RC cap */
|
||||
u8 rc_cap; /* FIXME initial value? */
|
||||
/* BX arch */
|
||||
u8 bx_arch; /* FIXME initial value? */
|
||||
u8 bx_arch;
|
||||
|
||||
/* Full calibration channel */
|
||||
u8 full_calib_chan; /* FIXME initial value? */
|
||||
@ -884,8 +884,17 @@ struct b43_phy_lp {
|
||||
|
||||
/* Used for "Save/Restore Dig Filt State" */
|
||||
u16 dig_flt_state[9];
|
||||
|
||||
bool crs_usr_disable, crs_sys_disable;
|
||||
|
||||
unsigned int pdiv;
|
||||
};
|
||||
|
||||
enum tssi_mux_mode {
|
||||
TSSI_MUX_PREPA,
|
||||
TSSI_MUX_POSTPA,
|
||||
TSSI_MUX_EXT,
|
||||
};
|
||||
|
||||
struct b43_phy_operations;
|
||||
extern const struct b43_phy_operations b43_phyops_lp;
|
||||
|
@ -461,8 +461,8 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
|
||||
|
||||
cookie = generate_cookie(q, pack);
|
||||
hdrlen = b43_txhdr_size(q->dev);
|
||||
err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb->data,
|
||||
skb->len, info, cookie);
|
||||
err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb,
|
||||
info, cookie);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -2367,7 +2367,17 @@ static void lpphy_rev2plus_write_gain_table(struct b43_wldev *dev, int offset,
|
||||
tmp = data.pad << 16;
|
||||
tmp |= data.pga << 8;
|
||||
tmp |= data.gm;
|
||||
tmp |= 0x7f000000;
|
||||
if (dev->phy.rev >= 3) {
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
|
||||
tmp |= 0x10 << 24;
|
||||
else
|
||||
tmp |= 0x70 << 24;
|
||||
} else {
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
|
||||
tmp |= 0x14 << 24;
|
||||
else
|
||||
tmp |= 0x7F << 24;
|
||||
}
|
||||
b43_lptab_write(dev, B43_LPTAB32(7, 0xC0 + offset), tmp);
|
||||
tmp = data.bb_mult << 20;
|
||||
tmp |= data.dac << 28;
|
||||
|
@ -37,7 +37,7 @@ static void b43_wa_papd(struct b43_wldev *dev)
|
||||
backup = b43_ofdmtab_read16(dev, B43_OFDMTAB_PWRDYN2, 0);
|
||||
b43_ofdmtab_write16(dev, B43_OFDMTAB_PWRDYN2, 0, 7);
|
||||
b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_APHY, 0, 0);
|
||||
b43_dummy_transmission(dev);
|
||||
b43_dummy_transmission(dev, true, true);
|
||||
b43_ofdmtab_write16(dev, B43_OFDMTAB_PWRDYN2, 0, backup);
|
||||
}
|
||||
|
||||
@ -628,7 +628,7 @@ void b43_wa_all(struct b43_wldev *dev)
|
||||
B43_WARN_ON(1);
|
||||
}
|
||||
b43_wa_boards_g(dev);
|
||||
} else { /* No N PHY support so far */
|
||||
} else { /* No N PHY support so far, LP PHY is in phy_lp.c */
|
||||
B43_WARN_ON(1);
|
||||
}
|
||||
|
||||
|
@ -180,11 +180,12 @@ static u8 b43_calc_fallback_rate(u8 bitrate)
|
||||
/* Generate a TX data header. */
|
||||
int b43_generate_txhdr(struct b43_wldev *dev,
|
||||
u8 *_txhdr,
|
||||
const unsigned char *fragment_data,
|
||||
unsigned int fragment_len,
|
||||
struct sk_buff *skb_frag,
|
||||
struct ieee80211_tx_info *info,
|
||||
u16 cookie)
|
||||
{
|
||||
const unsigned char *fragment_data = skb_frag->data;
|
||||
unsigned int fragment_len = skb_frag->len;
|
||||
struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
|
||||
const struct b43_phy *phy = &dev->phy;
|
||||
const struct ieee80211_hdr *wlhdr =
|
||||
@ -258,9 +259,26 @@ int b43_generate_txhdr(struct b43_wldev *dev,
|
||||
mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
|
||||
B43_TXH_MAC_KEYALG;
|
||||
wlhdr_len = ieee80211_hdrlen(fctl);
|
||||
iv_len = min((size_t) info->control.hw_key->iv_len,
|
||||
ARRAY_SIZE(txhdr->iv));
|
||||
memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
|
||||
if (key->algorithm == B43_SEC_ALGO_TKIP) {
|
||||
u16 phase1key[5];
|
||||
int i;
|
||||
/* we give the phase1key and iv16 here, the key is stored in
|
||||
* shm. With that the hardware can do phase 2 and encryption.
|
||||
*/
|
||||
ieee80211_get_tkip_key(info->control.hw_key, skb_frag,
|
||||
IEEE80211_TKIP_P1_KEY, (u8*)phase1key);
|
||||
/* phase1key is in host endian */
|
||||
for (i = 0; i < 5; i++)
|
||||
phase1key[i] = cpu_to_le16(phase1key[i]);
|
||||
|
||||
memcpy(txhdr->iv, phase1key, 10);
|
||||
/* iv16 */
|
||||
memcpy(txhdr->iv + 10, ((u8 *) wlhdr) + wlhdr_len, 3);
|
||||
} else {
|
||||
iv_len = min((size_t) info->control.hw_key->iv_len,
|
||||
ARRAY_SIZE(txhdr->iv));
|
||||
memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
|
||||
}
|
||||
}
|
||||
if (b43_is_old_txhdr_format(dev)) {
|
||||
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp),
|
||||
@ -655,6 +673,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
|
||||
status.freq = chanid + 2400;
|
||||
break;
|
||||
case B43_PHYTYPE_N:
|
||||
case B43_PHYTYPE_LP:
|
||||
/* chanid is the SHM channel cookie. Which is the plain
|
||||
* channel number in b43. */
|
||||
if (chanstat & B43_RX_CHAN_5GHZ) {
|
||||
|
@ -176,8 +176,7 @@ size_t b43_txhdr_size(struct b43_wldev *dev)
|
||||
|
||||
int b43_generate_txhdr(struct b43_wldev *dev,
|
||||
u8 * txhdr,
|
||||
const unsigned char *fragment_data,
|
||||
unsigned int fragment_len,
|
||||
struct sk_buff *skb_frag,
|
||||
struct ieee80211_tx_info *txctl, u16 cookie);
|
||||
|
||||
/* Transmit Status */
|
||||
|
@ -2836,9 +2836,7 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
|
||||
static void b43legacy_op_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed,
|
||||
unsigned int *fflags,
|
||||
int mc_count,
|
||||
struct dev_addr_list *mc_list)
|
||||
unsigned int *fflags,u64 multicast)
|
||||
{
|
||||
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
|
||||
struct b43legacy_wldev *dev = wl->current_dev;
|
||||
|
@ -185,7 +185,7 @@ MODULE_AUTHOR(DRV_COPYRIGHT);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int debug = 0;
|
||||
static int mode = 0;
|
||||
static int network_mode = 0;
|
||||
static int channel = 0;
|
||||
static int associate = 0;
|
||||
static int disable = 0;
|
||||
@ -195,7 +195,7 @@ static struct ipw2100_fw ipw2100_firmware;
|
||||
|
||||
#include <linux/moduleparam.h>
|
||||
module_param(debug, int, 0444);
|
||||
module_param(mode, int, 0444);
|
||||
module_param_named(mode, network_mode, int, 0444);
|
||||
module_param(channel, int, 0444);
|
||||
module_param(associate, int, 0444);
|
||||
module_param(disable, int, 0444);
|
||||
@ -2844,7 +2844,7 @@ static int __ipw2100_tx_process(struct ipw2100_priv *priv)
|
||||
|
||||
#ifdef CONFIG_IPW2100_DEBUG
|
||||
{
|
||||
int i = txq->oldest;
|
||||
i = txq->oldest;
|
||||
IPW_DEBUG_TX("TX%d V=%p P=%04X T=%04X L=%d\n", i,
|
||||
&txq->drv[i],
|
||||
(u32) (txq->nic + i * sizeof(struct ipw2100_bd)),
|
||||
@ -6076,7 +6076,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
|
||||
priv->ieee->ieee802_1x = 1;
|
||||
|
||||
/* Set module parameters */
|
||||
switch (mode) {
|
||||
switch (network_mode) {
|
||||
case 1:
|
||||
priv->ieee->iw_mode = IW_MODE_ADHOC;
|
||||
break;
|
||||
@ -8179,10 +8179,11 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev)
|
||||
int rssi_qual;
|
||||
int tx_qual;
|
||||
int beacon_qual;
|
||||
int quality;
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct iw_statistics *wstats;
|
||||
u32 rssi, quality, tx_retries, missed_beacons, tx_failures;
|
||||
u32 rssi, tx_retries, missed_beacons, tx_failures;
|
||||
u32 ord_len = sizeof(u32);
|
||||
|
||||
if (!priv)
|
||||
@ -8265,7 +8266,8 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev)
|
||||
beacon_qual = (20 - missed_beacons) *
|
||||
(PERFECT - VERY_GOOD) / 20 + VERY_GOOD;
|
||||
|
||||
quality = min(beacon_qual, min(tx_qual, rssi_qual));
|
||||
quality = min(tx_qual, rssi_qual);
|
||||
quality = min(beacon_qual, quality);
|
||||
|
||||
#ifdef CONFIG_IPW2100_DEBUG
|
||||
if (beacon_qual == quality)
|
||||
|
@ -83,13 +83,13 @@ MODULE_LICENSE("GPL");
|
||||
|
||||
static int cmdlog = 0;
|
||||
static int debug = 0;
|
||||
static int channel = 0;
|
||||
static int mode = 0;
|
||||
static int default_channel = 0;
|
||||
static int network_mode = 0;
|
||||
|
||||
static u32 ipw_debug_level;
|
||||
static int associate;
|
||||
static int auto_create = 1;
|
||||
static int led = 0;
|
||||
static int led_support = 0;
|
||||
static int disable = 0;
|
||||
static int bt_coexist = 0;
|
||||
static int hwcrypto = 0;
|
||||
@ -4265,9 +4265,10 @@ static void ipw_gather_stats(struct ipw_priv *priv)
|
||||
IPW_DEBUG_STATS("Signal level : %3d%% (%d dBm)\n",
|
||||
signal_quality, rssi);
|
||||
|
||||
quality = min(beacon_quality,
|
||||
min(rate_quality,
|
||||
min(tx_quality, min(rx_quality, signal_quality))));
|
||||
quality = min(rx_quality, signal_quality);
|
||||
quality = min(tx_quality, quality);
|
||||
quality = min(rate_quality, quality);
|
||||
quality = min(beacon_quality, quality);
|
||||
if (quality == beacon_quality)
|
||||
IPW_DEBUG_STATS("Quality (%d%%): Clamped to missed beacons.\n",
|
||||
quality);
|
||||
@ -4411,7 +4412,6 @@ static void ipw_rx_notification(struct ipw_priv *priv,
|
||||
{
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
u16 size = le16_to_cpu(notif->size);
|
||||
notif->size = le16_to_cpu(notif->size);
|
||||
|
||||
IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, size);
|
||||
|
||||
@ -6101,11 +6101,10 @@ static void ipw_debug_config(struct ipw_priv *priv)
|
||||
static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode)
|
||||
{
|
||||
/* TODO: Verify that this works... */
|
||||
struct ipw_fixed_rate fr = {
|
||||
.tx_rates = priv->rates_mask
|
||||
};
|
||||
struct ipw_fixed_rate fr;
|
||||
u32 reg;
|
||||
u16 mask = 0;
|
||||
u16 new_tx_rates = priv->rates_mask;
|
||||
|
||||
/* Identify 'current FW band' and match it with the fixed
|
||||
* Tx rates */
|
||||
@ -6117,54 +6116,56 @@ static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode)
|
||||
/* Invalid fixed rate mask */
|
||||
IPW_DEBUG_WX
|
||||
("invalid fixed rate mask in ipw_set_fixed_rate\n");
|
||||
fr.tx_rates = 0;
|
||||
new_tx_rates = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
fr.tx_rates >>= IEEE80211_OFDM_SHIFT_MASK_A;
|
||||
new_tx_rates >>= IEEE80211_OFDM_SHIFT_MASK_A;
|
||||
break;
|
||||
|
||||
default: /* 2.4Ghz or Mixed */
|
||||
/* IEEE_B */
|
||||
if (mode == IEEE_B) {
|
||||
if (fr.tx_rates & ~IEEE80211_CCK_RATES_MASK) {
|
||||
if (new_tx_rates & ~IEEE80211_CCK_RATES_MASK) {
|
||||
/* Invalid fixed rate mask */
|
||||
IPW_DEBUG_WX
|
||||
("invalid fixed rate mask in ipw_set_fixed_rate\n");
|
||||
fr.tx_rates = 0;
|
||||
new_tx_rates = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* IEEE_G */
|
||||
if (fr.tx_rates & ~(IEEE80211_CCK_RATES_MASK |
|
||||
if (new_tx_rates & ~(IEEE80211_CCK_RATES_MASK |
|
||||
IEEE80211_OFDM_RATES_MASK)) {
|
||||
/* Invalid fixed rate mask */
|
||||
IPW_DEBUG_WX
|
||||
("invalid fixed rate mask in ipw_set_fixed_rate\n");
|
||||
fr.tx_rates = 0;
|
||||
new_tx_rates = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (IEEE80211_OFDM_RATE_6MB_MASK & fr.tx_rates) {
|
||||
if (IEEE80211_OFDM_RATE_6MB_MASK & new_tx_rates) {
|
||||
mask |= (IEEE80211_OFDM_RATE_6MB_MASK >> 1);
|
||||
fr.tx_rates &= ~IEEE80211_OFDM_RATE_6MB_MASK;
|
||||
new_tx_rates &= ~IEEE80211_OFDM_RATE_6MB_MASK;
|
||||
}
|
||||
|
||||
if (IEEE80211_OFDM_RATE_9MB_MASK & fr.tx_rates) {
|
||||
if (IEEE80211_OFDM_RATE_9MB_MASK & new_tx_rates) {
|
||||
mask |= (IEEE80211_OFDM_RATE_9MB_MASK >> 1);
|
||||
fr.tx_rates &= ~IEEE80211_OFDM_RATE_9MB_MASK;
|
||||
new_tx_rates &= ~IEEE80211_OFDM_RATE_9MB_MASK;
|
||||
}
|
||||
|
||||
if (IEEE80211_OFDM_RATE_12MB_MASK & fr.tx_rates) {
|
||||
if (IEEE80211_OFDM_RATE_12MB_MASK & new_tx_rates) {
|
||||
mask |= (IEEE80211_OFDM_RATE_12MB_MASK >> 1);
|
||||
fr.tx_rates &= ~IEEE80211_OFDM_RATE_12MB_MASK;
|
||||
new_tx_rates &= ~IEEE80211_OFDM_RATE_12MB_MASK;
|
||||
}
|
||||
|
||||
fr.tx_rates |= mask;
|
||||
new_tx_rates |= mask;
|
||||
break;
|
||||
}
|
||||
|
||||
fr.tx_rates = cpu_to_le16(new_tx_rates);
|
||||
|
||||
reg = ipw_read32(priv, IPW_MEM_FIXED_OVERRIDE);
|
||||
ipw_write_reg32(priv, reg, *(u32 *) & fr);
|
||||
}
|
||||
@ -7850,7 +7851,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv,
|
||||
|
||||
/* Convert signal to DBM */
|
||||
ipw_rt->rt_dbmsignal = antsignal;
|
||||
ipw_rt->rt_dbmnoise = frame->noise;
|
||||
ipw_rt->rt_dbmnoise = (s8) le16_to_cpu(frame->noise);
|
||||
|
||||
/* Convert the channel data and set the flags */
|
||||
ipw_rt->rt_channel = cpu_to_le16(ieee80211chan2mhz(received_channel));
|
||||
@ -7964,7 +7965,7 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv,
|
||||
u16 channel = frame->received_channel;
|
||||
u8 phy_flags = frame->antennaAndPhy;
|
||||
s8 signal = frame->rssi_dbm - IPW_RSSI_TO_DBM;
|
||||
s8 noise = frame->noise;
|
||||
s8 noise = (s8) le16_to_cpu(frame->noise);
|
||||
u8 rate = frame->rate;
|
||||
short len = le16_to_cpu(pkt->u.frame.length);
|
||||
struct sk_buff *skb;
|
||||
@ -8335,7 +8336,7 @@ static void ipw_rx(struct ipw_priv *priv)
|
||||
.rssi = pkt->u.frame.rssi_dbm -
|
||||
IPW_RSSI_TO_DBM,
|
||||
.signal =
|
||||
le16_to_cpu(pkt->u.frame.rssi_dbm) -
|
||||
pkt->u.frame.rssi_dbm -
|
||||
IPW_RSSI_TO_DBM + 0x100,
|
||||
.noise =
|
||||
le16_to_cpu(pkt->u.frame.noise),
|
||||
@ -8517,7 +8518,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option)
|
||||
|
||||
/* We default to disabling the LED code as right now it causes
|
||||
* too many systems to lock up... */
|
||||
if (!led)
|
||||
if (!led_support)
|
||||
priv->config |= CFG_NO_LED;
|
||||
|
||||
if (associate)
|
||||
@ -8539,10 +8540,10 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option)
|
||||
IPW_DEBUG_INFO("Radio disabled.\n");
|
||||
}
|
||||
|
||||
if (channel != 0) {
|
||||
if (default_channel != 0) {
|
||||
priv->config |= CFG_STATIC_CHANNEL;
|
||||
priv->channel = channel;
|
||||
IPW_DEBUG_INFO("Bind to static channel %d\n", channel);
|
||||
priv->channel = default_channel;
|
||||
IPW_DEBUG_INFO("Bind to static channel %d\n", default_channel);
|
||||
/* TODO: Validate that provided channel is in range */
|
||||
}
|
||||
#ifdef CONFIG_IPW2200_QOS
|
||||
@ -8550,7 +8551,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option)
|
||||
burst_duration_CCK, burst_duration_OFDM);
|
||||
#endif /* CONFIG_IPW2200_QOS */
|
||||
|
||||
switch (mode) {
|
||||
switch (network_mode) {
|
||||
case 1:
|
||||
priv->ieee->iw_mode = IW_MODE_ADHOC;
|
||||
priv->net_dev->type = ARPHRD_ETHER;
|
||||
@ -10181,7 +10182,6 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
|
||||
#endif
|
||||
struct clx2_queue *q = &txq->q;
|
||||
u8 id, hdr_len, unicast;
|
||||
u16 remaining_bytes;
|
||||
int fc;
|
||||
|
||||
if (!(priv->status & STATUS_ASSOCIATED))
|
||||
@ -10220,7 +10220,6 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
|
||||
|
||||
tfd->u.data.cmd_id = DINO_CMD_TX;
|
||||
tfd->u.data.len = cpu_to_le16(txb->payload_size);
|
||||
remaining_bytes = txb->payload_size;
|
||||
|
||||
if (priv->assoc_request.ieee_mode == IPW_B_MODE)
|
||||
tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_MODE_CCK;
|
||||
@ -11946,13 +11945,13 @@ MODULE_PARM_DESC(associate, "auto associate when scanning (default off)");
|
||||
module_param(auto_create, int, 0444);
|
||||
MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)");
|
||||
|
||||
module_param(led, int, 0444);
|
||||
module_param_named(led, led_support, int, 0444);
|
||||
MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)");
|
||||
|
||||
module_param(debug, int, 0444);
|
||||
MODULE_PARM_DESC(debug, "debug output mask");
|
||||
|
||||
module_param(channel, int, 0444);
|
||||
module_param_named(channel, default_channel, int, 0444);
|
||||
MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])");
|
||||
|
||||
#ifdef CONFIG_IPW2200_PROMISCUOUS
|
||||
@ -11978,10 +11977,10 @@ MODULE_PARM_DESC(burst_duration_OFDM, "set OFDM burst value");
|
||||
#endif /* CONFIG_IPW2200_QOS */
|
||||
|
||||
#ifdef CONFIG_IPW2200_MONITOR
|
||||
module_param(mode, int, 0444);
|
||||
module_param_named(mode, network_mode, int, 0444);
|
||||
MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)");
|
||||
#else
|
||||
module_param(mode, int, 0444);
|
||||
module_param_named(mode, network_mode, int, 0444);
|
||||
MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)");
|
||||
#endif
|
||||
|
||||
|
@ -149,12 +149,15 @@ struct iwl_cfg iwl1000_bgn_cfg = {
|
||||
.ucode_api_min = IWL1000_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl1000_ops,
|
||||
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_A,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = true,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_1000,
|
||||
.shadow_ram_support = false,
|
||||
.ht_greenfield_support = true,
|
||||
};
|
||||
|
||||
|
@ -349,12 +349,13 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void iwl3945_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
|
||||
IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
|
||||
(int)sizeof(struct iwl3945_notif_statistics),
|
||||
le32_to_cpu(pkt->len));
|
||||
le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
|
||||
|
||||
memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39));
|
||||
|
||||
@ -2889,7 +2890,8 @@ static struct iwl_cfg iwl3945_bg_cfg = {
|
||||
.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
|
||||
.ops = &iwl3945_ops,
|
||||
.mod_params = &iwl3945_mod_params,
|
||||
.use_isr_legacy = true
|
||||
.use_isr_legacy = true,
|
||||
.ht_greenfield_support = false,
|
||||
};
|
||||
|
||||
static struct iwl_cfg iwl3945_abg_cfg = {
|
||||
@ -2902,7 +2904,8 @@ static struct iwl_cfg iwl3945_abg_cfg = {
|
||||
.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
|
||||
.ops = &iwl3945_ops,
|
||||
.mod_params = &iwl3945_mod_params,
|
||||
.use_isr_legacy = true
|
||||
.use_isr_legacy = true,
|
||||
.ht_greenfield_support = false,
|
||||
};
|
||||
|
||||
struct pci_device_id iwl3945_hw_card_ids[] = {
|
||||
|
@ -2344,7 +2344,8 @@ struct iwl_cfg iwl4965_agn_cfg = {
|
||||
.eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
|
||||
.ops = &iwl4965_ops,
|
||||
.mod_params = &iwl4965_mod_params,
|
||||
.use_isr_legacy = true
|
||||
.use_isr_legacy = true,
|
||||
.ht_greenfield_support = false,
|
||||
};
|
||||
|
||||
/* Module firmware */
|
||||
|
@ -494,7 +494,7 @@ static void iwl5000_rx_calib_result(struct iwl_priv *priv,
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
|
||||
struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw;
|
||||
int len = le32_to_cpu(pkt->len) & FH_RSCSR_FRAME_SIZE_MSK;
|
||||
int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
|
||||
int index;
|
||||
|
||||
/* reduce the size of the length field itself */
|
||||
@ -1411,6 +1411,7 @@ static void iwl5150_temperature(struct iwl_priv *priv)
|
||||
vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;
|
||||
/* now vt hold the temperature in Kelvin */
|
||||
priv->temperature = KELVIN_TO_CELSIUS(vt);
|
||||
iwl_tt_handler(priv);
|
||||
}
|
||||
|
||||
/* Calc max signal level (dBm) among 3 possible receivers */
|
||||
@ -1652,6 +1653,7 @@ struct iwl_cfg iwl5300_agn_cfg = {
|
||||
.valid_tx_ant = ANT_ABC,
|
||||
.valid_rx_ant = ANT_ABC,
|
||||
.need_pll_cfg = true,
|
||||
.ht_greenfield_support = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5100_bg_cfg = {
|
||||
@ -1668,6 +1670,7 @@ struct iwl_cfg iwl5100_bg_cfg = {
|
||||
.valid_tx_ant = ANT_B,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = true,
|
||||
.ht_greenfield_support = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5100_abg_cfg = {
|
||||
@ -1684,6 +1687,7 @@ struct iwl_cfg iwl5100_abg_cfg = {
|
||||
.valid_tx_ant = ANT_B,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = true,
|
||||
.ht_greenfield_support = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5100_agn_cfg = {
|
||||
@ -1700,6 +1704,7 @@ struct iwl_cfg iwl5100_agn_cfg = {
|
||||
.valid_tx_ant = ANT_B,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = true,
|
||||
.ht_greenfield_support = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5350_agn_cfg = {
|
||||
@ -1716,6 +1721,7 @@ struct iwl_cfg iwl5350_agn_cfg = {
|
||||
.valid_tx_ant = ANT_ABC,
|
||||
.valid_rx_ant = ANT_ABC,
|
||||
.need_pll_cfg = true,
|
||||
.ht_greenfield_support = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5150_agn_cfg = {
|
||||
@ -1732,6 +1738,7 @@ struct iwl_cfg iwl5150_agn_cfg = {
|
||||
.valid_tx_ant = ANT_A,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = true,
|
||||
.ht_greenfield_support = true,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
|
||||
|
@ -161,7 +161,7 @@ struct iwl_cfg iwl6000h_2agn_cfg = {
|
||||
.ucode_api_min = IWL6000_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
@ -169,6 +169,9 @@ struct iwl_cfg iwl6000h_2agn_cfg = {
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = false,
|
||||
.pa_type = IWL_PA_HYBRID,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -181,7 +184,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
|
||||
.ucode_api_min = IWL6000_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
@ -189,6 +192,9 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
|
||||
.valid_rx_ant = ANT_BC,
|
||||
.need_pll_cfg = false,
|
||||
.pa_type = IWL_PA_INTERNAL,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6050_2agn_cfg = {
|
||||
@ -198,7 +204,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
|
||||
.ucode_api_min = IWL6050_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
@ -206,6 +212,9 @@ struct iwl_cfg iwl6050_2agn_cfg = {
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000_3agn_cfg = {
|
||||
@ -215,7 +224,7 @@ struct iwl_cfg iwl6000_3agn_cfg = {
|
||||
.ucode_api_min = IWL6000_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
@ -223,6 +232,9 @@ struct iwl_cfg iwl6000_3agn_cfg = {
|
||||
.valid_rx_ant = ANT_ABC,
|
||||
.need_pll_cfg = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6050_3agn_cfg = {
|
||||
@ -232,7 +244,7 @@ struct iwl_cfg iwl6050_3agn_cfg = {
|
||||
.ucode_api_min = IWL6050_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
@ -240,6 +252,9 @@ struct iwl_cfg iwl6050_3agn_cfg = {
|
||||
.valid_rx_ant = ANT_ABC,
|
||||
.need_pll_cfg = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
|
||||
|
@ -332,6 +332,9 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
|
||||
} else
|
||||
return MAX_TID_COUNT;
|
||||
|
||||
if (unlikely(tid >= TID_MAX_LOAD_COUNT))
|
||||
return MAX_TID_COUNT;
|
||||
|
||||
tl = &lq_data->load[tid];
|
||||
|
||||
curr_time -= curr_time % TID_ROUND_VALUE;
|
||||
@ -654,19 +657,15 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* in 4965 we don't use greenfield at all */
|
||||
static inline u8 rs_use_green(struct iwl_priv *priv,
|
||||
struct ieee80211_conf *conf)
|
||||
/**
|
||||
* Green-field mode is valid if the station supports it and
|
||||
* there are no non-GF stations present in the BSS.
|
||||
*/
|
||||
static inline u8 rs_use_green(struct ieee80211_sta *sta,
|
||||
struct iwl_ht_info *ht_conf)
|
||||
{
|
||||
u8 is_green;
|
||||
|
||||
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
|
||||
is_green = 0;
|
||||
else
|
||||
is_green = (conf_is_ht(conf) &&
|
||||
priv->current_ht_config.is_green_field &&
|
||||
!priv->current_ht_config.non_GF_STA_present);
|
||||
return is_green;
|
||||
return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) &&
|
||||
!(ht_conf->non_GF_STA_present);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1222,18 +1221,6 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
|
||||
else
|
||||
tbl->is_ht40 = 0;
|
||||
|
||||
/* FIXME: - don't toggle SGI here
|
||||
if (tbl->is_ht40) {
|
||||
if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
|
||||
tbl->is_SGI = 1;
|
||||
else
|
||||
tbl->is_SGI = 0;
|
||||
} else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY)
|
||||
tbl->is_SGI = 1;
|
||||
else
|
||||
tbl->is_SGI = 0;
|
||||
*/
|
||||
|
||||
rs_set_expected_tpt_table(lq_sta, tbl);
|
||||
|
||||
rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index);
|
||||
@ -1288,18 +1275,6 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
|
||||
else
|
||||
tbl->is_ht40 = 0;
|
||||
|
||||
/* FIXME: - don't toggle SGI here
|
||||
if (tbl->is_ht40) {
|
||||
if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
|
||||
tbl->is_SGI = 1;
|
||||
else
|
||||
tbl->is_SGI = 0;
|
||||
} else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY)
|
||||
tbl->is_SGI = 1;
|
||||
else
|
||||
tbl->is_SGI = 0;
|
||||
*/
|
||||
|
||||
rs_set_expected_tpt_table(lq_sta, tbl);
|
||||
|
||||
rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index);
|
||||
@ -1347,18 +1322,6 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
|
||||
else
|
||||
tbl->is_ht40 = 0;
|
||||
|
||||
/* FIXME: - don't toggle SGI here
|
||||
if (tbl->is_ht40) {
|
||||
if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
|
||||
tbl->is_SGI = 1;
|
||||
else
|
||||
tbl->is_SGI = 0;
|
||||
} else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY)
|
||||
tbl->is_SGI = 1;
|
||||
else
|
||||
tbl->is_SGI = 0;
|
||||
*/
|
||||
|
||||
if (is_green)
|
||||
tbl->is_SGI = 0; /*11n spec: no SGI in SISO+Greenfield*/
|
||||
|
||||
@ -1527,6 +1490,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
|
||||
struct iwl_scale_tbl_info *search_tbl =
|
||||
&(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
|
||||
struct iwl_rate_scale_data *window = &(tbl->win[index]);
|
||||
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
|
||||
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
|
||||
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
|
||||
u8 start_action = tbl->action;
|
||||
@ -1586,13 +1550,11 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
|
||||
goto out;
|
||||
break;
|
||||
case IWL_SISO_SWITCH_GI:
|
||||
if (!tbl->is_ht40 &&
|
||||
!(priv->current_ht_config.sgf &
|
||||
HT_SHORT_GI_20MHZ))
|
||||
if (!tbl->is_ht40 && !(ht_cap->cap &
|
||||
IEEE80211_HT_CAP_SGI_20))
|
||||
break;
|
||||
if (tbl->is_ht40 &&
|
||||
!(priv->current_ht_config.sgf &
|
||||
HT_SHORT_GI_40MHZ))
|
||||
if (tbl->is_ht40 && !(ht_cap->cap &
|
||||
IEEE80211_HT_CAP_SGI_40))
|
||||
break;
|
||||
|
||||
IWL_DEBUG_RATE(priv, "LQ: SISO toggle SGI/NGI\n");
|
||||
@ -1666,6 +1628,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
|
||||
struct iwl_scale_tbl_info *search_tbl =
|
||||
&(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
|
||||
struct iwl_rate_scale_data *window = &(tbl->win[index]);
|
||||
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
|
||||
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
|
||||
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
|
||||
u8 start_action = tbl->action;
|
||||
@ -1726,13 +1689,11 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
|
||||
break;
|
||||
|
||||
case IWL_MIMO2_SWITCH_GI:
|
||||
if (!tbl->is_ht40 &&
|
||||
!(priv->current_ht_config.sgf &
|
||||
HT_SHORT_GI_20MHZ))
|
||||
if (!tbl->is_ht40 && !(ht_cap->cap &
|
||||
IEEE80211_HT_CAP_SGI_20))
|
||||
break;
|
||||
if (tbl->is_ht40 &&
|
||||
!(priv->current_ht_config.sgf &
|
||||
HT_SHORT_GI_40MHZ))
|
||||
if (tbl->is_ht40 && !(ht_cap->cap &
|
||||
IEEE80211_HT_CAP_SGI_40))
|
||||
break;
|
||||
|
||||
IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle SGI/NGI\n");
|
||||
@ -1808,6 +1769,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
|
||||
struct iwl_scale_tbl_info *search_tbl =
|
||||
&(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
|
||||
struct iwl_rate_scale_data *window = &(tbl->win[index]);
|
||||
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
|
||||
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
|
||||
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
|
||||
u8 start_action = tbl->action;
|
||||
@ -1890,13 +1852,11 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
|
||||
break;
|
||||
|
||||
case IWL_MIMO3_SWITCH_GI:
|
||||
if (!tbl->is_ht40 &&
|
||||
!(priv->current_ht_config.sgf &
|
||||
HT_SHORT_GI_20MHZ))
|
||||
if (!tbl->is_ht40 && !(ht_cap->cap &
|
||||
IEEE80211_HT_CAP_SGI_20))
|
||||
break;
|
||||
if (tbl->is_ht40 &&
|
||||
!(priv->current_ht_config.sgf &
|
||||
HT_SHORT_GI_40MHZ))
|
||||
if (tbl->is_ht40 && !(ht_cap->cap &
|
||||
IEEE80211_HT_CAP_SGI_40))
|
||||
break;
|
||||
|
||||
IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle SGI/NGI\n");
|
||||
@ -2108,7 +2068,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
|
||||
if (is_legacy(tbl->lq_type))
|
||||
lq_sta->is_green = 0;
|
||||
else
|
||||
lq_sta->is_green = rs_use_green(priv, conf);
|
||||
lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config);
|
||||
is_green = lq_sta->is_green;
|
||||
|
||||
/* current tx rate */
|
||||
@ -2466,7 +2426,7 @@ static void rs_initialize_lq(struct iwl_priv *priv,
|
||||
int rate_idx;
|
||||
int i;
|
||||
u32 rate;
|
||||
u8 use_green = rs_use_green(priv, conf);
|
||||
u8 use_green = rs_use_green(sta, &priv->current_ht_config);
|
||||
u8 active_tbl = 0;
|
||||
u8 valid_tx_ant;
|
||||
|
||||
@ -2519,6 +2479,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
|
||||
struct ieee80211_supported_band *sband = txrc->sband;
|
||||
struct iwl_priv *priv = (struct iwl_priv *)priv_r;
|
||||
struct ieee80211_conf *conf = &priv->hw->conf;
|
||||
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct iwl_lq_sta *lq_sta = priv_sta;
|
||||
@ -2551,7 +2512,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
|
||||
IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n",
|
||||
hdr->addr1);
|
||||
sta_id = iwl_add_station(priv, hdr->addr1,
|
||||
false, CMD_ASYNC, NULL);
|
||||
false, CMD_ASYNC, ht_cap);
|
||||
}
|
||||
if ((sta_id != IWL_INVALID_STATION)) {
|
||||
lq_sta->lq.sta_id = sta_id;
|
||||
@ -2620,6 +2581,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
|
||||
int i, j;
|
||||
struct iwl_priv *priv = (struct iwl_priv *)priv_r;
|
||||
struct ieee80211_conf *conf = &priv->hw->conf;
|
||||
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
|
||||
struct iwl_lq_sta *lq_sta = priv_sta;
|
||||
u16 mask_bit = 0;
|
||||
int count;
|
||||
@ -2648,7 +2610,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr);
|
||||
sta_id = iwl_add_station(priv, sta->addr, false,
|
||||
CMD_ASYNC, NULL);
|
||||
CMD_ASYNC, ht_cap);
|
||||
}
|
||||
if ((sta_id != IWL_INVALID_STATION)) {
|
||||
lq_sta->lq.sta_id = sta_id;
|
||||
@ -2661,7 +2623,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
|
||||
lq_sta->is_dup = 0;
|
||||
lq_sta->max_rate_idx = -1;
|
||||
lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX;
|
||||
lq_sta->is_green = rs_use_green(priv, conf);
|
||||
lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config);
|
||||
lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
|
||||
lq_sta->active_rate_basic = priv->active_rate_basic;
|
||||
lq_sta->band = priv->band;
|
||||
@ -2669,19 +2631,19 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
|
||||
* active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
|
||||
* supp_rates[] does not; shift to convert format, force 9 MBits off.
|
||||
*/
|
||||
lq_sta->active_siso_rate = sta->ht_cap.mcs.rx_mask[0] << 1;
|
||||
lq_sta->active_siso_rate |= sta->ht_cap.mcs.rx_mask[0] & 0x1;
|
||||
lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1;
|
||||
lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1;
|
||||
lq_sta->active_siso_rate &= ~((u16)0x2);
|
||||
lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE;
|
||||
|
||||
/* Same here */
|
||||
lq_sta->active_mimo2_rate = sta->ht_cap.mcs.rx_mask[1] << 1;
|
||||
lq_sta->active_mimo2_rate |= sta->ht_cap.mcs.rx_mask[1] & 0x1;
|
||||
lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1;
|
||||
lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1;
|
||||
lq_sta->active_mimo2_rate &= ~((u16)0x2);
|
||||
lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE;
|
||||
|
||||
lq_sta->active_mimo3_rate = sta->ht_cap.mcs.rx_mask[2] << 1;
|
||||
lq_sta->active_mimo3_rate |= sta->ht_cap.mcs.rx_mask[2] & 0x1;
|
||||
lq_sta->active_mimo3_rate = ht_cap->mcs.rx_mask[2] << 1;
|
||||
lq_sta->active_mimo3_rate |= ht_cap->mcs.rx_mask[2] & 0x1;
|
||||
lq_sta->active_mimo3_rate &= ~((u16)0x2);
|
||||
lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE;
|
||||
|
||||
|
@ -1156,6 +1156,7 @@ struct iwl_wep_cmd {
|
||||
#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK cpu_to_le16(1 << 2)
|
||||
#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK cpu_to_le16(1 << 3)
|
||||
#define RX_RES_PHY_FLAGS_ANTENNA_MSK cpu_to_le16(0xf0)
|
||||
#define RX_RES_PHY_FLAGS_ANTENNA_POS 4
|
||||
|
||||
#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8)
|
||||
#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8)
|
||||
@ -3481,7 +3482,7 @@ struct iwl_wimax_coex_cmd {
|
||||
*****************************************************************************/
|
||||
|
||||
struct iwl_rx_packet {
|
||||
__le32 len;
|
||||
__le32 len_n_flags;
|
||||
struct iwl_cmd_header hdr;
|
||||
union {
|
||||
struct iwl3945_rx_frame rx_frame;
|
||||
|
@ -394,7 +394,8 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
|
||||
|
||||
ht_info->ht_supported = true;
|
||||
|
||||
ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
|
||||
if (priv->cfg->ht_greenfield_support)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
|
||||
ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
|
||||
ht_info->cap |= (IEEE80211_HT_CAP_SM_PS &
|
||||
(WLAN_HT_CAP_SM_PS_DISABLED << 2));
|
||||
@ -1513,7 +1514,7 @@ EXPORT_SYMBOL(iwl_irq_handle_error);
|
||||
void iwl_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
int mc_count, struct dev_addr_list *mc_list)
|
||||
u64 multicast)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
__le32 *filter_flags = &priv->staging_rxon.filter_flags;
|
||||
@ -1579,6 +1580,12 @@ int iwl_setup_mac(struct iwl_priv *priv)
|
||||
/* Firmware does not support this */
|
||||
hw->wiphy->disable_beacon_hints = true;
|
||||
|
||||
/*
|
||||
* For now, disable PS by default because it affects
|
||||
* RX performance significantly.
|
||||
*/
|
||||
hw->wiphy->ps_default = false;
|
||||
|
||||
hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
|
||||
/* we create the 802.11 header and a zero-length SSID element */
|
||||
hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
|
||||
@ -2293,10 +2300,11 @@ void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
|
||||
IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
|
||||
"notification for %s:\n",
|
||||
le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
|
||||
iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
|
||||
"notification for %s:\n", len,
|
||||
get_cmd_string(pkt->hdr.cmd));
|
||||
iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);
|
||||
|
||||
@ -2391,39 +2399,10 @@ static void iwl_ht_conf(struct iwl_priv *priv,
|
||||
}
|
||||
ht_conf = &sta->ht_cap;
|
||||
|
||||
if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
|
||||
iwl_conf->sgf |= HT_SHORT_GI_20MHZ;
|
||||
if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
|
||||
iwl_conf->sgf |= HT_SHORT_GI_40MHZ;
|
||||
|
||||
iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
|
||||
iwl_conf->max_amsdu_size =
|
||||
!!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
|
||||
|
||||
iwl_conf->supported_chan_width =
|
||||
!!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
|
||||
|
||||
/*
|
||||
* XXX: The HT configuration needs to be moved into iwl_mac_config()
|
||||
* to be done there correctly.
|
||||
*/
|
||||
|
||||
iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
|
||||
if (conf_is_ht40_minus(&priv->hw->conf))
|
||||
iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
|
||||
else if (conf_is_ht40_plus(&priv->hw->conf))
|
||||
iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
|
||||
|
||||
/* If no above or below channel supplied disable HT40 channel */
|
||||
if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE &&
|
||||
iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW)
|
||||
iwl_conf->supported_chan_width = 0;
|
||||
|
||||
iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2);
|
||||
|
||||
memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16);
|
||||
|
||||
iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0;
|
||||
iwl_conf->ht_protection =
|
||||
bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
|
||||
iwl_conf->non_GF_STA_present =
|
||||
@ -2736,6 +2715,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
struct iwl_ht_info *ht_conf = &priv->current_ht_config;
|
||||
unsigned long flags = 0;
|
||||
int ret = 0;
|
||||
u16 ch;
|
||||
@ -2777,10 +2757,32 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
goto set_ch_out;
|
||||
}
|
||||
|
||||
priv->current_ht_config.is_ht = conf_is_ht(conf);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* Configure HT40 channels */
|
||||
ht_conf->is_ht = conf_is_ht(conf);
|
||||
if (ht_conf->is_ht) {
|
||||
if (conf_is_ht40_minus(conf)) {
|
||||
ht_conf->extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_BELOW;
|
||||
ht_conf->supported_chan_width =
|
||||
IWL_CHANNEL_WIDTH_40MHZ;
|
||||
} else if (conf_is_ht40_plus(conf)) {
|
||||
ht_conf->extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
|
||||
ht_conf->supported_chan_width =
|
||||
IWL_CHANNEL_WIDTH_40MHZ;
|
||||
} else {
|
||||
ht_conf->extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_NONE;
|
||||
ht_conf->supported_chan_width =
|
||||
IWL_CHANNEL_WIDTH_20MHZ;
|
||||
}
|
||||
} else
|
||||
ht_conf->supported_chan_width = IWL_CHANNEL_WIDTH_20MHZ;
|
||||
/* Default to no protection. Protection mode will later be set
|
||||
* from BSS config in iwl_ht_conf */
|
||||
ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
|
||||
|
||||
/* if we are switching from ht to 2.4 clear flags
|
||||
* from any ht related info since 2.4 does not
|
||||
|
@ -209,6 +209,8 @@ struct iwl_mod_params {
|
||||
* @ucode_api_max: Highest version of uCode API supported by driver.
|
||||
* @ucode_api_min: Lowest version of uCode API supported by driver.
|
||||
* @pa_type: used by 6000 series only to identify the type of Power Amplifier
|
||||
* @max_ll_items: max number of OTP blocks
|
||||
* @shadow_ram_support: shadow support for OTP memory
|
||||
*
|
||||
* We enable the driver to be backward compatible wrt API version. The
|
||||
* driver specifies which APIs it supports (with @ucode_api_max being the
|
||||
@ -247,6 +249,9 @@ struct iwl_cfg {
|
||||
bool need_pll_cfg;
|
||||
bool use_isr_legacy;
|
||||
enum iwl_pa_type pa_type;
|
||||
const u16 max_ll_items;
|
||||
const bool shadow_ram_support;
|
||||
const bool ht_greenfield_support;
|
||||
};
|
||||
|
||||
/***************************
|
||||
@ -277,8 +282,7 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv,
|
||||
void iwl_irq_handle_error(struct iwl_priv *priv);
|
||||
void iwl_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
int mc_count, struct dev_addr_list *mc_list);
|
||||
unsigned int *total_flags, u64 multicast);
|
||||
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);
|
||||
|
@ -507,15 +507,9 @@ struct iwl_ht_info {
|
||||
u8 is_ht;
|
||||
u8 supported_chan_width;
|
||||
u8 sm_ps;
|
||||
u8 is_green_field;
|
||||
u8 sgf; /* HT_SHORT_GI_* short guard interval */
|
||||
u8 max_amsdu_size;
|
||||
u8 ampdu_factor;
|
||||
u8 mpdu_density;
|
||||
struct ieee80211_mcs_info mcs;
|
||||
/* BSS related data */
|
||||
u8 extension_chan_offset;
|
||||
u8 tx_chan_width;
|
||||
u8 ht_protection;
|
||||
u8 non_GF_STA_present;
|
||||
};
|
||||
@ -732,9 +726,6 @@ struct iwl_dma_ptr {
|
||||
size_t size;
|
||||
};
|
||||
|
||||
#define HT_SHORT_GI_20MHZ (1 << 0)
|
||||
#define HT_SHORT_GI_40MHZ (1 << 1)
|
||||
|
||||
#define IWL_CHANNEL_WIDTH_20MHZ 0
|
||||
#define IWL_CHANNEL_WIDTH_40MHZ 1
|
||||
|
||||
@ -888,6 +879,17 @@ enum iwl_nvm_type {
|
||||
NVM_DEVICE_TYPE_OTP,
|
||||
};
|
||||
|
||||
/*
|
||||
* Two types of OTP memory access modes
|
||||
* IWL_OTP_ACCESS_ABSOLUTE - absolute address mode,
|
||||
* based on physical memory addressing
|
||||
* IWL_OTP_ACCESS_RELATIVE - relative address mode,
|
||||
* based on logical memory addressing
|
||||
*/
|
||||
enum iwl_access_mode {
|
||||
IWL_OTP_ACCESS_ABSOLUTE,
|
||||
IWL_OTP_ACCESS_RELATIVE,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_pa_type - Power Amplifier type
|
||||
|
@ -152,6 +152,19 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv)
|
||||
}
|
||||
EXPORT_SYMBOL(iwlcore_eeprom_verify_signature);
|
||||
|
||||
static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode)
|
||||
{
|
||||
u32 otpgp;
|
||||
|
||||
otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
|
||||
if (mode == IWL_OTP_ACCESS_ABSOLUTE)
|
||||
iwl_clear_bit(priv, CSR_OTP_GP_REG,
|
||||
CSR_OTP_GP_REG_OTP_ACCESS_MODE);
|
||||
else
|
||||
iwl_set_bit(priv, CSR_OTP_GP_REG,
|
||||
CSR_OTP_GP_REG_OTP_ACCESS_MODE);
|
||||
}
|
||||
|
||||
static int iwlcore_get_nvm_type(struct iwl_priv *priv)
|
||||
{
|
||||
u32 otpgp;
|
||||
@ -252,6 +265,124 @@ static int iwl_init_otp_access(struct iwl_priv *priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 r;
|
||||
u32 otpgp;
|
||||
|
||||
_iwl_write32(priv, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
|
||||
ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
IWL_EEPROM_ACCESS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
IWL_ERR(priv, "Time out reading OTP[%d]\n", addr);
|
||||
return ret;
|
||||
}
|
||||
r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
|
||||
/* check for ECC errors: */
|
||||
otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
|
||||
if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
|
||||
/* stop in this case */
|
||||
/* set the uncorrectable OTP ECC bit for acknowledgement */
|
||||
iwl_set_bit(priv, CSR_OTP_GP_REG,
|
||||
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
|
||||
IWL_ERR(priv, "Uncorrectable OTP ECC error, abort OTP read\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
|
||||
/* continue in this case */
|
||||
/* set the correctable OTP ECC bit for acknowledgement */
|
||||
iwl_set_bit(priv, CSR_OTP_GP_REG,
|
||||
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
|
||||
IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
|
||||
}
|
||||
*eeprom_data = le16_to_cpu((__force __le16)(r >> 16));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* iwl_is_otp_empty: check for empty OTP
|
||||
*/
|
||||
static bool iwl_is_otp_empty(struct iwl_priv *priv)
|
||||
{
|
||||
u16 next_link_addr = 0, link_value;
|
||||
bool is_empty = false;
|
||||
|
||||
/* locate the beginning of OTP link list */
|
||||
if (!iwl_read_otp_word(priv, next_link_addr, &link_value)) {
|
||||
if (!link_value) {
|
||||
IWL_ERR(priv, "OTP is empty\n");
|
||||
is_empty = true;
|
||||
}
|
||||
} else {
|
||||
IWL_ERR(priv, "Unable to read first block of OTP list.\n");
|
||||
is_empty = true;
|
||||
}
|
||||
|
||||
return is_empty;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* iwl_find_otp_image: find EEPROM image in OTP
|
||||
* finding the OTP block that contains the EEPROM image.
|
||||
* the last valid block on the link list (the block _before_ the last block)
|
||||
* is the block we should read and used to configure the device.
|
||||
* If all the available OTP blocks are full, the last block will be the block
|
||||
* we should read and used to configure the device.
|
||||
* only perform this operation if shadow RAM is disabled
|
||||
*/
|
||||
static int iwl_find_otp_image(struct iwl_priv *priv,
|
||||
u16 *validblockaddr)
|
||||
{
|
||||
u16 next_link_addr = 0, link_value = 0, valid_addr;
|
||||
int ret = 0;
|
||||
int usedblocks = 0;
|
||||
|
||||
/* set addressing mode to absolute to traverse the link list */
|
||||
iwl_set_otp_access(priv, IWL_OTP_ACCESS_ABSOLUTE);
|
||||
|
||||
/* checking for empty OTP or error */
|
||||
if (iwl_is_otp_empty(priv))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* start traverse link list
|
||||
* until reach the max number of OTP blocks
|
||||
* different devices have different number of OTP blocks
|
||||
*/
|
||||
do {
|
||||
/* save current valid block address
|
||||
* check for more block on the link list
|
||||
*/
|
||||
valid_addr = next_link_addr;
|
||||
next_link_addr = link_value;
|
||||
IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n",
|
||||
usedblocks, next_link_addr);
|
||||
if (iwl_read_otp_word(priv, next_link_addr, &link_value))
|
||||
return -EINVAL;
|
||||
if (!link_value) {
|
||||
/*
|
||||
* reach the end of link list,
|
||||
* set address point to the starting address
|
||||
* of the image
|
||||
*/
|
||||
goto done;
|
||||
}
|
||||
/* more in the link list, continue */
|
||||
usedblocks++;
|
||||
} while (usedblocks < priv->cfg->max_ll_items);
|
||||
/* OTP full, use last block */
|
||||
IWL_DEBUG_INFO(priv, "OTP is full, use last block\n");
|
||||
done:
|
||||
*validblockaddr = valid_addr;
|
||||
/* skip first 2 bytes (link list pointer) */
|
||||
*validblockaddr += 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_eeprom_init - read EEPROM contents
|
||||
*
|
||||
@ -266,15 +397,14 @@ int iwl_eeprom_init(struct iwl_priv *priv)
|
||||
int sz;
|
||||
int ret;
|
||||
u16 addr;
|
||||
u32 otpgp;
|
||||
u16 validblockaddr = 0;
|
||||
u16 cache_addr = 0;
|
||||
|
||||
priv->nvm_device_type = iwlcore_get_nvm_type(priv);
|
||||
if (priv->nvm_device_type == -ENOENT)
|
||||
return -ENOENT;
|
||||
/* allocate eeprom */
|
||||
if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
|
||||
priv->cfg->eeprom_size =
|
||||
OTP_BLOCK_SIZE * OTP_LOWER_BLOCKS_TOTAL;
|
||||
IWL_DEBUG_INFO(priv, "NVM size = %d\n", priv->cfg->eeprom_size);
|
||||
sz = priv->cfg->eeprom_size;
|
||||
priv->eeprom = kzalloc(sz, GFP_KERNEL);
|
||||
if (!priv->eeprom) {
|
||||
@ -302,46 +432,31 @@ int iwl_eeprom_init(struct iwl_priv *priv)
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Failed to initialize OTP access.\n");
|
||||
ret = -ENOENT;
|
||||
goto err;
|
||||
goto done;
|
||||
}
|
||||
_iwl_write32(priv, CSR_EEPROM_GP,
|
||||
iwl_read32(priv, CSR_EEPROM_GP) &
|
||||
~CSR_EEPROM_GP_IF_OWNER_MSK);
|
||||
/* clear */
|
||||
_iwl_write32(priv, CSR_OTP_GP_REG,
|
||||
iwl_read32(priv, CSR_OTP_GP_REG) |
|
||||
|
||||
iwl_set_bit(priv, CSR_OTP_GP_REG,
|
||||
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
|
||||
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
|
||||
|
||||
for (addr = 0; addr < sz; addr += sizeof(u16)) {
|
||||
u32 r;
|
||||
|
||||
_iwl_write32(priv, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
|
||||
|
||||
ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
IWL_EEPROM_ACCESS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
IWL_ERR(priv, "Time out reading OTP[%d]\n", addr);
|
||||
/* traversing the linked list if no shadow ram supported */
|
||||
if (!priv->cfg->shadow_ram_support) {
|
||||
if (iwl_find_otp_image(priv, &validblockaddr)) {
|
||||
ret = -ENOENT;
|
||||
goto done;
|
||||
}
|
||||
r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
|
||||
/* check for ECC errors: */
|
||||
otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
|
||||
if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
|
||||
/* stop in this case */
|
||||
IWL_ERR(priv, "Uncorrectable OTP ECC error, Abort OTP read\n");
|
||||
}
|
||||
for (addr = validblockaddr; addr < validblockaddr + sz;
|
||||
addr += sizeof(u16)) {
|
||||
u16 eeprom_data;
|
||||
|
||||
ret = iwl_read_otp_word(priv, addr, &eeprom_data);
|
||||
if (ret)
|
||||
goto done;
|
||||
}
|
||||
if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
|
||||
/* continue in this case */
|
||||
_iwl_write32(priv, CSR_OTP_GP_REG,
|
||||
iwl_read32(priv, CSR_OTP_GP_REG) |
|
||||
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
|
||||
IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
|
||||
}
|
||||
e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
|
||||
e[cache_addr / 2] = eeprom_data;
|
||||
cache_addr += sizeof(u16);
|
||||
}
|
||||
} else {
|
||||
/* eeprom is an array of 16bit values */
|
||||
@ -484,14 +599,14 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
|
||||
? # x " " : "")
|
||||
|
||||
/**
|
||||
* iwl_set_ht40_chan_info - Copy ht40 channel info into driver's priv.
|
||||
* iwl_mod_ht40_chan_info - Copy ht40 channel info into driver's priv.
|
||||
*
|
||||
* Does not set up a command, or touch hardware.
|
||||
*/
|
||||
static int iwl_set_ht40_chan_info(struct iwl_priv *priv,
|
||||
static int iwl_mod_ht40_chan_info(struct iwl_priv *priv,
|
||||
enum ieee80211_band band, u16 channel,
|
||||
const struct iwl_eeprom_channel *eeprom_ch,
|
||||
u8 ht40_extension_channel)
|
||||
u8 clear_ht40_extension_channel)
|
||||
{
|
||||
struct iwl_channel_info *ch_info;
|
||||
|
||||
@ -523,7 +638,7 @@ static int iwl_set_ht40_chan_info(struct iwl_priv *priv,
|
||||
ch_info->ht40_min_power = 0;
|
||||
ch_info->ht40_scan_power = eeprom_ch->max_power_avg;
|
||||
ch_info->ht40_flags = eeprom_ch->flags;
|
||||
ch_info->ht40_extension_channel = ht40_extension_channel;
|
||||
ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -592,8 +707,7 @@ int iwl_init_channel_map(struct iwl_priv *priv)
|
||||
/* First write that ht40 is not enabled, and then enable
|
||||
* one by one */
|
||||
ch_info->ht40_extension_channel =
|
||||
(IEEE80211_CHAN_NO_HT40PLUS |
|
||||
IEEE80211_CHAN_NO_HT40MINUS);
|
||||
IEEE80211_CHAN_NO_HT40;
|
||||
|
||||
if (!(is_channel_valid(ch_info))) {
|
||||
IWL_DEBUG_INFO(priv, "Ch. %d Flags %x [%sGHz] - "
|
||||
@ -652,7 +766,6 @@ int iwl_init_channel_map(struct iwl_priv *priv)
|
||||
/* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */
|
||||
for (band = 6; band <= 7; band++) {
|
||||
enum ieee80211_band ieeeband;
|
||||
u8 ht40_extension_chan;
|
||||
|
||||
iwl_init_band_reference(priv, band, &eeprom_ch_count,
|
||||
&eeprom_ch_info, &eeprom_ch_index);
|
||||
@ -663,28 +776,17 @@ int iwl_init_channel_map(struct iwl_priv *priv)
|
||||
|
||||
/* Loop through each band adding each of the channels */
|
||||
for (ch = 0; ch < eeprom_ch_count; ch++) {
|
||||
|
||||
if ((band == 6) &&
|
||||
((eeprom_ch_index[ch] == 5) ||
|
||||
(eeprom_ch_index[ch] == 6) ||
|
||||
(eeprom_ch_index[ch] == 7)))
|
||||
/* both are allowed: above and below */
|
||||
ht40_extension_chan = 0;
|
||||
else
|
||||
ht40_extension_chan =
|
||||
IEEE80211_CHAN_NO_HT40MINUS;
|
||||
|
||||
/* Set up driver's info for lower half */
|
||||
iwl_set_ht40_chan_info(priv, ieeeband,
|
||||
iwl_mod_ht40_chan_info(priv, ieeeband,
|
||||
eeprom_ch_index[ch],
|
||||
&(eeprom_ch_info[ch]),
|
||||
ht40_extension_chan);
|
||||
&eeprom_ch_info[ch],
|
||||
IEEE80211_CHAN_NO_HT40PLUS);
|
||||
|
||||
/* Set up driver's info for upper half */
|
||||
iwl_set_ht40_chan_info(priv, ieeeband,
|
||||
(eeprom_ch_index[ch] + 4),
|
||||
&(eeprom_ch_info[ch]),
|
||||
IEEE80211_CHAN_NO_HT40PLUS);
|
||||
iwl_mod_ht40_chan_info(priv, ieeeband,
|
||||
eeprom_ch_index[ch] + 4,
|
||||
&eeprom_ch_info[ch],
|
||||
IEEE80211_CHAN_NO_HT40MINUS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,8 +180,14 @@ struct iwl_eeprom_channel {
|
||||
#define EEPROM_5050_EEPROM_VERSION (0x21E)
|
||||
|
||||
/* OTP */
|
||||
#define OTP_LOWER_BLOCKS_TOTAL (3)
|
||||
#define OTP_BLOCK_SIZE (0x400)
|
||||
/* lower blocks contain EEPROM image and calibration data */
|
||||
#define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */
|
||||
/* high blocks contain PAPD data */
|
||||
#define OTP_HIGH_IMAGE_SIZE_6x00 (6 * 512 * sizeof(u16)) /* 6 KB */
|
||||
#define OTP_HIGH_IMAGE_SIZE_1000 (0x200 * sizeof(u16)) /* 1024 bytes */
|
||||
#define OTP_MAX_LL_ITEMS_1000 (3) /* OTP blocks for 1000 */
|
||||
#define OTP_MAX_LL_ITEMS_6x00 (4) /* OTP blocks for 6x00 */
|
||||
#define OTP_MAX_LL_ITEMS_6x50 (7) /* OTP blocks for 6x50 */
|
||||
|
||||
/* 2.4 GHz */
|
||||
extern const u8 iwl_eeprom_band_1[14];
|
||||
|
@ -539,7 +539,8 @@ void iwl_rx_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
|
||||
IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
|
||||
(int)sizeof(priv->statistics), pkt->len);
|
||||
(int)sizeof(priv->statistics),
|
||||
le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
|
||||
|
||||
change = ((priv->statistics.general.temperature !=
|
||||
pkt->u.stats.general.temperature) ||
|
||||
@ -853,61 +854,12 @@ static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
|
||||
}
|
||||
|
||||
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 ieee80211_hdr *hdr,
|
||||
u16 len,
|
||||
u32 ampdu_status,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct ieee80211_rx_status *stats)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_phy_res *rx_start = (include_phy) ?
|
||||
(struct iwl_rx_phy_res *)&(pkt->u.raw[0]) : NULL;
|
||||
struct ieee80211_hdr *hdr;
|
||||
u16 len;
|
||||
__le32 *rx_end;
|
||||
unsigned int skblen;
|
||||
u32 ampdu_status;
|
||||
u32 ampdu_status_legacy;
|
||||
|
||||
if (!include_phy && priv->last_phy_res[0])
|
||||
rx_start = (struct iwl_rx_phy_res *)&priv->last_phy_res[1];
|
||||
|
||||
if (!rx_start) {
|
||||
IWL_ERR(priv, "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 iwl_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(priv,
|
||||
@ -915,13 +867,15 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
|
||||
return;
|
||||
}
|
||||
|
||||
hdr = (struct ieee80211_hdr *)rxb->skb->data;
|
||||
|
||||
/* in case of HW accelerated crypto and bad decryption, drop */
|
||||
/* In case of HW accelerated crypto and bad decryption, drop */
|
||||
if (!priv->cfg->mod_params->sw_crypto &&
|
||||
iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
|
||||
return;
|
||||
|
||||
/* Resize SKB from mac header to end of packet */
|
||||
skb_reserve(rxb->skb, (void *)hdr - (void *)rxb->skb->data);
|
||||
skb_put(rxb->skb, len);
|
||||
|
||||
iwl_update_stats(priv, false, hdr->frame_control, len);
|
||||
memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
|
||||
ieee80211_rx_irqsafe(priv->hw, rxb->skb);
|
||||
@ -955,25 +909,66 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
|
||||
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 iwl_rx_phy_res *rx_start = (include_phy) ?
|
||||
(struct iwl_rx_phy_res *)&(pkt->u.raw[0]) :
|
||||
(struct iwl_rx_phy_res *)&priv->last_phy_res[1];
|
||||
__le32 *rx_end;
|
||||
unsigned int len = 0;
|
||||
struct iwl_rx_phy_res *phy_res;
|
||||
__le32 rx_pkt_status;
|
||||
struct iwl4965_rx_mpdu_res_start *amsdu;
|
||||
u32 len;
|
||||
u32 ampdu_status;
|
||||
u16 fc;
|
||||
u8 network_packet;
|
||||
|
||||
rx_status.mactime = le64_to_cpu(rx_start->timestamp);
|
||||
/**
|
||||
* REPLY_RX and REPLY_RX_MPDU_CMD are handled differently.
|
||||
* REPLY_RX: physical layer info is in this buffer
|
||||
* REPLY_RX_MPDU_CMD: physical layer info was sent in separate
|
||||
* command and cached in priv->last_phy_res
|
||||
*
|
||||
* Here we set up local variables depending on which command is
|
||||
* received.
|
||||
*/
|
||||
if (pkt->hdr.cmd == REPLY_RX) {
|
||||
phy_res = (struct iwl_rx_phy_res *)pkt->u.raw;
|
||||
header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res)
|
||||
+ phy_res->cfg_phy_cnt);
|
||||
|
||||
len = le16_to_cpu(phy_res->byte_count);
|
||||
rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) +
|
||||
phy_res->cfg_phy_cnt + len);
|
||||
ampdu_status = le32_to_cpu(rx_pkt_status);
|
||||
} else {
|
||||
if (!priv->last_phy_res[0]) {
|
||||
IWL_ERR(priv, "MPDU frame without cached PHY data\n");
|
||||
return;
|
||||
}
|
||||
phy_res = (struct iwl_rx_phy_res *)&priv->last_phy_res[1];
|
||||
amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw;
|
||||
header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
|
||||
len = le16_to_cpu(amsdu->byte_count);
|
||||
rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len);
|
||||
ampdu_status = iwl_translate_rx_status(priv,
|
||||
le32_to_cpu(rx_pkt_status));
|
||||
}
|
||||
|
||||
if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
|
||||
IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
|
||||
phy_res->cfg_phy_cnt);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
|
||||
!(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
|
||||
IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n",
|
||||
le32_to_cpu(rx_pkt_status));
|
||||
return;
|
||||
}
|
||||
|
||||
/* rx_status carries information about the packet to mac80211 */
|
||||
rx_status.mactime = le64_to_cpu(phy_res->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_channel_to_frequency(le16_to_cpu(phy_res->channel));
|
||||
rx_status.band = (phy_res->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));
|
||||
iwl_hwrate_to_plcp_idx(le32_to_cpu(phy_res->rate_n_flags));
|
||||
if (rx_status.band == IEEE80211_BAND_5GHZ)
|
||||
rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
|
||||
|
||||
@ -983,54 +978,10 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
|
||||
* this W/A doesn't propagate it to the mac80211 */
|
||||
/*rx_status.flag |= RX_FLAG_TSFT;*/
|
||||
|
||||
if ((unlikely(rx_start->cfg_phy_cnt > 20))) {
|
||||
IWL_DEBUG_DROP(priv, "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 iwl_rx_phy_res *)
|
||||
&priv->last_phy_res[1];
|
||||
else
|
||||
rx_start = NULL;
|
||||
}
|
||||
|
||||
if (!rx_start) {
|
||||
IWL_ERR(priv, "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 iwl_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(priv, "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);
|
||||
priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
|
||||
|
||||
/* Find max signal strength (dBm) among 3 antenna/receiver chains */
|
||||
rx_status.signal = iwl_calc_rssi(priv, rx_start);
|
||||
rx_status.signal = iwl_calc_rssi(priv, phy_res);
|
||||
|
||||
/* Meaningful noise values are available only from beacon statistics,
|
||||
* which are gathered only when associated, and indicate noise
|
||||
@ -1050,10 +1001,10 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
|
||||
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 */
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
/* Set "1" to report good data frames in groups of 100 */
|
||||
if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX))
|
||||
iwl_dbg_report_frame(priv, rx_start, len, header, 1);
|
||||
iwl_dbg_report_frame(priv, phy_res, len, header, 1);
|
||||
#endif
|
||||
iwl_dbg_log_rx_data_frame(priv, len, header);
|
||||
IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n",
|
||||
@ -1073,18 +1024,18 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
|
||||
* new 802.11n radiotap field "RX chains" that is defined
|
||||
* as a bitmask.
|
||||
*/
|
||||
rx_status.antenna = le16_to_cpu(rx_start->phy_flags &
|
||||
RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
|
||||
rx_status.antenna =
|
||||
le16_to_cpu(phy_res->phy_flags & RX_RES_PHY_FLAGS_ANTENNA_MSK)
|
||||
>> RX_RES_PHY_FLAGS_ANTENNA_POS;
|
||||
|
||||
/* set the preamble flag if appropriate */
|
||||
if (rx_start->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
|
||||
if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
|
||||
rx_status.flag |= RX_FLAG_SHORTPRE;
|
||||
|
||||
network_packet = iwl_is_network_packet(priv, header);
|
||||
if (network_packet) {
|
||||
if (iwl_is_network_packet(priv, header)) {
|
||||
priv->last_rx_rssi = rx_status.signal;
|
||||
priv->last_beacon_time = priv->ucode_beacon_time;
|
||||
priv->last_tsf = le64_to_cpu(rx_start->timestamp);
|
||||
priv->last_tsf = le64_to_cpu(phy_res->timestamp);
|
||||
}
|
||||
|
||||
fc = le16_to_cpu(header->frame_control);
|
||||
@ -1096,8 +1047,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
|
||||
header->addr2);
|
||||
/* fall through */
|
||||
default:
|
||||
iwl_pass_packet_to_mac80211(priv, include_phy, rxb,
|
||||
&rx_status);
|
||||
iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status,
|
||||
rxb, &rx_status);
|
||||
break;
|
||||
|
||||
}
|
||||
|
@ -745,6 +745,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
if (ieee80211_is_data_qos(fc)) {
|
||||
qc = ieee80211_get_qos_ctl(hdr);
|
||||
tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
|
||||
if (unlikely(tid >= MAX_TID_COUNT))
|
||||
goto drop_unlock;
|
||||
seq_number = priv->stations[sta_id].tid[tid].seq_number;
|
||||
seq_number &= IEEE80211_SCTL_SEQ;
|
||||
hdr->seq_ctrl = hdr->seq_ctrl &
|
||||
@ -1238,6 +1240,9 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (unlikely(tid >= MAX_TID_COUNT))
|
||||
return -EINVAL;
|
||||
|
||||
if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo)))
|
||||
tx_fifo_id = default_tid_to_tx_fifo[tid];
|
||||
else
|
||||
|
@ -544,6 +544,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
if (ieee80211_is_data_qos(fc)) {
|
||||
qc = ieee80211_get_qos_ctl(hdr);
|
||||
tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
|
||||
if (unlikely(tid >= MAX_TID_COUNT))
|
||||
goto drop;
|
||||
seq_number = priv->stations[sta_id].tid[tid].seq_number &
|
||||
IEEE80211_SCTL_SEQ;
|
||||
hdr->seq_ctrl = cpu_to_le16(seq_number) |
|
||||
|
@ -45,9 +45,14 @@ static int get_common_rates(struct lbs_private *priv,
|
||||
u8 *card_rates = lbs_bg_rates;
|
||||
size_t num_card_rates = sizeof(lbs_bg_rates);
|
||||
int ret = 0, i, j;
|
||||
u8 tmp[30];
|
||||
u8 *tmp;
|
||||
size_t tmp_size = 0;
|
||||
|
||||
tmp = kzalloc((ARRAY_SIZE(lbs_bg_rates) - 1) * (*rates_size - 1),
|
||||
GFP_KERNEL);
|
||||
if (!tmp)
|
||||
return -1;
|
||||
|
||||
/* For each rate in card_rates that exists in rate1, copy to tmp */
|
||||
for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
|
||||
for (j = 0; rates[j] && (j < *rates_size); j++) {
|
||||
@ -77,6 +82,7 @@ static int get_common_rates(struct lbs_private *priv,
|
||||
memset(rates, 0, *rates_size);
|
||||
*rates_size = min_t(int, tmp_size, *rates_size);
|
||||
memcpy(rates, tmp, *rates_size);
|
||||
kfree(tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -366,15 +366,35 @@ static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 lbtf_op_prepare_multicast(struct ieee80211_hw *hw,
|
||||
int mc_count, struct dev_addr_list *mclist)
|
||||
{
|
||||
struct lbtf_private *priv = hw->priv;
|
||||
int i;
|
||||
|
||||
if (!mc_count || mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE)
|
||||
return mc_count;
|
||||
|
||||
priv->nr_of_multicastmacaddr = mc_count;
|
||||
for (i = 0; i < mc_count; i++) {
|
||||
if (!mclist)
|
||||
break;
|
||||
memcpy(&priv->multicastlist[i], mclist->da_addr,
|
||||
ETH_ALEN);
|
||||
mclist = mclist->next;
|
||||
}
|
||||
|
||||
return mc_count;
|
||||
}
|
||||
|
||||
#define SUPPORTED_FIF_FLAGS (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)
|
||||
static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *new_flags,
|
||||
int mc_count, struct dev_mc_list *mclist)
|
||||
u64 multicast)
|
||||
{
|
||||
struct lbtf_private *priv = hw->priv;
|
||||
int old_mac_control = priv->mac_control;
|
||||
int i;
|
||||
changed_flags &= SUPPORTED_FIF_FLAGS;
|
||||
*new_flags &= SUPPORTED_FIF_FLAGS;
|
||||
|
||||
@ -386,20 +406,12 @@ static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
|
||||
else
|
||||
priv->mac_control &= ~CMD_ACT_MAC_PROMISCUOUS_ENABLE;
|
||||
if (*new_flags & (FIF_ALLMULTI) ||
|
||||
mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) {
|
||||
multicast > MRVDRV_MAX_MULTICAST_LIST_SIZE) {
|
||||
priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
|
||||
priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE;
|
||||
} else if (mc_count) {
|
||||
} else if (multicast) {
|
||||
priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE;
|
||||
priv->mac_control &= ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
|
||||
priv->nr_of_multicastmacaddr = mc_count;
|
||||
for (i = 0; i < mc_count; i++) {
|
||||
if (!mclist)
|
||||
break;
|
||||
memcpy(&priv->multicastlist[i], mclist->da_addr,
|
||||
ETH_ALEN);
|
||||
mclist = mclist->next;
|
||||
}
|
||||
lbtf_cmd_set_mac_multicast_addr(priv);
|
||||
} else {
|
||||
priv->mac_control &= ~(CMD_ACT_MAC_MULTICAST_ENABLE |
|
||||
@ -461,6 +473,7 @@ static const struct ieee80211_ops lbtf_ops = {
|
||||
.add_interface = lbtf_op_add_interface,
|
||||
.remove_interface = lbtf_op_remove_interface,
|
||||
.config = lbtf_op_config,
|
||||
.prepare_multicast = lbtf_op_prepare_multicast,
|
||||
.configure_filter = lbtf_op_configure_filter,
|
||||
.bss_info_changed = lbtf_op_bss_info_changed,
|
||||
};
|
||||
|
@ -582,9 +582,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
|
||||
|
||||
static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
int mc_count,
|
||||
struct dev_addr_list *mc_list)
|
||||
unsigned int *total_flags,u64 multicast)
|
||||
{
|
||||
struct mac80211_hwsim_data *data = hw->priv;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1291,7 +1291,7 @@ static int orinoco_ioctl_setibssport(struct net_device *dev,
|
||||
if (orinoco_lock(priv, &flags) != 0)
|
||||
return -EBUSY;
|
||||
|
||||
priv->ibss_port = val ;
|
||||
priv->ibss_port = val;
|
||||
|
||||
/* Actually update the mode we are using */
|
||||
set_port_type(priv);
|
||||
|
@ -302,7 +302,7 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed)
|
||||
static void p54_configure_filter(struct ieee80211_hw *dev,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
int mc_count, struct dev_mc_list *mclist)
|
||||
u64 multicast)
|
||||
{
|
||||
struct p54_common *priv = dev->priv;
|
||||
|
||||
@ -575,6 +575,12 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
|
||||
dev->extra_tx_headroom = sizeof(struct p54_hdr) + 4 +
|
||||
sizeof(struct p54_tx_data);
|
||||
|
||||
/*
|
||||
* For now, disable PS by default because it affects
|
||||
* link stability significantly.
|
||||
*/
|
||||
dev->wiphy->ps_default = false;
|
||||
|
||||
mutex_init(&priv->conf_mutex);
|
||||
mutex_init(&priv->eeprom_mutex);
|
||||
init_completion(&priv->eeprom_comp);
|
||||
|
@ -1874,7 +1874,6 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
*/
|
||||
__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
|
||||
__set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
|
||||
__set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
|
||||
if (!modparam_nohwcrypt) {
|
||||
__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
|
||||
__set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags);
|
||||
|
@ -1463,6 +1463,10 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
/*
|
||||
* ASIC will keep garbage value after boot, clear encryption keys.
|
||||
*/
|
||||
for (i = 0; i < 4; i++)
|
||||
rt2x00usb_register_write(rt2x00dev,
|
||||
SHARED_KEY_MODE_ENTRY(i), 0);
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
u32 wcid[2] = { 0xffffffff, 0x00ffffff };
|
||||
rt2x00usb_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i),
|
||||
@ -1472,10 +1476,6 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00usb_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
rt2x00usb_register_write(rt2x00dev,
|
||||
SHARED_KEY_MODE_ENTRY(i), 0);
|
||||
|
||||
/*
|
||||
* Clear all beacons
|
||||
* For the Beacon base registers we only need to clear
|
||||
@ -1520,7 +1520,7 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00usb_register_read(rt2x00dev, LG_FBK_CFG0, ®);
|
||||
rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS0FBK, 8);
|
||||
rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS1FBK, 8);
|
||||
rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS2FBK, 3);
|
||||
rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS2FBK, 9);
|
||||
rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS3FBK, 10);
|
||||
rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS4FBK, 11);
|
||||
rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS5FBK, 12);
|
||||
@ -1995,11 +1995,11 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size);
|
||||
rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
|
||||
test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
|
||||
txdesc->key_idx : 0xff);
|
||||
(skbdesc->entry->entry_idx + 1) : 0xff);
|
||||
rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
|
||||
skb->len - txdesc->l2pad);
|
||||
rt2x00_set_field32(&word, TXWI_W1_PACKETID,
|
||||
skbdesc->entry->entry_idx);
|
||||
skbdesc->entry->queue->qid + 1);
|
||||
rt2x00_desc_write(txwi, 1, word);
|
||||
|
||||
/*
|
||||
@ -2163,8 +2163,10 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
|
||||
if (rt2x00_get_field32(rxd0, RXD_W0_MY_BSS))
|
||||
rxdesc->dev_flags |= RXDONE_MY_BSS;
|
||||
|
||||
if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD))
|
||||
if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD)) {
|
||||
rxdesc->dev_flags |= RXDONE_L2PAD;
|
||||
skbdesc->flags |= SKBDESC_L2_PADDED;
|
||||
}
|
||||
|
||||
if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI))
|
||||
rxdesc->flags |= RX_FLAG_SHORT_GI;
|
||||
@ -2632,7 +2634,6 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
* This device requires firmware.
|
||||
*/
|
||||
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
|
||||
__set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
|
||||
__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
|
||||
if (!modparam_nohwcrypt)
|
||||
__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
|
||||
|
@ -36,6 +36,9 @@
|
||||
* RF2750 2.4G/5G 1T2R
|
||||
* RF3020 2.4G 1T1R
|
||||
* RF2020 2.4G B/G
|
||||
* RF3021 2.4G 1T2R
|
||||
* RF3022 2.4G 2T2R
|
||||
* RF3052 2.4G 2T2R
|
||||
*/
|
||||
#define RF2820 0x0001
|
||||
#define RF2850 0x0002
|
||||
@ -43,6 +46,9 @@
|
||||
#define RF2750 0x0004
|
||||
#define RF3020 0x0005
|
||||
#define RF2020 0x0006
|
||||
#define RF3021 0x0007
|
||||
#define RF3022 0x0008
|
||||
#define RF3052 0x0009
|
||||
|
||||
/*
|
||||
* RT2870 version
|
||||
@ -1300,8 +1306,8 @@
|
||||
* PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry
|
||||
* MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry
|
||||
* MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry
|
||||
* SHARED_KEY_TABLE_BASE: 32-byte * 16-entry
|
||||
* SHARED_KEY_MODE_BASE: 4-byte * 16-entry
|
||||
* SHARED_KEY_TABLE_BASE: 32 bytes * 32-entry
|
||||
* SHARED_KEY_MODE_BASE: 4 bits * 32-entry
|
||||
*/
|
||||
#define MAC_WCID_BASE 0x1800
|
||||
#define PAIRWISE_KEY_TABLE_BASE 0x4000
|
||||
|
@ -350,8 +350,6 @@ struct rt2x00_intf {
|
||||
*/
|
||||
unsigned int delayed_flags;
|
||||
#define DELAYED_UPDATE_BEACON 0x00000001
|
||||
#define DELAYED_CONFIG_ERP 0x00000002
|
||||
#define DELAYED_LED_ASSOC 0x00000004
|
||||
|
||||
/*
|
||||
* Software sequence counter, this is only required
|
||||
@ -614,7 +612,6 @@ enum rt2x00_flags {
|
||||
DRIVER_REQUIRE_FIRMWARE,
|
||||
DRIVER_REQUIRE_BEACON_GUARD,
|
||||
DRIVER_REQUIRE_ATIM_QUEUE,
|
||||
DRIVER_REQUIRE_SCHEDULED,
|
||||
DRIVER_REQUIRE_DMA,
|
||||
DRIVER_REQUIRE_COPY_IV,
|
||||
DRIVER_REQUIRE_L2PAD,
|
||||
@ -826,7 +823,6 @@ struct rt2x00_dev {
|
||||
* due to RTNL locking requirements.
|
||||
*/
|
||||
struct work_struct intf_work;
|
||||
struct work_struct filter_work;
|
||||
|
||||
/*
|
||||
* Data queue arrays for RX, TX and Beacon.
|
||||
@ -978,7 +974,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed);
|
||||
void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
int mc_count, struct dev_addr_list *mc_list);
|
||||
u64 multicast);
|
||||
int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
|
||||
bool set);
|
||||
#ifdef CONFIG_RT2X00_LIB_CRYPTO
|
||||
|
@ -118,20 +118,11 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state)
|
||||
rt2x00link_start_tuner(rt2x00dev);
|
||||
}
|
||||
|
||||
static void rt2x00lib_packetfilter_scheduled(struct work_struct *work)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev =
|
||||
container_of(work, struct rt2x00_dev, filter_work);
|
||||
|
||||
rt2x00dev->ops->lib->config_filter(rt2x00dev, rt2x00dev->packet_filter);
|
||||
}
|
||||
|
||||
static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = data;
|
||||
struct rt2x00_intf *intf = vif_to_intf(vif);
|
||||
struct ieee80211_bss_conf conf;
|
||||
int delayed_flags;
|
||||
|
||||
/*
|
||||
@ -141,7 +132,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
|
||||
*/
|
||||
spin_lock(&intf->lock);
|
||||
|
||||
memcpy(&conf, &vif->bss_conf, sizeof(conf));
|
||||
delayed_flags = intf->delayed_flags;
|
||||
intf->delayed_flags = 0;
|
||||
|
||||
@ -158,12 +148,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
|
||||
|
||||
if (delayed_flags & DELAYED_UPDATE_BEACON)
|
||||
rt2x00queue_update_beacon(rt2x00dev, vif, true);
|
||||
|
||||
if (delayed_flags & DELAYED_CONFIG_ERP)
|
||||
rt2x00lib_config_erp(rt2x00dev, intf, &conf);
|
||||
|
||||
if (delayed_flags & DELAYED_LED_ASSOC)
|
||||
rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated);
|
||||
}
|
||||
|
||||
static void rt2x00lib_intf_scheduled(struct work_struct *work)
|
||||
@ -220,7 +204,8 @@ void rt2x00lib_txdone(struct queue_entry *entry,
|
||||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
|
||||
enum data_queue_qid qid = skb_get_queue_mapping(entry->skb);
|
||||
unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
|
||||
u8 rate_idx, rate_flags;
|
||||
u8 rate_idx, rate_flags, retry_rates;
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* Unmap the skb.
|
||||
@ -259,16 +244,27 @@ void rt2x00lib_txdone(struct queue_entry *entry,
|
||||
|
||||
rate_idx = skbdesc->tx_rate_idx;
|
||||
rate_flags = skbdesc->tx_rate_flags;
|
||||
retry_rates = test_bit(TXDONE_FALLBACK, &txdesc->flags) ?
|
||||
(txdesc->retry + 1) : 1;
|
||||
|
||||
/*
|
||||
* Initialize TX status
|
||||
*/
|
||||
memset(&tx_info->status, 0, sizeof(tx_info->status));
|
||||
tx_info->status.ack_signal = 0;
|
||||
tx_info->status.rates[0].idx = rate_idx;
|
||||
tx_info->status.rates[0].flags = rate_flags;
|
||||
tx_info->status.rates[0].count = txdesc->retry + 1;
|
||||
tx_info->status.rates[1].idx = -1; /* terminate */
|
||||
|
||||
/*
|
||||
* Frame was send with retries, hardware tried
|
||||
* different rates to send out the frame, at each
|
||||
* retry it lowered the rate 1 step.
|
||||
*/
|
||||
for (i = 0; i < retry_rates && i < IEEE80211_TX_MAX_RATES; i++) {
|
||||
tx_info->status.rates[i].idx = rate_idx - i;
|
||||
tx_info->status.rates[i].flags = rate_flags;
|
||||
tx_info->status.rates[i].count = 1;
|
||||
}
|
||||
if (i < (IEEE80211_TX_MAX_RATES -1))
|
||||
tx_info->status.rates[i].idx = -1; /* terminate */
|
||||
|
||||
if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
|
||||
if (test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
|
||||
@ -847,7 +843,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
|
||||
* Initialize configuration work.
|
||||
*/
|
||||
INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
|
||||
INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled);
|
||||
|
||||
/*
|
||||
* Allocate queue array.
|
||||
@ -895,7 +890,6 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
|
||||
/*
|
||||
* Stop all work.
|
||||
*/
|
||||
cancel_work_sync(&rt2x00dev->filter_work);
|
||||
cancel_work_sync(&rt2x00dev->intf_work);
|
||||
|
||||
/*
|
||||
|
@ -379,7 +379,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_config);
|
||||
void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
int mc_count, struct dev_addr_list *mc_list)
|
||||
u64 multicast)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
|
||||
@ -430,10 +430,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
|
||||
return;
|
||||
rt2x00dev->packet_filter = *total_flags;
|
||||
|
||||
if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
|
||||
rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
|
||||
else
|
||||
ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->filter_work);
|
||||
rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
|
||||
|
||||
@ -639,23 +636,15 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
|
||||
else
|
||||
rt2x00dev->intf_associated--;
|
||||
|
||||
if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
|
||||
rt2x00leds_led_assoc(rt2x00dev,
|
||||
!!rt2x00dev->intf_associated);
|
||||
else
|
||||
delayed |= DELAYED_LED_ASSOC;
|
||||
rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated);
|
||||
}
|
||||
|
||||
/*
|
||||
* When the erp information has changed, we should perform
|
||||
* additional configuration steps. For all other changes we are done.
|
||||
*/
|
||||
if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) {
|
||||
if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
|
||||
rt2x00lib_config_erp(rt2x00dev, intf, bss_conf);
|
||||
else
|
||||
delayed |= DELAYED_CONFIG_ERP;
|
||||
}
|
||||
if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT))
|
||||
rt2x00lib_config_erp(rt2x00dev, intf, bss_conf);
|
||||
|
||||
spin_lock(&intf->lock);
|
||||
if (delayed) {
|
||||
@ -704,8 +693,8 @@ EXPORT_SYMBOL_GPL(rt2x00mac_conf_tx);
|
||||
void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
bool blocked = !!rt2x00dev->ops->lib->rfkill_poll(rt2x00dev);
|
||||
bool active = !!rt2x00dev->ops->lib->rfkill_poll(rt2x00dev);
|
||||
|
||||
wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
|
||||
wiphy_rfkill_set_hw_state(hw->wiphy, !active);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll);
|
||||
|
@ -214,6 +214,7 @@ struct rxdone_entry_desc {
|
||||
*
|
||||
* @TXDONE_UNKNOWN: Hardware could not determine success of transmission.
|
||||
* @TXDONE_SUCCESS: Frame was successfully send
|
||||
* @TXDONE_FALLBACK: Frame was successfully send using a fallback rate.
|
||||
* @TXDONE_FAILURE: Frame was not successfully send
|
||||
* @TXDONE_EXCESSIVE_RETRY: In addition to &TXDONE_FAILURE, the
|
||||
* frame transmission failed due to excessive retries.
|
||||
@ -221,6 +222,7 @@ struct rxdone_entry_desc {
|
||||
enum txdone_entry_desc_flags {
|
||||
TXDONE_UNKNOWN,
|
||||
TXDONE_SUCCESS,
|
||||
TXDONE_FALLBACK,
|
||||
TXDONE_FAILURE,
|
||||
TXDONE_EXCESSIVE_RETRY,
|
||||
};
|
||||
|
@ -2151,7 +2151,6 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
* This device requires firmware.
|
||||
*/
|
||||
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
|
||||
__set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
|
||||
if (!modparam_nohwcrypt)
|
||||
__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
|
||||
|
||||
|
@ -728,10 +728,16 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev,
|
||||
priv->rf->conf_erp(dev, info);
|
||||
}
|
||||
|
||||
static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, int mc_count,
|
||||
struct dev_addr_list *mc_list)
|
||||
{
|
||||
return mc_count;
|
||||
}
|
||||
|
||||
static void rtl8180_configure_filter(struct ieee80211_hw *dev,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
int mc_count, struct dev_addr_list *mclist)
|
||||
u64 multicast)
|
||||
{
|
||||
struct rtl8180_priv *priv = dev->priv;
|
||||
|
||||
@ -741,7 +747,7 @@ static void rtl8180_configure_filter(struct ieee80211_hw *dev,
|
||||
priv->rx_conf ^= RTL818X_RX_CONF_CTRL;
|
||||
if (changed_flags & FIF_OTHER_BSS)
|
||||
priv->rx_conf ^= RTL818X_RX_CONF_MONITOR;
|
||||
if (*total_flags & FIF_ALLMULTI || mc_count > 0)
|
||||
if (*total_flags & FIF_ALLMULTI || multicast > 0)
|
||||
priv->rx_conf |= RTL818X_RX_CONF_MULTICAST;
|
||||
else
|
||||
priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST;
|
||||
@ -768,6 +774,7 @@ static const struct ieee80211_ops rtl8180_ops = {
|
||||
.remove_interface = rtl8180_remove_interface,
|
||||
.config = rtl8180_config,
|
||||
.bss_info_changed = rtl8180_bss_info_changed,
|
||||
.prepare_multicast = rtl8180_prepare_multicast,
|
||||
.configure_filter = rtl8180_configure_filter,
|
||||
};
|
||||
|
||||
|
@ -1192,10 +1192,16 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev,
|
||||
info->use_short_preamble);
|
||||
}
|
||||
|
||||
static u64 rtl8187_prepare_multicast(struct ieee80211_hw *dev,
|
||||
int mc_count, struct dev_addr_list *mc_list)
|
||||
{
|
||||
return mc_count;
|
||||
}
|
||||
|
||||
static void rtl8187_configure_filter(struct ieee80211_hw *dev,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
int mc_count, struct dev_addr_list *mclist)
|
||||
u64 multicast)
|
||||
{
|
||||
struct rtl8187_priv *priv = dev->priv;
|
||||
|
||||
@ -1205,7 +1211,7 @@ static void rtl8187_configure_filter(struct ieee80211_hw *dev,
|
||||
priv->rx_conf ^= RTL818X_RX_CONF_CTRL;
|
||||
if (changed_flags & FIF_OTHER_BSS)
|
||||
priv->rx_conf ^= RTL818X_RX_CONF_MONITOR;
|
||||
if (*total_flags & FIF_ALLMULTI || mc_count > 0)
|
||||
if (*total_flags & FIF_ALLMULTI || multicast > 0)
|
||||
priv->rx_conf |= RTL818X_RX_CONF_MULTICAST;
|
||||
else
|
||||
priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST;
|
||||
@ -1268,6 +1274,7 @@ static const struct ieee80211_ops rtl8187_ops = {
|
||||
.remove_interface = rtl8187_remove_interface,
|
||||
.config = rtl8187_config,
|
||||
.bss_info_changed = rtl8187_bss_info_changed,
|
||||
.prepare_multicast = rtl8187_prepare_multicast,
|
||||
.configure_filter = rtl8187_configure_filter,
|
||||
.conf_tx = rtl8187_conf_tx
|
||||
};
|
||||
|
@ -465,6 +465,9 @@ int wl1251_boot(struct wl1251 *wl)
|
||||
int ret = 0, minor_minor_e2_ver;
|
||||
u32 tmp, boot_data;
|
||||
|
||||
/* halt embedded ARM CPU while loading firmware */
|
||||
wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, ECPU_CONTROL_HALT);
|
||||
|
||||
ret = wl1251_boot_soft_reset(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
@ -652,9 +652,7 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
|
||||
static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed,
|
||||
unsigned int *total,
|
||||
int mc_count,
|
||||
struct dev_addr_list *mc_list)
|
||||
unsigned int *total,u64 multicast)
|
||||
{
|
||||
struct wl1251 *wl = hw->priv;
|
||||
|
||||
|
@ -245,8 +245,8 @@ enum wl12xx_acx_int_reg {
|
||||
ACX_REG_TABLE_LEN
|
||||
};
|
||||
|
||||
#define ACX_SLV_SOFT_RESET_BIT BIT(1)
|
||||
#define ACX_REG_EEPROM_START_BIT BIT(1)
|
||||
#define ACX_SLV_SOFT_RESET_BIT BIT(0)
|
||||
#define ACX_REG_EEPROM_START_BIT BIT(0)
|
||||
|
||||
/* Command/Information Mailbox Pointers */
|
||||
|
||||
|
@ -605,11 +605,10 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %s",
|
||||
conf->type, print_mac(mac, conf->mac_addr));
|
||||
wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
|
||||
conf->type, conf->mac_addr);
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
@ -793,9 +792,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
|
||||
static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed,
|
||||
unsigned int *total,
|
||||
int mc_count,
|
||||
struct dev_addr_list *mc_list)
|
||||
unsigned int *total,u64 multicast)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
|
||||
|
@ -796,18 +796,40 @@ static void set_rx_filter_handler(struct work_struct *work)
|
||||
dev_err(zd_mac_dev(mac), "set_rx_filter_handler error %d\n", r);
|
||||
}
|
||||
|
||||
static u64 zd_op_prepare_multicast(struct ieee80211_hw *hw,
|
||||
int mc_count, struct dev_addr_list *mclist)
|
||||
{
|
||||
struct zd_mac *mac = zd_hw_mac(hw);
|
||||
struct zd_mc_hash hash;
|
||||
int i;
|
||||
|
||||
zd_mc_clear(&hash);
|
||||
|
||||
for (i = 0; i < mc_count; i++) {
|
||||
if (!mclist)
|
||||
break;
|
||||
dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n", mclist->dmi_addr);
|
||||
zd_mc_add_addr(&hash, mclist->dmi_addr);
|
||||
mclist = mclist->next;
|
||||
}
|
||||
|
||||
return hash.low | ((u64)hash.high << 32);
|
||||
}
|
||||
|
||||
#define SUPPORTED_FIF_FLAGS \
|
||||
(FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \
|
||||
FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)
|
||||
static void zd_op_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *new_flags,
|
||||
int mc_count, struct dev_mc_list *mclist)
|
||||
u64 multicast)
|
||||
{
|
||||
struct zd_mc_hash hash;
|
||||
struct zd_mc_hash hash = {
|
||||
.low = multicast,
|
||||
.high = multicast >> 32,
|
||||
};
|
||||
struct zd_mac *mac = zd_hw_mac(hw);
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
/* Only deal with supported flags */
|
||||
changed_flags &= SUPPORTED_FIF_FLAGS;
|
||||
@ -819,25 +841,16 @@ static void zd_op_configure_filter(struct ieee80211_hw *hw,
|
||||
if (!changed_flags)
|
||||
return;
|
||||
|
||||
if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) {
|
||||
if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI))
|
||||
zd_mc_add_all(&hash);
|
||||
} else {
|
||||
zd_mc_clear(&hash);
|
||||
for (i = 0; i < mc_count; i++) {
|
||||
if (!mclist)
|
||||
break;
|
||||
dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n",
|
||||
mclist->dmi_addr);
|
||||
zd_mc_add_addr(&hash, mclist->dmi_addr);
|
||||
mclist = mclist->next;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&mac->lock, flags);
|
||||
mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL);
|
||||
mac->pass_ctrl = !!(*new_flags & FIF_CONTROL);
|
||||
mac->multicast_hash = hash;
|
||||
spin_unlock_irqrestore(&mac->lock, flags);
|
||||
|
||||
/* XXX: these can be called here now, can sleep now! */
|
||||
queue_work(zd_workqueue, &mac->set_multicast_hash_work);
|
||||
|
||||
if (changed_flags & FIF_CONTROL)
|
||||
@ -940,6 +953,7 @@ static const struct ieee80211_ops zd_ops = {
|
||||
.add_interface = zd_op_add_interface,
|
||||
.remove_interface = zd_op_remove_interface,
|
||||
.config = zd_op_config,
|
||||
.prepare_multicast = zd_op_prepare_multicast,
|
||||
.configure_filter = zd_op_configure_filter,
|
||||
.bss_info_changed = zd_op_bss_info_changed,
|
||||
.get_tsf = zd_op_get_tsf,
|
||||
|
@ -480,7 +480,7 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
|
||||
|
||||
/* extract the MAC address */
|
||||
for (i = 0; i < 3; i++) {
|
||||
v = in[SPOFF(SSB_SPROM1_IL0MAC) + i];
|
||||
v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
|
||||
*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
|
||||
}
|
||||
SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
|
||||
|
@ -1325,6 +1325,8 @@ struct wireless_dev {
|
||||
|
||||
struct mutex mtx;
|
||||
|
||||
struct work_struct cleanup_work;
|
||||
|
||||
/* currently used for IBSS and SME - might be rearranged later */
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||
u8 ssid_len;
|
||||
|
@ -583,7 +583,6 @@ enum ieee80211_conf_flags {
|
||||
/**
|
||||
* enum ieee80211_conf_changed - denotes which configuration changed
|
||||
*
|
||||
* @_IEEE80211_CONF_CHANGE_RADIO_ENABLED: DEPRECATED
|
||||
* @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed
|
||||
* @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed
|
||||
* @IEEE80211_CONF_CHANGE_PS: the PS flag or dynamic PS timeout changed
|
||||
@ -593,7 +592,6 @@ enum ieee80211_conf_flags {
|
||||
* @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed
|
||||
*/
|
||||
enum ieee80211_conf_changed {
|
||||
_IEEE80211_CONF_CHANGE_RADIO_ENABLED = BIT(0),
|
||||
IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2),
|
||||
IEEE80211_CONF_CHANGE_RADIOTAP = BIT(3),
|
||||
IEEE80211_CONF_CHANGE_PS = BIT(4),
|
||||
@ -603,14 +601,6 @@ enum ieee80211_conf_changed {
|
||||
IEEE80211_CONF_CHANGE_IDLE = BIT(8),
|
||||
};
|
||||
|
||||
static inline __deprecated enum ieee80211_conf_changed
|
||||
__IEEE80211_CONF_CHANGE_RADIO_ENABLED(void)
|
||||
{
|
||||
return _IEEE80211_CONF_CHANGE_RADIO_ENABLED;
|
||||
}
|
||||
#define IEEE80211_CONF_CHANGE_RADIO_ENABLED \
|
||||
__IEEE80211_CONF_CHANGE_RADIO_ENABLED()
|
||||
|
||||
/**
|
||||
* struct ieee80211_conf - configuration of the device
|
||||
*
|
||||
@ -618,9 +608,6 @@ __IEEE80211_CONF_CHANGE_RADIO_ENABLED(void)
|
||||
*
|
||||
* @flags: configuration flags defined above
|
||||
*
|
||||
* @radio_enabled: when zero, driver is required to switch off the radio.
|
||||
* @beacon_int: DEPRECATED, DO NOT USE
|
||||
*
|
||||
* @listen_interval: listen interval in units of beacon interval
|
||||
* @max_sleep_period: the maximum number of beacon intervals to sleep for
|
||||
* before checking the beacon for a TIM bit (managed mode only); this
|
||||
@ -644,13 +631,11 @@ __IEEE80211_CONF_CHANGE_RADIO_ENABLED(void)
|
||||
* number of transmissions not the number of retries
|
||||
*/
|
||||
struct ieee80211_conf {
|
||||
int __deprecated beacon_int;
|
||||
u32 flags;
|
||||
int power_level, dynamic_ps_timeout;
|
||||
int max_sleep_period;
|
||||
|
||||
u16 listen_interval;
|
||||
bool __deprecated radio_enabled;
|
||||
|
||||
u8 long_frame_max_tx_count, short_frame_max_tx_count;
|
||||
|
||||
@ -1219,10 +1204,13 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
|
||||
* the driver's configure_filter() function which frames should be
|
||||
* passed to mac80211 and which should be filtered out.
|
||||
*
|
||||
* The configure_filter() callback is invoked with the parameters
|
||||
* @mc_count and @mc_list for the combined multicast address list
|
||||
* of all virtual interfaces, @changed_flags telling which flags
|
||||
* were changed and @total_flags with the new flag states.
|
||||
* Before configure_filter() is invoked, the prepare_multicast()
|
||||
* callback is invoked with the parameters @mc_count and @mc_list
|
||||
* for the combined multicast address list of all virtual interfaces.
|
||||
* It's use is optional, and it returns a u64 that is passed to
|
||||
* configure_filter(). Additionally, configure_filter() has the
|
||||
* arguments @changed_flags telling which flags were changed and
|
||||
* @total_flags with the new flag states.
|
||||
*
|
||||
* If your device has no multicast address filters your driver will
|
||||
* need to check both the %FIF_ALLMULTI flag and the @mc_count
|
||||
@ -1375,9 +1363,13 @@ enum ieee80211_ampdu_mlme_action {
|
||||
* for association indication. The @changed parameter indicates which
|
||||
* of the bss parameters has changed when a call is made.
|
||||
*
|
||||
* @prepare_multicast: Prepare for multicast filter configuration.
|
||||
* This callback is optional, and its return value is passed
|
||||
* to configure_filter(). This callback must be atomic.
|
||||
*
|
||||
* @configure_filter: Configure the device's RX filter.
|
||||
* See the section "Frame filtering" for more information.
|
||||
* This callback must be implemented and atomic.
|
||||
* This callback must be implemented.
|
||||
*
|
||||
* @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit
|
||||
* must be set or cleared for a given STA. Must be atomic.
|
||||
@ -1479,10 +1471,12 @@ struct ieee80211_ops {
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *info,
|
||||
u32 changed);
|
||||
u64 (*prepare_multicast)(struct ieee80211_hw *hw,
|
||||
int mc_count, struct dev_addr_list *mc_list);
|
||||
void (*configure_filter)(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
int mc_count, struct dev_addr_list *mc_list);
|
||||
u64 multicast);
|
||||
int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
|
||||
bool set);
|
||||
int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
|
@ -116,6 +116,8 @@ IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
|
||||
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
/* Mesh stats attributes */
|
||||
IEEE80211_IF_FILE(fwded_mcast, u.mesh.mshstats.fwded_mcast, DEC);
|
||||
IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC);
|
||||
IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC);
|
||||
IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC);
|
||||
IEEE80211_IF_FILE(dropped_frames_no_route,
|
||||
@ -205,6 +207,8 @@ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
sdata->mesh_stats_dir = debugfs_create_dir("mesh_stats",
|
||||
sdata->debugfsdir);
|
||||
MESHSTATS_ADD(fwded_mcast);
|
||||
MESHSTATS_ADD(fwded_unicast);
|
||||
MESHSTATS_ADD(fwded_frames);
|
||||
MESHSTATS_ADD(dropped_frames_ttl);
|
||||
MESHSTATS_ADD(dropped_frames_no_route);
|
||||
@ -327,6 +331,8 @@ static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
|
||||
|
||||
static void del_mesh_stats(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
MESHSTATS_DEL(fwded_mcast);
|
||||
MESHSTATS_DEL(fwded_unicast);
|
||||
MESHSTATS_DEL(fwded_frames);
|
||||
MESHSTATS_DEL(dropped_frames_ttl);
|
||||
MESHSTATS_DEL(dropped_frames_no_route);
|
||||
|
@ -55,16 +55,32 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
|
||||
trace_drv_bss_info_changed(local, vif, info, changed);
|
||||
}
|
||||
|
||||
static inline void drv_configure_filter(struct ieee80211_local *local,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
|
||||
int mc_count,
|
||||
struct dev_addr_list *mc_list)
|
||||
{
|
||||
u64 ret = 0;
|
||||
|
||||
if (local->ops->prepare_multicast)
|
||||
ret = local->ops->prepare_multicast(&local->hw, mc_count,
|
||||
mc_list);
|
||||
|
||||
trace_drv_prepare_multicast(local, mc_count, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void drv_configure_filter(struct ieee80211_local *local,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
u64 multicast)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
local->ops->configure_filter(&local->hw, changed_flags, total_flags,
|
||||
mc_count, mc_list);
|
||||
multicast);
|
||||
trace_drv_configure_filter(local, changed_flags, total_flags,
|
||||
mc_count);
|
||||
multicast);
|
||||
}
|
||||
|
||||
static inline int drv_set_tim(struct ieee80211_local *local,
|
||||
|
@ -191,31 +191,55 @@ TRACE_EVENT(drv_bss_info_changed,
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(drv_prepare_multicast,
|
||||
TP_PROTO(struct ieee80211_local *local, int mc_count, u64 ret),
|
||||
|
||||
TP_ARGS(local, mc_count, ret),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
LOCAL_ENTRY
|
||||
__field(int, mc_count)
|
||||
__field(u64, ret)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
LOCAL_ASSIGN;
|
||||
__entry->mc_count = mc_count;
|
||||
__entry->ret = ret;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
LOCAL_PR_FMT " prepare mc (%d): %llx",
|
||||
LOCAL_PR_ARG, __entry->mc_count,
|
||||
(unsigned long long) __entry->ret
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(drv_configure_filter,
|
||||
TP_PROTO(struct ieee80211_local *local,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
int mc_count),
|
||||
u64 multicast),
|
||||
|
||||
TP_ARGS(local, changed_flags, total_flags, mc_count),
|
||||
TP_ARGS(local, changed_flags, total_flags, multicast),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
LOCAL_ENTRY
|
||||
__field(unsigned int, changed)
|
||||
__field(unsigned int, total)
|
||||
__field(int, mc)
|
||||
__field(u64, multicast)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
LOCAL_ASSIGN;
|
||||
__entry->changed = changed_flags;
|
||||
__entry->total = *total_flags;
|
||||
__entry->mc = mc_count;
|
||||
__entry->multicast = multicast;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
LOCAL_PR_FMT " changed:%#x total:%#x mc:%d",
|
||||
LOCAL_PR_ARG, __entry->changed, __entry->total, __entry->mc
|
||||
LOCAL_PR_FMT " changed:%#x total:%#x",
|
||||
LOCAL_PR_ARG, __entry->changed, __entry->total
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -212,7 +212,9 @@ struct ieee80211_if_vlan {
|
||||
};
|
||||
|
||||
struct mesh_stats {
|
||||
__u32 fwded_frames; /* Mesh forwarded frames */
|
||||
__u32 fwded_mcast; /* Mesh forwarded multicast frames */
|
||||
__u32 fwded_unicast; /* Mesh forwarded unicast frames */
|
||||
__u32 fwded_frames; /* Mesh total forwarded frames */
|
||||
__u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/
|
||||
__u32 dropped_frames_no_route; /* Not transmitted, no route found */
|
||||
atomic_t estab_plinks;
|
||||
@ -506,6 +508,8 @@ struct ieee80211_sub_if_data {
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
struct dentry *mesh_stats_dir;
|
||||
struct {
|
||||
struct dentry *fwded_mcast;
|
||||
struct dentry *fwded_unicast;
|
||||
struct dentry *fwded_frames;
|
||||
struct dentry *dropped_frames_ttl;
|
||||
struct dentry *dropped_frames_no_route;
|
||||
@ -636,6 +640,9 @@ struct ieee80211_local {
|
||||
/* protects the aggregated multicast list and filter calls */
|
||||
spinlock_t filter_lock;
|
||||
|
||||
/* used for uploading changed mc list */
|
||||
struct work_struct reconfig_filter;
|
||||
|
||||
/* aggregated multicast list */
|
||||
struct dev_addr_list *mc_list;
|
||||
int mc_count;
|
||||
|
@ -227,9 +227,7 @@ static int ieee80211_open(struct net_device *dev)
|
||||
if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
|
||||
local->fif_other_bss++;
|
||||
|
||||
spin_lock_bh(&local->filter_lock);
|
||||
ieee80211_configure_filter(local);
|
||||
spin_unlock_bh(&local->filter_lock);
|
||||
break;
|
||||
default:
|
||||
conf.vif = &sdata->vif;
|
||||
@ -241,17 +239,13 @@ static int ieee80211_open(struct net_device *dev)
|
||||
|
||||
if (ieee80211_vif_is_mesh(&sdata->vif)) {
|
||||
local->fif_other_bss++;
|
||||
spin_lock_bh(&local->filter_lock);
|
||||
ieee80211_configure_filter(local);
|
||||
spin_unlock_bh(&local->filter_lock);
|
||||
|
||||
ieee80211_start_mesh(sdata);
|
||||
} else if (sdata->vif.type == NL80211_IFTYPE_AP) {
|
||||
local->fif_pspoll++;
|
||||
|
||||
spin_lock_bh(&local->filter_lock);
|
||||
ieee80211_configure_filter(local);
|
||||
spin_unlock_bh(&local->filter_lock);
|
||||
}
|
||||
|
||||
changed |= ieee80211_reset_erp_info(sdata);
|
||||
@ -404,10 +398,11 @@ static int ieee80211_stop(struct net_device *dev)
|
||||
spin_lock_bh(&local->filter_lock);
|
||||
__dev_addr_unsync(&local->mc_list, &local->mc_count,
|
||||
&dev->mc_list, &dev->mc_count);
|
||||
ieee80211_configure_filter(local);
|
||||
spin_unlock_bh(&local->filter_lock);
|
||||
netif_addr_unlock_bh(dev);
|
||||
|
||||
ieee80211_configure_filter(local);
|
||||
|
||||
del_timer_sync(&local->dynamic_ps_timer);
|
||||
cancel_work_sync(&local->dynamic_ps_enable_work);
|
||||
|
||||
@ -458,9 +453,7 @@ static int ieee80211_stop(struct net_device *dev)
|
||||
if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
|
||||
local->fif_other_bss--;
|
||||
|
||||
spin_lock_bh(&local->filter_lock);
|
||||
ieee80211_configure_filter(local);
|
||||
spin_unlock_bh(&local->filter_lock);
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
del_timer_sync(&sdata->u.mgd.chswitch_timer);
|
||||
@ -503,9 +496,7 @@ static int ieee80211_stop(struct net_device *dev)
|
||||
local->fif_other_bss--;
|
||||
atomic_dec(&local->iff_allmultis);
|
||||
|
||||
spin_lock_bh(&local->filter_lock);
|
||||
ieee80211_configure_filter(local);
|
||||
spin_unlock_bh(&local->filter_lock);
|
||||
|
||||
ieee80211_stop_mesh(sdata);
|
||||
}
|
||||
@ -622,8 +613,8 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
|
||||
spin_lock_bh(&local->filter_lock);
|
||||
__dev_addr_sync(&local->mc_list, &local->mc_count,
|
||||
&dev->mc_list, &dev->mc_count);
|
||||
ieee80211_configure_filter(local);
|
||||
spin_unlock_bh(&local->filter_lock);
|
||||
ieee80211_queue_work(&local->hw, &local->reconfig_filter);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -50,9 +50,9 @@ struct ieee80211_tx_status_rtap_hdr {
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* must be called under mdev tx lock */
|
||||
void ieee80211_configure_filter(struct ieee80211_local *local)
|
||||
{
|
||||
u64 mc;
|
||||
unsigned int changed_flags;
|
||||
unsigned int new_flags = 0;
|
||||
|
||||
@ -62,7 +62,7 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
|
||||
if (atomic_read(&local->iff_allmultis))
|
||||
new_flags |= FIF_ALLMULTI;
|
||||
|
||||
if (local->monitors)
|
||||
if (local->monitors || local->scanning)
|
||||
new_flags |= FIF_BCN_PRBRESP_PROMISC;
|
||||
|
||||
if (local->fif_fcsfail)
|
||||
@ -80,20 +80,30 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
|
||||
if (local->fif_pspoll)
|
||||
new_flags |= FIF_PSPOLL;
|
||||
|
||||
spin_lock_bh(&local->filter_lock);
|
||||
changed_flags = local->filter_flags ^ new_flags;
|
||||
|
||||
mc = drv_prepare_multicast(local, local->mc_count, local->mc_list);
|
||||
spin_unlock_bh(&local->filter_lock);
|
||||
|
||||
/* be a bit nasty */
|
||||
new_flags |= (1<<31);
|
||||
|
||||
drv_configure_filter(local, changed_flags, &new_flags,
|
||||
local->mc_count,
|
||||
local->mc_list);
|
||||
drv_configure_filter(local, changed_flags, &new_flags, mc);
|
||||
|
||||
WARN_ON(new_flags & (1<<31));
|
||||
|
||||
local->filter_flags = new_flags & ~(1<<31);
|
||||
}
|
||||
|
||||
static void ieee80211_reconfig_filter(struct work_struct *work)
|
||||
{
|
||||
struct ieee80211_local *local =
|
||||
container_of(work, struct ieee80211_local, reconfig_filter);
|
||||
|
||||
ieee80211_configure_filter(local);
|
||||
}
|
||||
|
||||
int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
|
||||
{
|
||||
struct ieee80211_channel *chan, *scan_chan;
|
||||
@ -231,9 +241,6 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
drv_bss_info_changed(local, &sdata->vif,
|
||||
&sdata->vif.bss_conf, changed);
|
||||
|
||||
/* DEPRECATED */
|
||||
local->hw.conf.beacon_int = sdata->vif.bss_conf.beacon_int;
|
||||
}
|
||||
|
||||
u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
|
||||
@ -475,6 +482,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
rate_control_tx_status(local, sband, sta, skb);
|
||||
if (ieee80211_vif_is_mesh(&sta->sdata->vif))
|
||||
ieee80211s_update_metric(local, sta, skb);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
@ -677,7 +686,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
|
||||
local->hw.max_rates = 1;
|
||||
local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
|
||||
local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
|
||||
local->hw.conf.radio_enabled = true;
|
||||
local->user_power_level = -1;
|
||||
|
||||
INIT_LIST_HEAD(&local->interfaces);
|
||||
@ -692,6 +700,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
|
||||
|
||||
INIT_WORK(&local->restart_work, ieee80211_restart_work);
|
||||
|
||||
INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
|
||||
|
||||
INIT_WORK(&local->dynamic_ps_enable_work,
|
||||
ieee80211_dynamic_ps_enable_work);
|
||||
INIT_WORK(&local->dynamic_ps_disable_work,
|
||||
@ -920,7 +930,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||
fail_workqueue:
|
||||
wiphy_unregister(local->hw.wiphy);
|
||||
fail_wiphy_register:
|
||||
kfree(local->int_scan_req->channels);
|
||||
kfree(local->int_scan_req);
|
||||
return result;
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_register_hw);
|
||||
@ -946,6 +956,8 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
|
||||
|
||||
rtnl_unlock();
|
||||
|
||||
cancel_work_sync(&local->reconfig_filter);
|
||||
|
||||
ieee80211_clear_tx_pending(local);
|
||||
sta_info_stop(local);
|
||||
rate_control_deinitialize(local);
|
||||
|
@ -226,6 +226,8 @@ void mesh_mgmt_ies_add(struct sk_buff *skb,
|
||||
void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
|
||||
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211s_init(void);
|
||||
void ieee80211s_update_metric(struct ieee80211_local *local,
|
||||
struct sta_info *stainfo, struct sk_buff *skb);
|
||||
void ieee80211s_stop(void);
|
||||
void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
|
||||
ieee80211_rx_result
|
||||
|
@ -201,6 +201,24 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ieee80211s_update_metric(struct ieee80211_local *local,
|
||||
struct sta_info *stainfo, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
int failed;
|
||||
|
||||
if (!ieee80211_is_data(hdr->frame_control))
|
||||
return;
|
||||
|
||||
failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);
|
||||
|
||||
/* moving average, scaled to 100 */
|
||||
stainfo->fail_avg = ((80 * stainfo->fail_avg + 5) / 100 + 20 * failed);
|
||||
if (stainfo->fail_avg > 95)
|
||||
mesh_plink_broken(stainfo);
|
||||
}
|
||||
|
||||
static u32 airtime_link_metric_get(struct ieee80211_local *local,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
@ -479,6 +497,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
|
||||
hopcount, ttl, cpu_to_le32(lifetime),
|
||||
cpu_to_le32(metric), cpu_to_le32(preq_id),
|
||||
sdata);
|
||||
ifmsh->mshstats.fwded_mcast++;
|
||||
ifmsh->mshstats.fwded_frames++;
|
||||
}
|
||||
}
|
||||
@ -537,6 +556,8 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
|
||||
cpu_to_le32(lifetime), cpu_to_le32(metric),
|
||||
0, sdata);
|
||||
rcu_read_unlock();
|
||||
|
||||
sdata->u.mesh.mshstats.fwded_unicast++;
|
||||
sdata->u.mesh.mshstats.fwded_frames++;
|
||||
return;
|
||||
|
||||
|
@ -51,7 +51,6 @@
|
||||
#include <linux/random.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <net/mac80211.h>
|
||||
#include "mesh.h"
|
||||
#include "rate.h"
|
||||
#include "rc80211_minstrel.h"
|
||||
|
||||
@ -156,16 +155,12 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct minstrel_sta_info *mi = priv_sta;
|
||||
struct minstrel_priv *mp = (struct minstrel_priv *)priv;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_tx_rate *ar = info->status.rates;
|
||||
struct ieee80211_local *local = hw_to_local(mp->hw);
|
||||
struct sta_info *si;
|
||||
int i, ndx;
|
||||
int success;
|
||||
|
||||
success = !!(info->flags & IEEE80211_TX_STAT_ACK);
|
||||
si = sta_info_get(local, sta->addr);
|
||||
|
||||
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
|
||||
if (ar[i].idx < 0)
|
||||
@ -177,17 +172,8 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
|
||||
|
||||
mi->r[ndx].attempts += ar[i].count;
|
||||
|
||||
if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) {
|
||||
if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0))
|
||||
mi->r[ndx].success += success;
|
||||
if (si) {
|
||||
si->fail_avg = (18050 - mi->r[ndx].probability)
|
||||
/ 180;
|
||||
WARN_ON(si->fail_avg > 100);
|
||||
if (si->fail_avg == 100 &&
|
||||
ieee80211_vif_is_mesh(&si->sdata->vif))
|
||||
mesh_plink_broken(si);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0))
|
||||
|
@ -169,19 +169,9 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
|
||||
* still a good measurement and copy it. */
|
||||
if (unlikely(spinfo->tx_num_xmit == 0))
|
||||
pf = spinfo->last_pf;
|
||||
else {
|
||||
/* XXX: BAD HACK!!! */
|
||||
struct sta_info *si = container_of(sta, struct sta_info, sta);
|
||||
|
||||
else
|
||||
pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit;
|
||||
|
||||
if (ieee80211_vif_is_mesh(&si->sdata->vif) && pf == 100)
|
||||
mesh_plink_broken(si);
|
||||
pf <<= RC_PID_ARITH_SHIFT;
|
||||
si->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9)
|
||||
>> RC_PID_ARITH_SHIFT;
|
||||
}
|
||||
|
||||
spinfo->tx_num_xmit = 0;
|
||||
spinfo->tx_num_failed = 0;
|
||||
|
||||
@ -311,7 +301,6 @@ rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband,
|
||||
struct rc_pid_sta_info *spinfo = priv_sta;
|
||||
struct rc_pid_info *pinfo = priv;
|
||||
struct rc_pid_rateinfo *rinfo = pinfo->rinfo;
|
||||
struct sta_info *si;
|
||||
int i, j, tmp;
|
||||
bool s;
|
||||
|
||||
@ -348,9 +337,6 @@ rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband,
|
||||
}
|
||||
|
||||
spinfo->txrate_idx = rate_lowest_index(sband, sta);
|
||||
/* HACK */
|
||||
si = container_of(sta, struct sta_info, sta);
|
||||
si->fail_avg = 0;
|
||||
}
|
||||
|
||||
static void *rate_control_pid_alloc(struct ieee80211_hw *hw,
|
||||
|
@ -1550,7 +1550,10 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
||||
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
|
||||
info->control.vif = &rx->sdata->vif;
|
||||
ieee80211_select_queue(local, fwd_skb);
|
||||
if (!is_multicast_ether_addr(fwd_hdr->addr1)) {
|
||||
if (is_multicast_ether_addr(fwd_hdr->addr1))
|
||||
IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
|
||||
fwded_mcast);
|
||||
else {
|
||||
int err;
|
||||
/*
|
||||
* Save TA to addr1 to send TA a path error if a
|
||||
@ -1564,6 +1567,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
||||
* later to the pending skb queue. */
|
||||
if (err)
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
|
||||
fwded_unicast);
|
||||
}
|
||||
IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
|
||||
fwded_frames);
|
||||
|
@ -292,13 +292,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
|
||||
if (was_hw_scan)
|
||||
goto done;
|
||||
|
||||
spin_lock_bh(&local->filter_lock);
|
||||
local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC;
|
||||
drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC,
|
||||
&local->filter_flags,
|
||||
local->mc_count,
|
||||
local->mc_list);
|
||||
spin_unlock_bh(&local->filter_lock);
|
||||
ieee80211_configure_filter(local);
|
||||
|
||||
drv_sw_scan_complete(local);
|
||||
|
||||
@ -376,13 +370,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
|
||||
local->next_scan_state = SCAN_DECISION;
|
||||
local->scan_channel_idx = 0;
|
||||
|
||||
spin_lock_bh(&local->filter_lock);
|
||||
local->filter_flags |= FIF_BCN_PRBRESP_PROMISC;
|
||||
drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC,
|
||||
&local->filter_flags,
|
||||
local->mc_count,
|
||||
local->mc_list);
|
||||
spin_unlock_bh(&local->filter_lock);
|
||||
ieee80211_configure_filter(local);
|
||||
|
||||
/* TODO: start scan as soon as all nullfunc frames are ACKed */
|
||||
ieee80211_queue_delayed_work(&local->hw,
|
||||
|
@ -1076,9 +1076,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
/* reconfigure hardware */
|
||||
ieee80211_hw_config(local, ~0);
|
||||
|
||||
spin_lock_bh(&local->filter_lock);
|
||||
ieee80211_configure_filter(local);
|
||||
spin_unlock_bh(&local->filter_lock);
|
||||
|
||||
/* Finally also reconfigure all the BSS information */
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <net/genetlink.h>
|
||||
#include <net/cfg80211.h>
|
||||
@ -309,7 +310,8 @@ static void cfg80211_process_events(struct wireless_dev *wdev)
|
||||
switch (ev->type) {
|
||||
case EVENT_CONNECT_RESULT:
|
||||
__cfg80211_connect_result(
|
||||
wdev->netdev, ev->cr.bssid,
|
||||
wdev->netdev, is_zero_ether_addr(ev->cr.bssid) ?
|
||||
NULL : ev->cr.bssid,
|
||||
ev->cr.req_ie, ev->cr.req_ie_len,
|
||||
ev->cr.resp_ie, ev->cr.resp_ie_len,
|
||||
ev->cr.status,
|
||||
@ -430,6 +432,8 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
|
||||
INIT_WORK(&rdev->conn_work, cfg80211_conn_work);
|
||||
INIT_WORK(&rdev->event_work, cfg80211_event_work);
|
||||
|
||||
init_waitqueue_head(&rdev->dev_wait);
|
||||
|
||||
/*
|
||||
* Initialize wiphy parameters to IEEE 802.11 MIB default values.
|
||||
* Fragmentation and RTS threshold are disabled by default with the
|
||||
@ -574,7 +578,23 @@ void wiphy_unregister(struct wiphy *wiphy)
|
||||
/* protect the device list */
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
|
||||
wait_event(rdev->dev_wait, ({
|
||||
int __count;
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
__count = rdev->opencount;
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
__count == 0;}));
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
BUG_ON(!list_empty(&rdev->netdev_list));
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
/*
|
||||
* First remove the hardware from everywhere, this makes
|
||||
* it impossible to find from userspace.
|
||||
*/
|
||||
cfg80211_debugfs_rdev_del(rdev);
|
||||
list_del(&rdev->list);
|
||||
|
||||
/*
|
||||
* Try to grab rdev->mtx. If a command is still in progress,
|
||||
@ -582,21 +602,18 @@ void wiphy_unregister(struct wiphy *wiphy)
|
||||
* down the device already. We wait for this command to complete
|
||||
* before unlinking the item from the list.
|
||||
* Note: as codified by the BUG_ON above we cannot get here if
|
||||
* a virtual interface is still associated. Hence, we can only
|
||||
* get to lock contention here if userspace issues a command
|
||||
* that identified the hardware by wiphy index.
|
||||
* a virtual interface is still present. Hence, we can only get
|
||||
* to lock contention here if userspace issues a command that
|
||||
* identified the hardware by wiphy index.
|
||||
*/
|
||||
mutex_lock(&rdev->mtx);
|
||||
/* unlock again before freeing */
|
||||
mutex_unlock(&rdev->mtx);
|
||||
|
||||
cfg80211_debugfs_rdev_del(rdev);
|
||||
cfg80211_lock_rdev(rdev);
|
||||
/* nothing */
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
|
||||
/* If this device got a regulatory hint tell core its
|
||||
* free to listen now to a new shiny device regulatory hint */
|
||||
reg_device_remove(wiphy);
|
||||
|
||||
list_del(&rdev->list);
|
||||
cfg80211_rdev_list_generation++;
|
||||
device_del(&rdev->wiphy.dev);
|
||||
debugfs_remove(rdev->wiphy.debugfsdir);
|
||||
@ -605,7 +622,6 @@ void wiphy_unregister(struct wiphy *wiphy)
|
||||
|
||||
flush_work(&rdev->scan_done_wk);
|
||||
cancel_work_sync(&rdev->conn_work);
|
||||
kfree(rdev->scan_req);
|
||||
flush_work(&rdev->event_work);
|
||||
}
|
||||
EXPORT_SYMBOL(wiphy_unregister);
|
||||
@ -636,6 +652,31 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
|
||||
}
|
||||
EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
|
||||
|
||||
static void wdev_cleanup_work(struct work_struct *work)
|
||||
{
|
||||
struct wireless_dev *wdev;
|
||||
struct cfg80211_registered_device *rdev;
|
||||
|
||||
wdev = container_of(work, struct wireless_dev, cleanup_work);
|
||||
rdev = wiphy_to_dev(wdev->wiphy);
|
||||
|
||||
cfg80211_lock_rdev(rdev);
|
||||
|
||||
if (WARN_ON(rdev->scan_req && rdev->scan_req->dev == wdev->netdev)) {
|
||||
rdev->scan_req->aborted = true;
|
||||
___cfg80211_scan_done(rdev);
|
||||
}
|
||||
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
rdev->opencount--;
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
wake_up(&rdev->dev_wait);
|
||||
|
||||
dev_put(wdev->netdev);
|
||||
}
|
||||
|
||||
static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||
unsigned long state,
|
||||
void *ndev)
|
||||
@ -653,7 +694,13 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||
|
||||
switch (state) {
|
||||
case NETDEV_REGISTER:
|
||||
/*
|
||||
* NB: cannot take rdev->mtx here because this may be
|
||||
* called within code protected by it when interfaces
|
||||
* are added with nl80211.
|
||||
*/
|
||||
mutex_init(&wdev->mtx);
|
||||
INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work);
|
||||
INIT_LIST_HEAD(&wdev->event_list);
|
||||
spin_lock_init(&wdev->event_lock);
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
@ -708,8 +755,22 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
dev_hold(dev);
|
||||
schedule_work(&wdev->cleanup_work);
|
||||
break;
|
||||
case NETDEV_UP:
|
||||
/*
|
||||
* If we have a really quick DOWN/UP succession we may
|
||||
* have this work still pending ... cancel it and see
|
||||
* if it was pending, in which case we need to account
|
||||
* for some of the work it would have done.
|
||||
*/
|
||||
if (cancel_work_sync(&wdev->cleanup_work)) {
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
rdev->opencount--;
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
dev_put(dev);
|
||||
}
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
cfg80211_lock_rdev(rdev);
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
@ -725,18 +786,17 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||
break;
|
||||
}
|
||||
wdev_unlock(wdev);
|
||||
rdev->opencount++;
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
#endif
|
||||
break;
|
||||
case NETDEV_UNREGISTER:
|
||||
cfg80211_lock_rdev(rdev);
|
||||
|
||||
if (WARN_ON(rdev->scan_req && rdev->scan_req->dev == dev)) {
|
||||
rdev->scan_req->aborted = true;
|
||||
___cfg80211_scan_done(rdev);
|
||||
}
|
||||
|
||||
/*
|
||||
* NB: cannot take rdev->mtx here because this may be
|
||||
* called within code protected by it when interfaces
|
||||
* are removed with nl80211.
|
||||
*/
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
/*
|
||||
* It is possible to get NETDEV_UNREGISTER
|
||||
@ -749,13 +809,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||
sysfs_remove_link(&dev->dev.kobj, "phy80211");
|
||||
list_del_init(&wdev->list);
|
||||
rdev->devlist_generation++;
|
||||
mutex_destroy(&wdev->mtx);
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
kfree(wdev->wext.keys);
|
||||
#endif
|
||||
}
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
break;
|
||||
case NETDEV_PRE_UP:
|
||||
if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
|
||||
|
@ -50,6 +50,8 @@ struct cfg80211_registered_device {
|
||||
struct mutex devlist_mtx;
|
||||
struct list_head netdev_list;
|
||||
int devlist_generation;
|
||||
int opencount; /* also protected by devlist_mtx */
|
||||
wait_queue_head_t dev_wait;
|
||||
|
||||
/* BSSes/scanning */
|
||||
spinlock_t bss_lock;
|
||||
|
@ -96,6 +96,15 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
|
||||
WARN_ON(!bss);
|
||||
}
|
||||
|
||||
if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) {
|
||||
/*
|
||||
* This is for the userspace SME, the CONNECTING
|
||||
* state will be changed to CONNECTED by
|
||||
* __cfg80211_connect_result() below.
|
||||
*/
|
||||
wdev->sme_state = CFG80211_SME_CONNECTING;
|
||||
}
|
||||
|
||||
/* this consumes one bss reference (unless bss is NULL) */
|
||||
__cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
|
||||
status_code,
|
||||
|
@ -351,15 +351,13 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
|
||||
return;
|
||||
|
||||
if (wdev->sme_state == CFG80211_SME_CONNECTED)
|
||||
nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), dev,
|
||||
if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING))
|
||||
return;
|
||||
|
||||
nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev,
|
||||
bssid, req_ie, req_ie_len,
|
||||
resp_ie, resp_ie_len, GFP_KERNEL);
|
||||
else
|
||||
nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev,
|
||||
bssid, req_ie, req_ie_len,
|
||||
resp_ie, resp_ie_len,
|
||||
status, GFP_KERNEL);
|
||||
resp_ie, resp_ie_len,
|
||||
status, GFP_KERNEL);
|
||||
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
if (wextev) {
|
||||
@ -392,18 +390,13 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
wdev->current_bss = NULL;
|
||||
}
|
||||
|
||||
if (status == WLAN_STATUS_SUCCESS &&
|
||||
wdev->sme_state == CFG80211_SME_IDLE)
|
||||
goto success;
|
||||
|
||||
if (wdev->sme_state != CFG80211_SME_CONNECTING)
|
||||
return;
|
||||
|
||||
if (wdev->conn)
|
||||
wdev->conn->state = CFG80211_CONN_IDLE;
|
||||
|
||||
if (status != WLAN_STATUS_SUCCESS) {
|
||||
wdev->sme_state = CFG80211_SME_IDLE;
|
||||
if (wdev->conn)
|
||||
kfree(wdev->conn->ie);
|
||||
kfree(wdev->conn);
|
||||
wdev->conn = NULL;
|
||||
kfree(wdev->connect_keys);
|
||||
@ -412,7 +405,6 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
return;
|
||||
}
|
||||
|
||||
success:
|
||||
if (!bss)
|
||||
bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
|
||||
wdev->ssid, wdev->ssid_len,
|
||||
@ -458,7 +450,8 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
return;
|
||||
|
||||
ev->type = EVENT_CONNECT_RESULT;
|
||||
memcpy(ev->cr.bssid, bssid, ETH_ALEN);
|
||||
if (bssid)
|
||||
memcpy(ev->cr.bssid, bssid, ETH_ALEN);
|
||||
ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev);
|
||||
ev->cr.req_ie_len = req_ie_len;
|
||||
memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len);
|
||||
@ -789,6 +782,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
|
||||
}
|
||||
}
|
||||
if (err) {
|
||||
kfree(wdev->conn->ie);
|
||||
kfree(wdev->conn);
|
||||
wdev->conn = NULL;
|
||||
wdev->sme_state = CFG80211_SME_IDLE;
|
||||
@ -858,6 +852,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
|
||||
(wdev->conn->state == CFG80211_CONN_SCANNING ||
|
||||
wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)) {
|
||||
wdev->sme_state = CFG80211_SME_IDLE;
|
||||
kfree(wdev->conn->ie);
|
||||
kfree(wdev->conn);
|
||||
wdev->conn = NULL;
|
||||
wdev->ssid_len = 0;
|
||||
|
@ -771,6 +771,7 @@ int cfg80211_wext_siwfreq(struct net_device *dev,
|
||||
return err;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq);
|
||||
|
||||
int cfg80211_wext_giwfreq(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
|
Loading…
Reference in New Issue
Block a user