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

This commit is contained in:
David S. Miller 2009-08-21 01:56:56 -07:00
commit f8f2109d4f
99 changed files with 2826 additions and 2206 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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[] = {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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, &reg);
rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS0FBK, 8);
rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS1FBK, 8);
rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS2FBK, 3);
rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS2FBK, 9);
rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS3FBK, 10);
rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS4FBK, 11);
rt2x00_set_field32(&reg, 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);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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