2
0
mirror of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-09-04 20:19:47 +08:00

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: drivers/net/mv643xx_eth.*
F: include/linux/mv643xx.h 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 MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
M: Nicolas Pitre <nico@cam.org> M: Nicolas Pitre <nico@cam.org>
S: Maintained 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, static void adm8211_configure_filter(struct ieee80211_hw *dev,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *total_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 }; static const u8 bcast[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
struct adm8211_priv *priv = dev->priv; struct adm8211_priv *priv = dev->priv;
unsigned int bit_nr, new_flags; unsigned int new_flags;
u32 mc_filter[2]; u32 mc_filter[2];
int i;
mc_filter[0] = multicast;
mc_filter[1] = multicast >> 32;
new_flags = 0; 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_PR;
priv->nar &= ~ADM8211_NAR_MM; priv->nar &= ~ADM8211_NAR_MM;
mc_filter[1] = mc_filter[0] = ~0; 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; new_flags |= FIF_ALLMULTI;
priv->nar &= ~ADM8211_NAR_PR; priv->nar &= ~ADM8211_NAR_PR;
priv->nar |= ADM8211_NAR_MM; priv->nar |= ADM8211_NAR_MM;
mc_filter[1] = mc_filter[0] = ~0; mc_filter[1] = mc_filter[0] = ~0;
} else { } else {
priv->nar &= ~(ADM8211_NAR_MM | ADM8211_NAR_PR); 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(); ADM8211_IDLE_RX();
@ -1757,6 +1770,7 @@ static const struct ieee80211_ops adm8211_ops = {
.remove_interface = adm8211_remove_interface, .remove_interface = adm8211_remove_interface,
.config = adm8211_config, .config = adm8211_config,
.bss_info_changed = adm8211_bss_info_changed, .bss_info_changed = adm8211_bss_info_changed,
.prepare_multicast = adm8211_prepare_multicast,
.configure_filter = adm8211_configure_filter, .configure_filter = adm8211_configure_filter,
.get_stats = adm8211_get_stats, .get_stats = adm8211_get_stats,
.get_tx_stats = adm8211_get_tx_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; struct at76_priv *priv = hw->priv;
at76_dbg(DBG_MAC80211, "%s(): channel %d radio %d", at76_dbg(DBG_MAC80211, "%s(): channel %d",
__func__, hw->conf.channel->hw_value, __func__, hw->conf.channel->hw_value);
hw->conf.radio_enabled);
at76_dbg_dump(DBG_MAC80211, priv->bssid, ETH_ALEN, "bssid:"); at76_dbg_dump(DBG_MAC80211, priv->bssid, ETH_ALEN, "bssid:");
mutex_lock(&priv->mtx); mutex_lock(&priv->mtx);
@ -1997,15 +1996,14 @@ static void at76_bss_info_changed(struct ieee80211_hw *hw,
/* must be atomic */ /* must be atomic */
static void at76_configure_filter(struct ieee80211_hw *hw, static void at76_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *total_flags, int mc_count, unsigned int *total_flags, u64 multicast)
struct dev_addr_list *mc_list)
{ {
struct at76_priv *priv = hw->priv; struct at76_priv *priv = hw->priv;
int flags; int flags;
at76_dbg(DBG_MAC80211, "%s(): changed_flags=0x%08x " at76_dbg(DBG_MAC80211, "%s(): changed_flags=0x%08x "
"total_flags=0x%08x mc_count=%d", "total_flags=0x%08x",
__func__, changed_flags, *total_flags, mc_count); __func__, changed_flags, *total_flags);
flags = changed_flags & AT76_SUPPORTED_FILTERS; flags = changed_flags & AT76_SUPPORTED_FILTERS;
*total_flags = AT76_SUPPORTED_FILTERS; *total_flags = AT76_SUPPORTED_FILTERS;

View File

@ -157,6 +157,7 @@ struct ar9170_sta_tid {
struct ar9170 { struct ar9170 {
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
struct ath_common common;
struct mutex mutex; struct mutex mutex;
enum ar9170_device_state state; enum ar9170_device_state state;
unsigned long bad_hw_nagger; unsigned long bad_hw_nagger;
@ -184,10 +185,8 @@ struct ar9170 {
bool disable_offload; bool disable_offload;
/* filter settings */ /* filter settings */
struct work_struct filter_config_work; u64 cur_mc_hash;
u64 cur_mc_hash, want_mc_hash; u32 cur_filter;
u32 cur_filter, want_filter;
unsigned long filter_changed;
unsigned int filter_state; unsigned int filter_state;
bool sniffer_enabled; bool sniffer_enabled;
@ -222,7 +221,6 @@ struct ar9170 {
/* EEPROM */ /* EEPROM */
struct ar9170_eeprom eeprom; struct ar9170_eeprom eeprom;
struct ath_regulatory regulatory;
/* tx queues - as seen by hw - */ /* tx queues - as seen by hw - */
struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; 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_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED)
#define IS_ACCEPTING_CMD(a) (((struct ar9170 *)a)->state >= AR9170_IDLE) #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 */ /* exported interface */
void *ar9170_alloc(size_t priv_size); void *ar9170_alloc(size_t priv_size);
int ar9170_register(struct ar9170 *ar, struct device *pdev); 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_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
int ar9170_init_mac(struct ar9170 *ar); int ar9170_init_mac(struct ar9170 *ar);
int ar9170_set_qos(struct ar9170 *ar); int ar9170_set_qos(struct ar9170 *ar);
int ar9170_update_multicast(struct ar9170 *ar); int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hast);
int ar9170_update_frame_filter(struct ar9170 *ar); int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter);
int ar9170_set_operating_mode(struct ar9170 *ar); int ar9170_set_operating_mode(struct ar9170 *ar);
int ar9170_set_beacon_timers(struct ar9170 *ar); int ar9170_set_beacon_timers(struct ar9170 *ar);
int ar9170_set_dyn_sifs_ack(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(); return ar9170_regwrite_result();
} }
int ar9170_update_multicast(struct ar9170 *ar) int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hash)
{ {
int err; int err;
ar9170_regwrite_begin(ar); ar9170_regwrite_begin(ar);
ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, mc_hash >> 32);
ar->want_mc_hash >> 32); ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, mc_hash);
ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L,
ar->want_mc_hash);
ar9170_regwrite_finish(); ar9170_regwrite_finish();
err = ar9170_regwrite_result(); err = ar9170_regwrite_result();
if (err) if (err)
return err; return err;
ar->cur_mc_hash = ar->want_mc_hash; ar->cur_mc_hash = mc_hash;
return 0; return 0;
} }
int ar9170_update_frame_filter(struct ar9170 *ar) int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter)
{ {
int err; int err;
err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER, err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER, filter);
ar->want_filter);
if (err) if (err)
return err; return err;
ar->cur_filter = ar->want_filter; ar->cur_filter = filter;
return 0; return 0;
} }

View File

@ -1232,8 +1232,6 @@ static int ar9170_op_start(struct ieee80211_hw *hw)
mutex_lock(&ar->mutex); mutex_lock(&ar->mutex);
ar->filter_changed = 0;
/* reinitialize queues statistics */ /* reinitialize queues statistics */
memset(&ar->tx_stats, 0, sizeof(ar->tx_stats)); memset(&ar->tx_stats, 0, sizeof(ar->tx_stats));
for (i = 0; i < __AR9170_NUM_TXQ; i++) 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 #ifdef CONFIG_AR9170_LEDS
cancel_delayed_work_sync(&ar->led_work); cancel_delayed_work_sync(&ar->led_work);
#endif #endif
cancel_work_sync(&ar->filter_config_work);
cancel_work_sync(&ar->beacon_work); cancel_work_sync(&ar->beacon_work);
mutex_lock(&ar->mutex); mutex_lock(&ar->mutex);
@ -1973,8 +1970,7 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw,
} }
ar->cur_filter = 0; ar->cur_filter = 0;
ar->want_filter = AR9170_MAC_REG_FTF_DEFAULTS; err = ar9170_update_frame_filter(ar, AR9170_MAC_REG_FTF_DEFAULTS);
err = ar9170_update_frame_filter(ar);
if (err) if (err)
goto unlock; goto unlock;
@ -1992,8 +1988,7 @@ static void ar9170_op_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&ar->mutex); mutex_lock(&ar->mutex);
ar->vif = NULL; ar->vif = NULL;
ar->want_filter = 0; ar9170_update_frame_filter(ar, 0);
ar9170_update_frame_filter(ar);
ar9170_set_beacon_timers(ar); ar9170_set_beacon_timers(ar);
dev_kfree_skb(ar->beacon); dev_kfree_skb(ar->beacon);
ar->beacon = NULL; ar->beacon = NULL;
@ -2065,48 +2060,37 @@ out:
return err; 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, u64 mchash;
filter_config_work); int i;
int err;
if (unlikely(!IS_STARTED(ar))) /* always get broadcast frames */
return ; mchash = 1ULL << (0xff >> 2);
mutex_lock(&ar->mutex); for (i = 0; i < mc_count; i++) {
if (test_and_clear_bit(AR9170_FILTER_CHANGED_MODE, if (WARN_ON(!mclist))
&ar->filter_changed)) { break;
err = ar9170_set_operating_mode(ar); mchash |= 1ULL << (mclist->dmi_addr[5] >> 2);
if (err) mclist = mclist->next;
goto unlock;
} }
if (test_and_clear_bit(AR9170_FILTER_CHANGED_MULTICAST, return mchash;
&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);
} }
static void ar9170_op_configure_filter(struct ieee80211_hw *hw, static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *new_flags, unsigned int *new_flags,
int mc_count, struct dev_mc_list *mclist) u64 multicast)
{ {
struct ar9170 *ar = hw->priv; struct ar9170 *ar = hw->priv;
if (unlikely(!IS_ACCEPTING_CMD(ar)))
return ;
mutex_lock(&ar->mutex);
/* mask supported flags */ /* mask supported flags */
*new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC | *new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC |
FIF_PROMISC_IN_BSS | FIF_FCSFAIL | FIF_PLCPFAIL; 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. * then checking the error flags, later.
*/ */
if (changed_flags & FIF_ALLMULTI) { if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI)
if (*new_flags & FIF_ALLMULTI) { multicast = ~0ULL;
ar->want_mc_hash = ~0ULL;
} else {
u64 mchash;
int i;
/* always get broadcast frames */ if (multicast != ar->cur_mc_hash)
mchash = 1ULL << (0xff >> 2); ar9170_update_multicast(ar, multicast);
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 (changed_flags & FIF_CONTROL) { if (changed_flags & FIF_CONTROL) {
u32 filter = AR9170_MAC_REG_FTF_PSPOLL | 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; AR9170_MAC_REG_FTF_CFE_ACK;
if (*new_flags & FIF_CONTROL) if (*new_flags & FIF_CONTROL)
ar->want_filter = ar->cur_filter | filter; filter |= ar->cur_filter;
else else
ar->want_filter = ar->cur_filter & ~filter; filter &= (~ar->cur_filter);
set_bit(AR9170_FILTER_CHANGED_FRAMEFILTER, ar9170_update_frame_filter(ar, filter);
&ar->filter_changed);
} }
if (changed_flags & FIF_PROMISC_IN_BSS) { if (changed_flags & FIF_PROMISC_IN_BSS) {
ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0; ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0;
set_bit(AR9170_FILTER_CHANGED_MODE, ar9170_set_operating_mode(ar);
&ar->filter_changed);
} }
if (likely(IS_STARTED(ar))) mutex_unlock(&ar->mutex);
ieee80211_queue_work(ar->hw, &ar->filter_config_work);
} }
static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf, struct ieee80211_bss_conf *bss_conf,
@ -2417,9 +2384,6 @@ static void ar9170_sta_notify(struct ieee80211_hw *hw,
default: default:
break; 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, 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, .add_interface = ar9170_op_add_interface,
.remove_interface = ar9170_op_remove_interface, .remove_interface = ar9170_op_remove_interface,
.config = ar9170_op_config, .config = ar9170_op_config,
.prepare_multicast = ar9170_op_prepare_multicast,
.configure_filter = ar9170_op_configure_filter, .configure_filter = ar9170_op_configure_filter,
.conf_tx = ar9170_conf_tx, .conf_tx = ar9170_conf_tx,
.bss_info_changed = ar9170_op_bss_info_changed, .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]); skb_queue_head_init(&ar->tx_pending[i]);
} }
ar9170_rx_reset_rx_mpdu(ar); ar9170_rx_reset_rx_mpdu(ar);
INIT_WORK(&ar->filter_config_work, ar9170_set_filters);
INIT_WORK(&ar->beacon_work, ar9170_new_beacon); INIT_WORK(&ar->beacon_work, ar9170_new_beacon);
INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor);
INIT_LIST_HEAD(&ar->tx_ampdu_list); 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 RW 8 /* number of words to read at once */
#define RB (sizeof(u32) * RW) #define RB (sizeof(u32) * RW)
struct ath_regulatory *regulatory = &ar->common.regulatory;
u8 *eeprom = (void *)&ar->eeprom; u8 *eeprom = (void *)&ar->eeprom;
u8 *addr = ar->eeprom.mac_address; u8 *addr = ar->eeprom.mac_address;
__le32 offsets[RW]; __le32 offsets[RW];
@ -2700,8 +2665,8 @@ static int ar9170_read_eeprom(struct ar9170 *ar)
else else
ar->hw->channel_change_time = 80 * 1000; ar->hw->channel_change_time = 80 * 1000;
ar->regulatory.current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); 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_ext = le16_to_cpu(ar->eeprom.reg_domain[1]);
/* second part of wiphy init */ /* second part of wiphy init */
SET_IEEE80211_PERM_ADDR(ar->hw, addr); 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 ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct ar9170 *ar = hw->priv; 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) int ar9170_register(struct ar9170 *ar, struct device *pdev)
{ {
struct ath_regulatory *regulatory = &ar->common.regulatory;
int err; int err;
/* try to read EEPROM, init MAC addr */ /* try to read EEPROM, init MAC addr */
@ -2727,7 +2693,7 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev)
if (err) if (err)
goto err_out; goto err_out;
err = ath_regd_init(&ar->regulatory, ar->hw->wiphy, err = ath_regd_init(regulatory, ar->hw->wiphy,
ar9170_reg_notifier); ar9170_reg_notifier);
if (err) if (err)
goto err_out; goto err_out;
@ -2736,8 +2702,8 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev)
if (err) if (err)
goto err_out; goto err_out;
if (!ath_is_world_regd(&ar->regulatory)) if (!ath_is_world_regd(regulatory))
regulatory_hint(ar->hw->wiphy, ar->regulatory.alpha2); regulatory_hint(ar->hw->wiphy, regulatory->alpha2);
err = ar9170_init_leds(ar); err = ar9170_init_leds(ar);
if (err) if (err)

View File

@ -19,8 +19,26 @@
#include <linux/skbuff.h> #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 { struct ath_common {
u16 cachelsz; u16 cachelsz;
struct ath_regulatory regulatory;
}; };
struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,

View File

@ -27,8 +27,6 @@
#include <linux/types.h> #include <linux/types.h>
#include <net/mac80211.h> #include <net/mac80211.h>
#include "../regd.h"
/* RX/TX descriptor hw structs /* RX/TX descriptor hw structs
* TODO: Driver part should only see sw structs */ * TODO: Driver part should only see sw structs */
#include "desc.h" #include "desc.h"
@ -1077,7 +1075,6 @@ struct ath5k_hw {
int ah_gpio_npins; int ah_gpio_npins;
struct ath_regulatory ah_regulatory;
struct ath5k_capabilities ah_capabilities; struct ath5k_capabilities ah_capabilities;
struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES]; 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, static void ath5k_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf); struct ieee80211_if_init_conf *conf);
static int ath5k_config(struct ieee80211_hw *hw, u32 changed); 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, static void ath5k_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *new_flags, unsigned int *new_flags,
int mc_count, struct dev_mc_list *mclist); u64 multicast);
static int ath5k_set_key(struct ieee80211_hw *hw, static int ath5k_set_key(struct ieee80211_hw *hw,
enum set_key_cmd cmd, enum set_key_cmd cmd,
struct ieee80211_vif *vif, struct ieee80211_sta *sta, 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, .add_interface = ath5k_add_interface,
.remove_interface = ath5k_remove_interface, .remove_interface = ath5k_remove_interface,
.config = ath5k_config, .config = ath5k_config,
.prepare_multicast = ath5k_prepare_multicast,
.configure_filter = ath5k_configure_filter, .configure_filter = ath5k_configure_filter,
.set_key = ath5k_set_key, .set_key = ath5k_set_key,
.get_stats = ath5k_get_stats, .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 ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct ath5k_softc *sc = hw->priv; 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 static int
@ -725,6 +728,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
{ {
struct ath5k_softc *sc = hw->priv; struct ath5k_softc *sc = hw->priv;
struct ath5k_hw *ah = sc->ah; struct ath5k_hw *ah = sc->ah;
struct ath_regulatory *regulatory = &sc->common.regulatory;
u8 mac[ETH_ALEN] = {}; u8 mac[ETH_ALEN] = {};
int ret; int ret;
@ -814,9 +818,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
memset(sc->bssidmask, 0xff, ETH_ALEN); memset(sc->bssidmask, 0xff, ETH_ALEN);
ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
ah->ah_regulatory.current_rd = regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain;
ah->ah_capabilities.cap_eeprom.ee_regdomain; ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier);
ret = ath_regd_init(&ah->ah_regulatory, hw->wiphy, ath5k_reg_notifier);
if (ret) { if (ret) {
ATH5K_ERR(sc, "can't initialize regulatory system\n"); ATH5K_ERR(sc, "can't initialize regulatory system\n");
goto err_queues; goto err_queues;
@ -828,8 +831,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
goto err_queues; goto err_queues;
} }
if (!ath_is_world_regd(&sc->ah->ah_regulatory)) if (!ath_is_world_regd(regulatory))
regulatory_hint(hw->wiphy, sc->ah->ah_regulatory.alpha2); regulatory_hint(hw->wiphy, regulatory->alpha2);
ath5k_init_leds(sc); ath5k_init_leds(sc);
@ -2853,6 +2856,37 @@ unlock:
return ret; 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 \ #define SUPPORTED_FIF_FLAGS \
FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \
FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
@ -2878,16 +2912,14 @@ unlock:
static void ath5k_configure_filter(struct ieee80211_hw *hw, static void ath5k_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *new_flags, unsigned int *new_flags,
int mc_count, struct dev_mc_list *mclist) u64 multicast)
{ {
struct ath5k_softc *sc = hw->priv; struct ath5k_softc *sc = hw->priv;
struct ath5k_hw *ah = sc->ah; struct ath5k_hw *ah = sc->ah;
u32 mfilt[2], val, rfilt; u32 mfilt[2], rfilt;
u8 pos;
int i;
mfilt[0] = 0; mfilt[0] = multicast;
mfilt[1] = 0; mfilt[1] = multicast >> 32;
/* Only deal with supported flags */ /* Only deal with supported flags */
changed_flags &= SUPPORTED_FIF_FLAGS; changed_flags &= SUPPORTED_FIF_FLAGS;
@ -2913,24 +2945,6 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
if (*new_flags & FIF_ALLMULTI) { if (*new_flags & FIF_ALLMULTI) {
mfilt[0] = ~0; mfilt[0] = ~0;
mfilt[1] = ~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 */ /* This is the best we can do */

View File

@ -50,6 +50,8 @@
#include "ath5k.h" #include "ath5k.h"
#include "debug.h" #include "debug.h"
#include "../regd.h"
#include "../ath.h" #include "../ath.h"
#define ATH_RXBUF 40 /* number of RX buffers */ #define ATH_RXBUF 40 /* number of RX buffers */
@ -200,4 +202,15 @@ struct ath5k_softc {
#define ath5k_hw_hasveol(_ah) \ #define ath5k_hw_hasveol(_ah) \
(ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0) (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 #endif

View File

@ -2198,6 +2198,7 @@ static void
ath5k_get_max_ctl_power(struct ath5k_hw *ah, ath5k_get_max_ctl_power(struct ath5k_hw *ah,
struct ieee80211_channel *channel) struct ieee80211_channel *channel)
{ {
struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
struct ath5k_edge_power *rep = ee->ee_ctl_pwr; struct ath5k_edge_power *rep = ee->ee_ctl_pwr;
u8 *ctl_val = ee->ee_ctl; u8 *ctl_val = ee->ee_ctl;
@ -2208,7 +2209,7 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah,
u8 ctl_idx = 0xFF; u8 ctl_idx = 0xFF;
u32 target = channel->center_freq; 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) { switch (channel->hw_value & CHANNEL_MODES) {
case CHANNEL_A: 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, void ath9k_hw_ani_monitor(struct ath_hw *ah,
const struct ath9k_node_stats *stats,
struct ath9k_channel *chan) struct ath9k_channel *chan)
{ {
struct ar5416AniState *aniState; struct ar5416AniState *aniState;
@ -550,7 +549,6 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
return; return;
aniState = ah->curani; aniState = ah->curani;
ah->stats.ast_nodestats = *stats;
listenTime = ath9k_hw_ani_get_listen_time(ah); listenTime = ath9k_hw_ani_get_listen_time(ah);
if (listenTime < 0) { 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 * any of the MIB counters overflow/trigger so don't assume we're
* here because a PHY error counter triggered. * here because a PHY error counter triggered.
*/ */
void ath9k_hw_procmibevent(struct ath_hw *ah, void ath9k_hw_procmibevent(struct ath_hw *ah)
const struct ath9k_node_stats *stats)
{ {
u32 phyCnt1, phyCnt2; 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 */ /* Clear the mib counters and save them in the stats */
ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
ah->stats.ast_nodestats = *stats;
if (!DO_ANI(ah)) if (!DO_ANI(ah))
return; return;

View File

@ -18,15 +18,10 @@
#define ANI_H #define ANI_H
#define HAL_PROCESS_ANI 0x00000001 #define HAL_PROCESS_ANI 0x00000001
#define ATH9K_RSSI_EP_MULTIPLIER (1<<7)
#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI)) #define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI))
#define HAL_EP_RND(x, mul) \ #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi)
((((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 ATH9K_ANI_OFDM_TRIG_HIGH 500 #define ATH9K_ANI_OFDM_TRIG_HIGH 500
#define ATH9K_ANI_OFDM_TRIG_LOW 200 #define ATH9K_ANI_OFDM_TRIG_LOW 200
@ -65,13 +60,6 @@ struct ath9k_mib_stats {
u32 beacons; u32 beacons;
}; };
struct ath9k_node_stats {
u32 ns_avgbrssi;
u32 ns_avgrssi;
u32 ns_avgtxrssi;
u32 ns_avgtxrate;
};
struct ar5416AniState { struct ar5416AniState {
struct ath9k_channel *c; struct ath9k_channel *c;
u8 noiseImmunityLevel; u8 noiseImmunityLevel;
@ -115,21 +103,19 @@ struct ar5416Stats {
u32 ast_ani_reset; u32 ast_ani_reset;
u32 ast_ani_lzero; u32 ast_ani_lzero;
u32 ast_ani_lneg; u32 ast_ani_lneg;
u32 avgbrssi;
struct ath9k_mib_stats ast_mibstats; struct ath9k_mib_stats ast_mibstats;
struct ath9k_node_stats ast_nodestats;
}; };
#define ah_mibStats stats.ast_mibstats #define ah_mibStats stats.ast_mibstats
void ath9k_ani_reset(struct ath_hw *ah); void ath9k_ani_reset(struct ath_hw *ah);
void ath9k_hw_ani_monitor(struct ath_hw *ah, void ath9k_hw_ani_monitor(struct ath_hw *ah,
const struct ath9k_node_stats *stats,
struct ath9k_channel *chan); struct ath9k_channel *chan);
void ath9k_enable_mib_counters(struct ath_hw *ah); void ath9k_enable_mib_counters(struct ath_hw *ah);
void ath9k_hw_disable_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 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt,
u32 *rxf_pcnt, u32 *txf_pcnt); u32 *rxf_pcnt, u32 *txf_pcnt);
void ath9k_hw_procmibevent(struct ath_hw *ah, void ath9k_hw_procmibevent(struct ath_hw *ah);
const struct ath9k_node_stats *stats);
void ath9k_hw_ani_setup(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_init(struct ath_hw *ah);
void ath9k_hw_ani_disable(struct ath_hw *ah); void ath9k_hw_ani_disable(struct ath_hw *ah);

View File

@ -454,7 +454,8 @@ struct ath_ani {
/* LED Control */ /* 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_ON_DURATION_IDLE 350 /* in msecs */
#define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ #define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */
@ -602,7 +603,6 @@ struct ath_softc {
int beacon_interval; int beacon_interval;
struct ath_ani ani; struct ath_ani ani;
struct ath9k_node_stats nodestats;
#ifdef CONFIG_ATH9K_DEBUG #ifdef CONFIG_ATH9K_DEBUG
struct ath9k_debug debug; struct ath9k_debug debug;
#endif #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_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
int ath_cabq_update(struct ath_softc *); 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) static inline void ath_read_cachesize(struct ath_softc *sc, int *csz)
{ {
sc->bus_ops->read_cachesize(sc, 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) static void ath9k_olc_temp_compensation(struct ath_hw *ah)
{ {
u32 rddata, i; u32 rddata, i;
int delta, currPDADC, regval; int delta, currPDADC, regval, slope;
rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); 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) { if (OLC_FOR_AR9287_10_LATER) {
ah->PDADCdelta = delta; if (ah->initPDADC == 0 || currPDADC == 0) {
for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { return;
regval = ah->originalGain[i] - delta; } else {
if (regval < 0) slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
regval = 0; 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, if (delta != ah->PDADCdelta) {
AR_PHY_TX_GAIN, regval); 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)) == \ || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL)) ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
int i; int i;
int16_t twiceLargestAntenna; int16_t twiceLargestAntenna;
u16 twiceMinEdgePower; u16 twiceMinEdgePower;
@ -541,9 +542,9 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
twiceLargestAntenna, 0); twiceLargestAntenna, 0);
maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) { if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
maxRegAllowedPower -= maxRegAllowedPower -=
(tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
} }
scaledPower = min(powerLimit, maxRegAllowedPower); scaledPower = min(powerLimit, maxRegAllowedPower);
@ -707,6 +708,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
u8 twiceMaxRegulatoryPower, u8 twiceMaxRegulatoryPower,
u8 powerLimit) u8 powerLimit)
{ {
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
struct modal_eep_4k_header *pModal = &pEepData->modalHeader; struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
int16_t ratesArray[Ar5416RateSize]; 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)) else if (IS_CHAN_HT20(chan))
i = rateHt20_0; i = rateHt20_0;
ah->regulatory.max_power_level = ratesArray[i]; regulatory->max_power_level = ratesArray[i];
if (AR_SREV_9280_10_OR_LATER(ah)) { if (AR_SREV_9280_10_OR_LATER(ah)) {
for (i = 0; i < Ar5416RateSize; i++) 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, u8 *pCalChans, u16 availPiers,
int8_t *pPwr) int8_t *pPwr)
{ {
u8 pcdac, i = 0;
u16 idxL = 0, idxR = 0, numPiers; u16 idxL = 0, idxR = 0, numPiers;
bool match; bool match;
struct chan_centers centers; struct chan_centers centers;
@ -392,17 +391,12 @@ static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah,
&idxL, &idxR); &idxL, &idxR);
if (match) { if (match) {
pcdac = pRawDatasetOpLoop[idxL].pcdac[0][0]; *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0];
*pPwr = pRawDatasetOpLoop[idxL].pwrPdg[0][0];
} else { } else {
pcdac = pRawDatasetOpLoop[idxR].pcdac[0][0]; *pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] +
*pPwr = (pRawDatasetOpLoop[idxL].pwrPdg[0][0] + (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
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, 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_TWO_CHAIN 6
#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
static const u16 tpScaleReductionTable[5] = static const u16 tpScaleReductionTable[5] =
{ 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; { 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); twiceLargestAntenna, 0);
maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX)
maxRegAllowedPower -= maxRegAllowedPower -=
(tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
scaledPower = min(powerLimit, maxRegAllowedPower); 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_TWO_CHAIN 6
#define INCREASE_MAXPOW_BY_THREE_CHAIN 10 #define INCREASE_MAXPOW_BY_THREE_CHAIN 10
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
int16_t ratesArray[Ar5416RateSize]; int16_t ratesArray[Ar5416RateSize];
@ -955,20 +949,20 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah,
i = rate6mb; i = rate6mb;
if (AR_SREV_9280_10_OR_LATER(ah)) 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; ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
else else
ah->regulatory.max_power_level = ratesArray[i]; regulatory->max_power_level = ratesArray[i];
switch (ar5416_get_ntxchains(ah->txchainmask)) { switch (ar5416_get_ntxchains(ah->txchainmask)) {
case 1: case 1:
break; break;
case 2: case 2:
ah->regulatory.max_power_level += regulatory->max_power_level +=
INCREASE_MAXPOW_BY_TWO_CHAIN; INCREASE_MAXPOW_BY_TWO_CHAIN;
break; break;
case 3: case 3:
ah->regulatory.max_power_level += regulatory->max_power_level +=
INCREASE_MAXPOW_BY_THREE_CHAIN; INCREASE_MAXPOW_BY_THREE_CHAIN;
break; break;
default: 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_TWO_CHAIN 6 /* 10*log10(2)*2 */
#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*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; struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
static const u16 tpScaleReductionTable[5] = 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; maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) { if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
maxRegAllowedPower -= maxRegAllowedPower -=
(tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
} }
scaledPower = min(powerLimit, maxRegAllowedPower); scaledPower = min(powerLimit, maxRegAllowedPower);
@ -1163,6 +1164,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
u8 powerLimit) u8 powerLimit)
{ {
#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) #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 ar5416_eeprom_def *pEepData = &ah->eeprom.def;
struct modal_eep_header *pModal = struct modal_eep_header *pModal =
&(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]); &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
@ -1292,19 +1294,19 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
i = rateHt20_0; i = rateHt20_0;
if (AR_SREV_9280_10_OR_LATER(ah)) if (AR_SREV_9280_10_OR_LATER(ah))
ah->regulatory.max_power_level = regulatory->max_power_level =
ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2; ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
else else
ah->regulatory.max_power_level = ratesArray[i]; regulatory->max_power_level = ratesArray[i];
switch(ar5416_get_ntxchains(ah->txchainmask)) { switch(ar5416_get_ntxchains(ah->txchainmask)) {
case 1: case 1:
break; break;
case 2: case 2:
ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
break; break;
case 3: case 3:
ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
break; break;
default: default:
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, 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) 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->hw_version.magic = AR5416_MAGIC;
ah->regulatory.country_code = CTRY_DEFAULT;
ah->hw_version.subvendorid = 0; ah->hw_version.subvendorid = 0;
ah->ah_flags = 0; ah->ah_flags = 0;
@ -449,8 +454,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
if (!AR_SREV_9100(ah)) if (!AR_SREV_9100(ah))
ah->ah_flags = AH_USE_EEPROM; 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->atim_window = 0;
ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE; ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE;
ah->beacon_interval = 100; ah->beacon_interval = 100;
@ -1332,11 +1335,21 @@ static void ath9k_olc_init(struct ath_hw *ah)
{ {
u32 i; u32 i;
for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) if (OLC_FOR_AR9287_10_LATER) {
ah->originalGain[i] = REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9,
MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4), AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL);
AR_PHY_TX_GAIN); ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TXPC0,
ah->PDADCdelta = 0; 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, 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, struct ath9k_channel *chan,
enum ath9k_ht_macmode macmode) enum ath9k_ht_macmode macmode)
{ {
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
int i, regWrites = 0; int i, regWrites = 0;
struct ieee80211_channel *channel = chan->chan; struct ieee80211_channel *channel = chan->chan;
u32 modesIndex, freqIndex; u32 modesIndex, freqIndex;
@ -1464,11 +1478,11 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
ath9k_olc_init(ah); ath9k_olc_init(ah);
ah->eep_ops->set_txpower(ah, chan, 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_antenna_gain * 2,
channel->max_power * 2, channel->max_power * 2,
min((u32) MAX_RATE_POWER, min((u32) MAX_RATE_POWER,
(u32) ah->regulatory.power_limit)); (u32) regulatory->power_limit));
if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
DPRINTF(ah->ah_sc, ATH_DBG_FATAL, 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, struct ath9k_channel *chan,
enum ath9k_ht_macmode macmode) enum ath9k_ht_macmode macmode)
{ {
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ieee80211_channel *channel = chan->chan; struct ieee80211_channel *channel = chan->chan;
u32 synthDelay, qnum; u32 synthDelay, qnum;
@ -1818,11 +1833,11 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
} }
ah->eep_ops->set_txpower(ah, chan, 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_antenna_gain * 2,
channel->max_power * 2, channel->max_power * 2,
min((u32) MAX_RATE_POWER, 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; synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
if (IS_CHAN_B(chan)) 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)) if (AR_SREV_9280_10_OR_LATER(ah))
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); 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 */ /* Enable ASYNC FIFO */
REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); 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); 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, REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR); AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
REG_WRITE(ah, AR_D_GBL_IFS_SLOT, 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, REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL); 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, REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
AR_PCU_MISC_MODE2_ENABLE_AGGWEP); 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) { if (ah->config.pcie_waen) {
REG_WRITE(ah, AR_WA, ah->config.pcie_waen); REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
} else { } 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); REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT);
/* /*
* On AR9280 chips bit 22 of 0x4004 needs to be set to * 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) void ath9k_hw_fill_cap_info(struct ath_hw *ah)
{ {
struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath9k_hw_capabilities *pCap = &ah->caps;
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
u16 capField = 0, eeval; u16 capField = 0, eeval;
eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); 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); eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1);
if (AR_SREV_9285_10_OR_LATER(ah)) if (AR_SREV_9285_10_OR_LATER(ah))
eeval |= AR9285_RDEXT_DEFAULT; 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); capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP);
if (ah->opmode != NL80211_IFTYPE_AP && if (ah->opmode != NL80211_IFTYPE_AP &&
ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) { ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) {
if (ah->regulatory.current_rd == 0x64 || if (regulatory->current_rd == 0x64 ||
ah->regulatory.current_rd == 0x65) regulatory->current_rd == 0x65)
ah->regulatory.current_rd += 5; regulatory->current_rd += 5;
else if (ah->regulatory.current_rd == 0x41) else if (regulatory->current_rd == 0x41)
ah->regulatory.current_rd = 0x43; regulatory->current_rd = 0x43;
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, 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); 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 else
pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; 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 = pCap->reg_cap =
AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | 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, bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
u32 capability, u32 *result) u32 capability, u32 *result)
{ {
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
switch (type) { switch (type) {
case ATH9K_CAP_CIPHER: case ATH9K_CAP_CIPHER:
switch (capability) { switch (capability) {
@ -3702,13 +3720,13 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
case 0: case 0:
return 0; return 0;
case 1: case 1:
*result = ah->regulatory.power_limit; *result = regulatory->power_limit;
return 0; return 0;
case 2: case 2:
*result = ah->regulatory.max_power_level; *result = regulatory->max_power_level;
return 0; return 0;
case 3: case 3:
*result = ah->regulatory.tp_scale; *result = regulatory->tp_scale;
return 0; return 0;
} }
return false; 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) 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 ath9k_channel *chan = ah->curchan;
struct ieee80211_channel *channel = chan->chan; 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, 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_antenna_gain * 2,
channel->max_power * 2, channel->max_power * 2,
min((u32) MAX_RATE_POWER, 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) 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_hw_version hw_version;
struct ath9k_ops_config config; struct ath9k_ops_config config;
struct ath9k_hw_capabilities caps; struct ath9k_hw_capabilities caps;
struct ath_regulatory regulatory;
struct ath9k_channel channels[38]; struct ath9k_channel channels[38];
struct ath9k_channel *curchan; struct ath9k_channel *curchan;
@ -522,6 +521,7 @@ struct ath_hw {
u32 originalGain[22]; u32 originalGain[22];
int initPDADC; int initPDADC;
int PDADCdelta; int PDADCdelta;
u8 led_pin;
struct ar5416IniArray iniModes; struct ar5416IniArray iniModes;
struct ar5416IniArray iniCommon; struct ar5416IniArray iniCommon;

View File

@ -384,7 +384,7 @@ static void ath_ani_calibrate(unsigned long data)
if (longcal || shortcal || aniflag) { if (longcal || shortcal || aniflag) {
/* Call ANI routine if necessary */ /* Call ANI routine if necessary */
if (aniflag) if (aniflag)
ath9k_hw_ani_monitor(ah, &sc->nodestats, ah->curchan); ath9k_hw_ani_monitor(ah, ah->curchan);
/* Perform calibration if necessary */ /* Perform calibration if necessary */
if (longcal || shortcal) { if (longcal || shortcal) {
@ -589,7 +589,7 @@ irqreturn_t ath_isr(int irq, void *dev)
* it will clear whatever condition caused * it will clear whatever condition caused
* the interrupt. * the interrupt.
*/ */
ath9k_hw_procmibevent(ah, &sc->nodestats); ath9k_hw_procmibevent(ah);
ath9k_hw_set_interrupts(ah, sc->imask); 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); ath_beacon_config(sc, vif);
/* Reset rssi stats */ /* Reset rssi stats */
sc->nodestats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; sc->sc_ah->stats.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;
ath_start_ani(sc); ath_start_ani(sc);
} else { } 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) || if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
(sc->led_off_duration == ATH_LED_OFF_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 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); (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0);
ieee80211_queue_delayed_work(sc->hw, ieee80211_queue_delayed_work(sc->hw,
@ -1002,7 +999,7 @@ static void ath_led_brightness(struct led_classdev *led_cdev,
case LED_OFF: case LED_OFF:
if (led->led_type == ATH_LED_ASSOC || if (led->led_type == ATH_LED_ASSOC ||
led->led_type == ATH_LED_RADIO) { 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)); (led->led_type == ATH_LED_RADIO));
sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
if (led->led_type == ATH_LED_RADIO) 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, ieee80211_queue_delayed_work(sc->hw,
&sc->ath_led_blink_work, 0); &sc->ath_led_blink_work, 0);
} else if (led->led_type == ATH_LED_RADIO) { } 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; sc->sc_flags |= SC_OP_LED_ON;
} else { } else {
sc->led_on_cnt++; 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->tx_led);
ath_unregister_led(&sc->rx_led); ath_unregister_led(&sc->rx_led);
ath_unregister_led(&sc->radio_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) static void ath_init_leds(struct ath_softc *sc)
@ -1070,11 +1067,16 @@ static void ath_init_leds(struct ath_softc *sc)
char *trigger; char *trigger;
int ret; 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 */ /* 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); AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
/* LED off, active low */ /* 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); 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); ath9k_hw_set_interrupts(ah, sc->imask);
/* Enable LED */ /* Enable LED */
ath9k_hw_cfg_output(ah, ATH_LED_PIN, ath9k_hw_cfg_output(ah, ah->led_pin,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT); 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); ieee80211_wake_queues(sc->hw);
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
@ -1171,8 +1173,8 @@ void ath_radio_disable(struct ath_softc *sc)
ieee80211_stop_queues(sc->hw); ieee80211_stop_queues(sc->hw);
/* Disable LED */ /* Disable LED */
ath9k_hw_set_gpio(ah, ATH_LED_PIN, 1); ath9k_hw_set_gpio(ah, ah->led_pin, 1);
ath9k_hw_cfg_gpio_input(ah, ATH_LED_PIN); ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
/* Disable interrupts */ /* Disable interrupts */
ath9k_hw_set_interrupts(ah, 0); 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 ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct ath_wiphy *aphy = hw->priv; struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc; 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); 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); 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); ath9k_reg_notifier);
if (error) if (error)
return error; return error;
reg = &sc->sc_ah->regulatory; reg = &sc->common.regulatory;
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); 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_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc; struct ath_softc *sc = aphy->sc;
mutex_lock(&sc->mutex);
aphy->state = ATH_WIPHY_INACTIVE; aphy->state = ATH_WIPHY_INACTIVE;
cancel_delayed_work_sync(&sc->ath_led_blink_work); 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) { if (sc->sc_flags & SC_OP_INVALID) {
DPRINTF(sc, ATH_DBG_ANY, "Device not present\n"); DPRINTF(sc, ATH_DBG_ANY, "Device not present\n");
mutex_unlock(&sc->mutex);
return; return;
} }
mutex_lock(&sc->mutex);
cancel_delayed_work_sync(&sc->tx_complete_work);
if (ath9k_wiphy_started(sc)) { if (ath9k_wiphy_started(sc)) {
mutex_unlock(&sc->mutex); mutex_unlock(&sc->mutex);
return; /* another wiphy still in use */ return; /* another wiphy still in use */
@ -2389,8 +2390,7 @@ skip_chan_change:
static void ath9k_configure_filter(struct ieee80211_hw *hw, static void ath9k_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *total_flags, unsigned int *total_flags,
int mc_count, u64 multicast)
struct dev_mc_list *mclist)
{ {
struct ath_wiphy *aphy = hw->priv; struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc; 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_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc; 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_save_state(pdev);
pci_disable_device(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); pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
/* Enable LED */ /* 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); 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; 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_PWRCTRL9 0xa27C
#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 #define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00
#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 #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_TBL1 0xa300
#define AR_PHY_TX_GAIN 0x0007F000 #define AR_PHY_TX_GAIN 0x0007F000
#define AR_PHY_TX_GAIN_S 12 #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_VIT_MASK2_M_46_61 0xa3a0
#define AR_PHY_MASK2_M_31_45 0xa3a4 #define AR_PHY_MASK2_M_31_45 0xa3a4
#define AR_PHY_MASK2_M_16_30 0xa3a8 #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. */ /* Update Beacon RSSI, this is used by ANI. */
if (ieee80211_is_beacon(fc)) 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->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp);
rx_status->band = hw->conf.channel->band; rx_status->band = hw->conf.channel->band;

View File

@ -744,6 +744,7 @@
#define AR_SREV_VERSION_9287 0x180 #define AR_SREV_VERSION_9287 0x180
#define AR_SREV_REVISION_9287_10 0 #define AR_SREV_REVISION_9287_10 0
#define AR_SREV_REVISION_9287_11 1 #define AR_SREV_REVISION_9287_11 1
#define AR_SREV_REVISION_9287_12 2
#define AR_SREV_VERSION_9271 0x140 #define AR_SREV_VERSION_9271 0x140
#define AR_SREV_REVISION_9271_10 0 #define AR_SREV_REVISION_9271_10 0
#define AR_SREV_REVISION_9271_11 1 #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.macVersion == AR_SREV_VERSION_9287) && \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_11))) ((_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) \ #define AR_SREV_9271(_ah) \
(((_ah))->hw_version.macVersion == AR_SREV_VERSION_9271) (((_ah))->hw_version.macVersion == AR_SREV_VERSION_9271)
#define AR_SREV_9271_10(_ah) \ #define AR_SREV_9271_10(_ah) \

View File

@ -18,9 +18,10 @@
#define REGD_H #define REGD_H
#include <linux/nl80211.h> #include <linux/nl80211.h>
#include <net/cfg80211.h> #include <net/cfg80211.h>
#include "ath.h"
#define NO_CTL 0xff #define NO_CTL 0xff
#define SD_NO_CTL 0xE0 #define SD_NO_CTL 0xE0
#define NO_CTL 0xff #define NO_CTL 0xff
@ -47,29 +48,12 @@
#define CHANNEL_HALF_BW 10 #define CHANNEL_HALF_BW 10
#define CHANNEL_QUARTER_BW 5 #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 { struct country_code_to_enum_rd {
u16 countryCode; u16 countryCode;
u16 regDmnEnum; u16 regDmnEnum;
const char *isoName; 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 { enum CountryCode {
CTRY_ALBANIA = 8, CTRY_ALBANIA = 8,
CTRY_ALGERIA = 12, CTRY_ALGERIA = 12,

View File

@ -80,16 +80,16 @@ config B43_NPHY
SAY N. SAY N.
config B43_PHY_LP config B43_PHY_LP
bool "IEEE 802.11g LP-PHY support (BROKEN)" bool "Support for low-power (LP-PHY) devices (EXPERIMENTAL)"
depends on B43 && EXPERIMENTAL && BROKEN depends on B43 && EXPERIMENTAL
---help--- ---help---
Support for the LP-PHY. Support for the LP-PHY.
The LP-PHY is an IEEE 802.11g based PHY built into some notebooks The LP-PHY is a low-power PHY built into some notebooks
and embedded devices. and embedded devices. It supports 802.11a/g
(802.11a support is optional, and currently disabled).
THIS IS BROKEN AND DOES NOT WORK YET. This is heavily experimental, and probably will not work for you.
Say N unless you want to help debug the driver.
SAY N.
# This config option automatically enables b43 LEDS support, # This config option automatically enables b43 LEDS support,
# if it's possible. # 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]); header = &(ring->txhdr_cache[(slot / TX_SLOTS_PER_FRAME) * hdrsize]);
cookie = generate_cookie(ring, slot); cookie = generate_cookie(ring, slot);
err = b43_generate_txhdr(ring->dev, header, err = b43_generate_txhdr(ring->dev, header,
skb->data, skb->len, info, cookie); skb, info, cookie);
if (unlikely(err)) { if (unlikely(err)) {
ring->current_slot = old_top_slot; ring->current_slot = old_top_slot;
ring->used_slots = old_used_slots; ring->used_slots = old_used_slots;

View File

@ -477,7 +477,7 @@ static void lo_measure_setup(struct b43_wldev *dev,
} else } else
b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x0802); b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x0802);
if (phy->rev >= 2) if (phy->rev >= 2)
b43_dummy_transmission(dev); b43_dummy_transmission(dev, false, true);
b43_gphy_channel_switch(dev, 6, 0); b43_gphy_channel_switch(dev, 6, 0);
b43_radio_read16(dev, 0x51); /* dummy read */ b43_radio_read16(dev, 0x51); /* dummy read */
if (phy->type == B43_PHYTYPE_G) 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_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); 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; static int modparam_qos = 1;
module_param_named(qos, modparam_qos, int, 0444); module_param_named(qos, modparam_qos, int, 0444);
MODULE_PARM_DESC(qos, "Enable QOS support (default on)"); 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 /* 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_wl *wl = dev->wl;
struct b43_phy *phy = &dev->phy; struct b43_phy *phy = &dev->phy;
@ -707,19 +711,12 @@ void b43_dummy_transmission(struct b43_wldev *dev)
0x00000000, 0x00000000,
}; };
switch (phy->type) { if (ofdm) {
case B43_PHYTYPE_A:
max_loop = 0x1E; max_loop = 0x1E;
buffer[0] = 0x000201CC; buffer[0] = 0x000201CC;
break; } else {
case B43_PHYTYPE_B:
case B43_PHYTYPE_G:
max_loop = 0xFA; max_loop = 0xFA;
buffer[0] = 0x000B846E; buffer[0] = 0x000B846E;
break;
default:
B43_WARN_ON(1);
return;
} }
spin_lock_irq(&wl->irq_lock); spin_lock_irq(&wl->irq_lock);
@ -728,20 +725,35 @@ void b43_dummy_transmission(struct b43_wldev *dev)
for (i = 0; i < 5; i++) for (i = 0; i < 5; i++)
b43_ram_write(dev, i * 4, buffer[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, 0x0568, 0x0000);
b43_write16(dev, 0x07C0, 0x0000); if (dev->dev->id.revision < 11)
value = ((phy->type == B43_PHYTYPE_A) ? 1 : 0); b43_write16(dev, 0x07C0, 0x0000);
else
b43_write16(dev, 0x07C0, 0x0100);
value = (ofdm ? 0x41 : 0x40);
b43_write16(dev, 0x050C, value); 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, 0x0508, 0x0000);
b43_write16(dev, 0x050A, 0x0000); b43_write16(dev, 0x050A, 0x0000);
b43_write16(dev, 0x054C, 0x0000); b43_write16(dev, 0x054C, 0x0000);
b43_write16(dev, 0x056A, 0x0014); b43_write16(dev, 0x056A, 0x0014);
b43_write16(dev, 0x0568, 0x0826); b43_write16(dev, 0x0568, 0x0826);
b43_write16(dev, 0x0500, 0x0000); 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) if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
b43_radio_write16(dev, 0x0051, 0x0017); 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]); (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, static void do_key_write(struct b43_wldev *dev,
u8 index, u8 algorithm, u8 index, u8 algorithm,
const u8 *key, size_t key_len, const u8 *mac_addr) 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) if (index >= pairwise_keys_start)
keymac_write(dev, index, NULL); /* First zero out mac. */ 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) if (key)
memcpy(buf, key, key_len); memcpy(buf, key, key_len);
key_write(dev, index, algorithm, buf); key_write(dev, index, algorithm, buf);
@ -859,6 +963,15 @@ static int b43_key_write(struct b43_wldev *dev,
int i; int i;
int pairwise_keys_start; 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) if (key_len > B43_SEC_KEYSIZE)
return -EINVAL; return -EINVAL;
for (i = 0; i < ARRAY_SIZE(dev->key); i++) { 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); printk(" Algo: %04X/%02X", algo, key->algorithm);
if (index >= pairwise_keys_start) { 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, rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA,
((index - pairwise_keys_start) * 2) + 0); ((index - pairwise_keys_start) * 2) + 0);
rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA, 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"; filename = "ucode5";
else if ((rev >= 11) && (rev <= 12)) else if ((rev >= 11) && (rev <= 12))
filename = "ucode11"; filename = "ucode11";
else if (rev >= 13) else if (rev == 13)
filename = "ucode13"; filename = "ucode13";
else if (rev == 14)
filename = "ucode14";
else if (rev >= 15)
filename = "ucode15";
else else
goto err_no_ucode; goto err_no_ucode;
err = b43_do_request_fw(ctx, filename, &fw->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 else
goto err_no_initvals; goto err_no_initvals;
break; 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: default:
goto err_no_initvals; goto err_no_initvals;
} }
@ -2030,6 +2165,16 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
else else
goto err_no_initvals; goto err_no_initvals;
break; 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: default:
goto err_no_initvals; 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_A:
case B43_PHYTYPE_G: case B43_PHYTYPE_G:
case B43_PHYTYPE_N: 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_6MB, 1);
b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1); b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1);
b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 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) { switch (cmd) {
case SET_KEY: case SET_KEY:
if (algorithm == B43_SEC_ALGO_TKIP) { if (algorithm == B43_SEC_ALGO_TKIP &&
/* FIXME: No TKIP hardware encryption for now. */ (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE) ||
!modparam_hwtkip)) {
/* We support only pairwise key */
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto out_unlock; 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); b43_hf_read(dev) & ~B43_HF_USEDEFKEYS);
} }
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
if (algorithm == B43_SEC_ALGO_TKIP)
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
break; break;
case DISABLE_KEY: { case DISABLE_KEY: {
err = b43_key_clear(dev, key->hw_key_idx); err = b43_key_clear(dev, key->hw_key_idx);
@ -3646,7 +3796,7 @@ out_unlock:
static void b43_op_configure_filter(struct ieee80211_hw *hw, static void b43_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed, unsigned int *fflags, 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_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev; struct b43_wldev *dev = wl->current_dev;
@ -3785,7 +3935,7 @@ static int b43_phy_versioning(struct b43_wldev *dev)
#endif #endif
#ifdef CONFIG_B43_PHY_LP #ifdef CONFIG_B43_PHY_LP
case B43_PHYTYPE_LP: case B43_PHYTYPE_LP:
if (phy_rev > 1) if (phy_rev > 2)
unsupported = 1; unsupported = 1;
break; break;
#endif #endif
@ -3842,7 +3992,7 @@ static int b43_phy_versioning(struct b43_wldev *dev)
unsupported = 1; unsupported = 1;
break; break;
case B43_PHYTYPE_LP: case B43_PHYTYPE_LP:
if (radio_ver != 0x2062) if (radio_ver != 0x2062 && radio_ver != 0x2063)
unsupported = 1; unsupported = 1;
break; break;
default: default:
@ -4345,6 +4495,7 @@ static const struct ieee80211_ops b43_hw_ops = {
.bss_info_changed = b43_op_bss_info_changed, .bss_info_changed = b43_op_bss_info_changed,
.configure_filter = b43_op_configure_filter, .configure_filter = b43_op_configure_filter,
.set_key = b43_op_set_key, .set_key = b43_op_set_key,
.update_tkip_key = b43_op_update_tkip_key,
.get_stats = b43_op_get_stats, .get_stats = b43_op_get_stats,
.get_tx_stats = b43_op_get_tx_stats, .get_tx_stats = b43_op_get_tx_stats,
.get_tsf = b43_op_get_tsf, .get_tsf = b43_op_get_tsf,
@ -4480,9 +4631,12 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
case B43_PHYTYPE_A: case B43_PHYTYPE_A:
have_5ghz_phy = 1; have_5ghz_phy = 1;
break; 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_G:
case B43_PHYTYPE_N: case B43_PHYTYPE_N:
case B43_PHYTYPE_LP:
have_2ghz_phy = 1; have_2ghz_phy = 1;
break; break;
default: default:
@ -4497,7 +4651,8 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
} }
if (1 /* disable A-PHY */) { if (1 /* disable A-PHY */) {
/* FIXME: For now we disable the A-PHY on multi-PHY devices. */ /* 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_2ghz_phy = 1;
have_5ghz_phy = 0; 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); u64 b43_hf_read(struct b43_wldev *dev);
void b43_hf_write(struct b43_wldev *dev, u64 value); 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); 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, 0x04A1, 0xBFBF, tmp);
b43_phy_maskset(dev, 0x04A2, 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) 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, 0x04A0, 0xBFBF, 0x4040);
b43_phy_maskset(dev, 0x04A1, 0xBFBF, 0x4040); b43_phy_maskset(dev, 0x04A1, 0xBFBF, 0x4040);
b43_phy_maskset(dev, 0x04A2, 0xBFBF, 0x4000); b43_phy_maskset(dev, 0x04A2, 0xBFBF, 0x4000);
b43_dummy_transmission(dev); b43_dummy_transmission(dev, false, true);
} }
/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ /* 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_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); gphy->cur_idle_tssi = b43_phy_read(dev, B43_PHY_ITSSI);
if (B43_DEBUG) { if (B43_DEBUG) {
/* Current-Idle-TSSI sanity check. */ /* 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; enum b43_lpphy_txpctl_mode txpctl_mode;
/* Transmit isolation medium band */ /* Transmit isolation medium band */
u8 tx_isolation_med_band; /* FIXME initial value? */ u8 tx_isolation_med_band;
/* Transmit isolation low band */ /* Transmit isolation low band */
u8 tx_isolation_low_band; /* FIXME initial value? */ u8 tx_isolation_low_band;
/* Transmit isolation high band */ /* Transmit isolation high band */
u8 tx_isolation_hi_band; /* FIXME initial value? */ u8 tx_isolation_hi_band;
/* Max transmit power medium band */ /* Max transmit power medium band */
u16 max_tx_pwr_med_band; u16 max_tx_pwr_med_band;
@ -848,7 +848,7 @@ struct b43_phy_lp {
s16 txpa[3], txpal[3], txpah[3]; s16 txpa[3], txpal[3], txpah[3];
/* Receive power offset */ /* Receive power offset */
u8 rx_pwr_offset; /* FIXME initial value? */ u8 rx_pwr_offset;
/* TSSI transmit count */ /* TSSI transmit count */
u16 tssi_tx_count; u16 tssi_tx_count;
@ -864,16 +864,16 @@ struct b43_phy_lp {
s8 tx_pwr_idx_over; /* FIXME initial value? */ s8 tx_pwr_idx_over; /* FIXME initial value? */
/* RSSI vf */ /* RSSI vf */
u8 rssi_vf; /* FIXME initial value? */ u8 rssi_vf;
/* RSSI vc */ /* RSSI vc */
u8 rssi_vc; /* FIXME initial value? */ u8 rssi_vc;
/* RSSI gs */ /* RSSI gs */
u8 rssi_gs; /* FIXME initial value? */ u8 rssi_gs;
/* RC cap */ /* RC cap */
u8 rc_cap; /* FIXME initial value? */ u8 rc_cap; /* FIXME initial value? */
/* BX arch */ /* BX arch */
u8 bx_arch; /* FIXME initial value? */ u8 bx_arch;
/* Full calibration channel */ /* Full calibration channel */
u8 full_calib_chan; /* FIXME initial value? */ u8 full_calib_chan; /* FIXME initial value? */
@ -884,8 +884,17 @@ struct b43_phy_lp {
/* Used for "Save/Restore Dig Filt State" */ /* Used for "Save/Restore Dig Filt State" */
u16 dig_flt_state[9]; 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; struct b43_phy_operations;
extern const struct b43_phy_operations b43_phyops_lp; 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); cookie = generate_cookie(q, pack);
hdrlen = b43_txhdr_size(q->dev); hdrlen = b43_txhdr_size(q->dev);
err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb->data, err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb,
skb->len, info, cookie); info, cookie);
if (err) if (err)
return 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.pad << 16;
tmp |= data.pga << 8; tmp |= data.pga << 8;
tmp |= data.gm; 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); b43_lptab_write(dev, B43_LPTAB32(7, 0xC0 + offset), tmp);
tmp = data.bb_mult << 20; tmp = data.bb_mult << 20;
tmp |= data.dac << 28; 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); backup = b43_ofdmtab_read16(dev, B43_OFDMTAB_PWRDYN2, 0);
b43_ofdmtab_write16(dev, B43_OFDMTAB_PWRDYN2, 0, 7); b43_ofdmtab_write16(dev, B43_OFDMTAB_PWRDYN2, 0, 7);
b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_APHY, 0, 0); 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); 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_WARN_ON(1);
} }
b43_wa_boards_g(dev); 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); B43_WARN_ON(1);
} }

View File

@ -180,11 +180,12 @@ static u8 b43_calc_fallback_rate(u8 bitrate)
/* Generate a TX data header. */ /* Generate a TX data header. */
int b43_generate_txhdr(struct b43_wldev *dev, int b43_generate_txhdr(struct b43_wldev *dev,
u8 *_txhdr, u8 *_txhdr,
const unsigned char *fragment_data, struct sk_buff *skb_frag,
unsigned int fragment_len,
struct ieee80211_tx_info *info, struct ieee80211_tx_info *info,
u16 cookie) 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; struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
const struct b43_phy *phy = &dev->phy; const struct b43_phy *phy = &dev->phy;
const struct ieee80211_hdr *wlhdr = 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) & mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
B43_TXH_MAC_KEYALG; B43_TXH_MAC_KEYALG;
wlhdr_len = ieee80211_hdrlen(fctl); wlhdr_len = ieee80211_hdrlen(fctl);
iv_len = min((size_t) info->control.hw_key->iv_len, if (key->algorithm == B43_SEC_ALGO_TKIP) {
ARRAY_SIZE(txhdr->iv)); u16 phase1key[5];
memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); 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)) { if (b43_is_old_txhdr_format(dev)) {
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp), 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; status.freq = chanid + 2400;
break; break;
case B43_PHYTYPE_N: case B43_PHYTYPE_N:
case B43_PHYTYPE_LP:
/* chanid is the SHM channel cookie. Which is the plain /* chanid is the SHM channel cookie. Which is the plain
* channel number in b43. */ * channel number in b43. */
if (chanstat & B43_RX_CHAN_5GHZ) { 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, int b43_generate_txhdr(struct b43_wldev *dev,
u8 * txhdr, u8 * txhdr,
const unsigned char *fragment_data, struct sk_buff *skb_frag,
unsigned int fragment_len,
struct ieee80211_tx_info *txctl, u16 cookie); struct ieee80211_tx_info *txctl, u16 cookie);
/* Transmit Status */ /* 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, static void b43legacy_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed, unsigned int changed,
unsigned int *fflags, unsigned int *fflags,u64 multicast)
int mc_count,
struct dev_addr_list *mc_list)
{ {
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev; struct b43legacy_wldev *dev = wl->current_dev;

View File

@ -185,7 +185,7 @@ MODULE_AUTHOR(DRV_COPYRIGHT);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static int debug = 0; static int debug = 0;
static int mode = 0; static int network_mode = 0;
static int channel = 0; static int channel = 0;
static int associate = 0; static int associate = 0;
static int disable = 0; static int disable = 0;
@ -195,7 +195,7 @@ static struct ipw2100_fw ipw2100_firmware;
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
module_param(debug, int, 0444); 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(channel, int, 0444);
module_param(associate, int, 0444); module_param(associate, int, 0444);
module_param(disable, int, 0444); module_param(disable, int, 0444);
@ -2844,7 +2844,7 @@ static int __ipw2100_tx_process(struct ipw2100_priv *priv)
#ifdef CONFIG_IPW2100_DEBUG #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, IPW_DEBUG_TX("TX%d V=%p P=%04X T=%04X L=%d\n", i,
&txq->drv[i], &txq->drv[i],
(u32) (txq->nic + i * sizeof(struct ipw2100_bd)), (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; priv->ieee->ieee802_1x = 1;
/* Set module parameters */ /* Set module parameters */
switch (mode) { switch (network_mode) {
case 1: case 1:
priv->ieee->iw_mode = IW_MODE_ADHOC; priv->ieee->iw_mode = IW_MODE_ADHOC;
break; break;
@ -8179,10 +8179,11 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev)
int rssi_qual; int rssi_qual;
int tx_qual; int tx_qual;
int beacon_qual; int beacon_qual;
int quality;
struct ipw2100_priv *priv = ieee80211_priv(dev); struct ipw2100_priv *priv = ieee80211_priv(dev);
struct iw_statistics *wstats; 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); u32 ord_len = sizeof(u32);
if (!priv) if (!priv)
@ -8265,7 +8266,8 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev)
beacon_qual = (20 - missed_beacons) * beacon_qual = (20 - missed_beacons) *
(PERFECT - VERY_GOOD) / 20 + VERY_GOOD; (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 #ifdef CONFIG_IPW2100_DEBUG
if (beacon_qual == quality) if (beacon_qual == quality)

View File

@ -83,13 +83,13 @@ MODULE_LICENSE("GPL");
static int cmdlog = 0; static int cmdlog = 0;
static int debug = 0; static int debug = 0;
static int channel = 0; static int default_channel = 0;
static int mode = 0; static int network_mode = 0;
static u32 ipw_debug_level; static u32 ipw_debug_level;
static int associate; static int associate;
static int auto_create = 1; static int auto_create = 1;
static int led = 0; static int led_support = 0;
static int disable = 0; static int disable = 0;
static int bt_coexist = 0; static int bt_coexist = 0;
static int hwcrypto = 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", IPW_DEBUG_STATS("Signal level : %3d%% (%d dBm)\n",
signal_quality, rssi); signal_quality, rssi);
quality = min(beacon_quality, quality = min(rx_quality, signal_quality);
min(rate_quality, quality = min(tx_quality, quality);
min(tx_quality, min(rx_quality, signal_quality)))); quality = min(rate_quality, quality);
quality = min(beacon_quality, quality);
if (quality == beacon_quality) if (quality == beacon_quality)
IPW_DEBUG_STATS("Quality (%d%%): Clamped to missed beacons.\n", IPW_DEBUG_STATS("Quality (%d%%): Clamped to missed beacons.\n",
quality); quality);
@ -4411,7 +4412,6 @@ static void ipw_rx_notification(struct ipw_priv *priv,
{ {
DECLARE_SSID_BUF(ssid); DECLARE_SSID_BUF(ssid);
u16 size = le16_to_cpu(notif->size); 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); 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) static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode)
{ {
/* TODO: Verify that this works... */ /* TODO: Verify that this works... */
struct ipw_fixed_rate fr = { struct ipw_fixed_rate fr;
.tx_rates = priv->rates_mask
};
u32 reg; u32 reg;
u16 mask = 0; u16 mask = 0;
u16 new_tx_rates = priv->rates_mask;
/* Identify 'current FW band' and match it with the fixed /* Identify 'current FW band' and match it with the fixed
* Tx rates */ * Tx rates */
@ -6117,54 +6116,56 @@ static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode)
/* Invalid fixed rate mask */ /* Invalid fixed rate mask */
IPW_DEBUG_WX IPW_DEBUG_WX
("invalid fixed rate mask in ipw_set_fixed_rate\n"); ("invalid fixed rate mask in ipw_set_fixed_rate\n");
fr.tx_rates = 0; new_tx_rates = 0;
break; break;
} }
fr.tx_rates >>= IEEE80211_OFDM_SHIFT_MASK_A; new_tx_rates >>= IEEE80211_OFDM_SHIFT_MASK_A;
break; break;
default: /* 2.4Ghz or Mixed */ default: /* 2.4Ghz or Mixed */
/* IEEE_B */ /* IEEE_B */
if (mode == 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 */ /* Invalid fixed rate mask */
IPW_DEBUG_WX IPW_DEBUG_WX
("invalid fixed rate mask in ipw_set_fixed_rate\n"); ("invalid fixed rate mask in ipw_set_fixed_rate\n");
fr.tx_rates = 0; new_tx_rates = 0;
} }
break; break;
} }
/* IEEE_G */ /* IEEE_G */
if (fr.tx_rates & ~(IEEE80211_CCK_RATES_MASK | if (new_tx_rates & ~(IEEE80211_CCK_RATES_MASK |
IEEE80211_OFDM_RATES_MASK)) { IEEE80211_OFDM_RATES_MASK)) {
/* Invalid fixed rate mask */ /* Invalid fixed rate mask */
IPW_DEBUG_WX IPW_DEBUG_WX
("invalid fixed rate mask in ipw_set_fixed_rate\n"); ("invalid fixed rate mask in ipw_set_fixed_rate\n");
fr.tx_rates = 0; new_tx_rates = 0;
break; 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); 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); 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); 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; break;
} }
fr.tx_rates = cpu_to_le16(new_tx_rates);
reg = ipw_read32(priv, IPW_MEM_FIXED_OVERRIDE); reg = ipw_read32(priv, IPW_MEM_FIXED_OVERRIDE);
ipw_write_reg32(priv, reg, *(u32 *) & fr); 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 */ /* Convert signal to DBM */
ipw_rt->rt_dbmsignal = antsignal; 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 */ /* Convert the channel data and set the flags */
ipw_rt->rt_channel = cpu_to_le16(ieee80211chan2mhz(received_channel)); 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; u16 channel = frame->received_channel;
u8 phy_flags = frame->antennaAndPhy; u8 phy_flags = frame->antennaAndPhy;
s8 signal = frame->rssi_dbm - IPW_RSSI_TO_DBM; 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; u8 rate = frame->rate;
short len = le16_to_cpu(pkt->u.frame.length); short len = le16_to_cpu(pkt->u.frame.length);
struct sk_buff *skb; struct sk_buff *skb;
@ -8335,7 +8336,7 @@ static void ipw_rx(struct ipw_priv *priv)
.rssi = pkt->u.frame.rssi_dbm - .rssi = pkt->u.frame.rssi_dbm -
IPW_RSSI_TO_DBM, IPW_RSSI_TO_DBM,
.signal = .signal =
le16_to_cpu(pkt->u.frame.rssi_dbm) - pkt->u.frame.rssi_dbm -
IPW_RSSI_TO_DBM + 0x100, IPW_RSSI_TO_DBM + 0x100,
.noise = .noise =
le16_to_cpu(pkt->u.frame.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 /* We default to disabling the LED code as right now it causes
* too many systems to lock up... */ * too many systems to lock up... */
if (!led) if (!led_support)
priv->config |= CFG_NO_LED; priv->config |= CFG_NO_LED;
if (associate) if (associate)
@ -8539,10 +8540,10 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option)
IPW_DEBUG_INFO("Radio disabled.\n"); IPW_DEBUG_INFO("Radio disabled.\n");
} }
if (channel != 0) { if (default_channel != 0) {
priv->config |= CFG_STATIC_CHANNEL; priv->config |= CFG_STATIC_CHANNEL;
priv->channel = channel; priv->channel = default_channel;
IPW_DEBUG_INFO("Bind to static channel %d\n", channel); IPW_DEBUG_INFO("Bind to static channel %d\n", default_channel);
/* TODO: Validate that provided channel is in range */ /* TODO: Validate that provided channel is in range */
} }
#ifdef CONFIG_IPW2200_QOS #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); burst_duration_CCK, burst_duration_OFDM);
#endif /* CONFIG_IPW2200_QOS */ #endif /* CONFIG_IPW2200_QOS */
switch (mode) { switch (network_mode) {
case 1: case 1:
priv->ieee->iw_mode = IW_MODE_ADHOC; priv->ieee->iw_mode = IW_MODE_ADHOC;
priv->net_dev->type = ARPHRD_ETHER; priv->net_dev->type = ARPHRD_ETHER;
@ -10181,7 +10182,6 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
#endif #endif
struct clx2_queue *q = &txq->q; struct clx2_queue *q = &txq->q;
u8 id, hdr_len, unicast; u8 id, hdr_len, unicast;
u16 remaining_bytes;
int fc; int fc;
if (!(priv->status & STATUS_ASSOCIATED)) 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.cmd_id = DINO_CMD_TX;
tfd->u.data.len = cpu_to_le16(txb->payload_size); tfd->u.data.len = cpu_to_le16(txb->payload_size);
remaining_bytes = txb->payload_size;
if (priv->assoc_request.ieee_mode == IPW_B_MODE) if (priv->assoc_request.ieee_mode == IPW_B_MODE)
tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_MODE_CCK; 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_param(auto_create, int, 0444);
MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)"); 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_PARM_DESC(led, "enable led control on some systems (default 0 off)");
module_param(debug, int, 0444); module_param(debug, int, 0444);
MODULE_PARM_DESC(debug, "debug output mask"); 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])"); MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])");
#ifdef CONFIG_IPW2200_PROMISCUOUS #ifdef CONFIG_IPW2200_PROMISCUOUS
@ -11978,10 +11977,10 @@ MODULE_PARM_DESC(burst_duration_OFDM, "set OFDM burst value");
#endif /* CONFIG_IPW2200_QOS */ #endif /* CONFIG_IPW2200_QOS */
#ifdef CONFIG_IPW2200_MONITOR #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)"); MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)");
#else #else
module_param(mode, int, 0444); module_param_named(mode, network_mode, int, 0444);
MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)"); MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)");
#endif #endif

View File

@ -149,12 +149,15 @@ struct iwl_cfg iwl1000_bgn_cfg = {
.ucode_api_min = IWL1000_UCODE_API_MIN, .ucode_api_min = IWL1000_UCODE_API_MIN,
.sku = IWL_SKU_G|IWL_SKU_N, .sku = IWL_SKU_G|IWL_SKU_N,
.ops = &iwl1000_ops, .ops = &iwl1000_ops,
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE, .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params, .mod_params = &iwl50_mod_params,
.valid_tx_ant = ANT_A, .valid_tx_ant = ANT_A,
.valid_rx_ant = ANT_AB, .valid_rx_ant = ANT_AB,
.need_pll_cfg = true, .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; struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
(int)sizeof(struct iwl3945_notif_statistics), (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)); 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, .eeprom_ver = EEPROM_3945_EEPROM_VERSION,
.ops = &iwl3945_ops, .ops = &iwl3945_ops,
.mod_params = &iwl3945_mod_params, .mod_params = &iwl3945_mod_params,
.use_isr_legacy = true .use_isr_legacy = true,
.ht_greenfield_support = false,
}; };
static struct iwl_cfg iwl3945_abg_cfg = { static struct iwl_cfg iwl3945_abg_cfg = {
@ -2902,7 +2904,8 @@ static struct iwl_cfg iwl3945_abg_cfg = {
.eeprom_ver = EEPROM_3945_EEPROM_VERSION, .eeprom_ver = EEPROM_3945_EEPROM_VERSION,
.ops = &iwl3945_ops, .ops = &iwl3945_ops,
.mod_params = &iwl3945_mod_params, .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[] = { 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, .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
.ops = &iwl4965_ops, .ops = &iwl4965_ops,
.mod_params = &iwl4965_mod_params, .mod_params = &iwl4965_mod_params,
.use_isr_legacy = true .use_isr_legacy = true,
.ht_greenfield_support = false,
}; };
/* Module firmware */ /* 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_rx_packet *pkt = (void *)rxb->skb->data;
struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; 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; int index;
/* reduce the size of the length field itself */ /* 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; vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;
/* now vt hold the temperature in Kelvin */ /* now vt hold the temperature in Kelvin */
priv->temperature = KELVIN_TO_CELSIUS(vt); priv->temperature = KELVIN_TO_CELSIUS(vt);
iwl_tt_handler(priv);
} }
/* Calc max signal level (dBm) among 3 possible receivers */ /* 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_tx_ant = ANT_ABC,
.valid_rx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC,
.need_pll_cfg = true, .need_pll_cfg = true,
.ht_greenfield_support = true,
}; };
struct iwl_cfg iwl5100_bg_cfg = { struct iwl_cfg iwl5100_bg_cfg = {
@ -1668,6 +1670,7 @@ struct iwl_cfg iwl5100_bg_cfg = {
.valid_tx_ant = ANT_B, .valid_tx_ant = ANT_B,
.valid_rx_ant = ANT_AB, .valid_rx_ant = ANT_AB,
.need_pll_cfg = true, .need_pll_cfg = true,
.ht_greenfield_support = true,
}; };
struct iwl_cfg iwl5100_abg_cfg = { struct iwl_cfg iwl5100_abg_cfg = {
@ -1684,6 +1687,7 @@ struct iwl_cfg iwl5100_abg_cfg = {
.valid_tx_ant = ANT_B, .valid_tx_ant = ANT_B,
.valid_rx_ant = ANT_AB, .valid_rx_ant = ANT_AB,
.need_pll_cfg = true, .need_pll_cfg = true,
.ht_greenfield_support = true,
}; };
struct iwl_cfg iwl5100_agn_cfg = { struct iwl_cfg iwl5100_agn_cfg = {
@ -1700,6 +1704,7 @@ struct iwl_cfg iwl5100_agn_cfg = {
.valid_tx_ant = ANT_B, .valid_tx_ant = ANT_B,
.valid_rx_ant = ANT_AB, .valid_rx_ant = ANT_AB,
.need_pll_cfg = true, .need_pll_cfg = true,
.ht_greenfield_support = true,
}; };
struct iwl_cfg iwl5350_agn_cfg = { struct iwl_cfg iwl5350_agn_cfg = {
@ -1716,6 +1721,7 @@ struct iwl_cfg iwl5350_agn_cfg = {
.valid_tx_ant = ANT_ABC, .valid_tx_ant = ANT_ABC,
.valid_rx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC,
.need_pll_cfg = true, .need_pll_cfg = true,
.ht_greenfield_support = true,
}; };
struct iwl_cfg iwl5150_agn_cfg = { struct iwl_cfg iwl5150_agn_cfg = {
@ -1732,6 +1738,7 @@ struct iwl_cfg iwl5150_agn_cfg = {
.valid_tx_ant = ANT_A, .valid_tx_ant = ANT_A,
.valid_rx_ant = ANT_AB, .valid_rx_ant = ANT_AB,
.need_pll_cfg = true, .need_pll_cfg = true,
.ht_greenfield_support = true,
}; };
MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); 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, .ucode_api_min = IWL6000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl6000_ops, .ops = &iwl6000_ops,
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE, .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params, .mod_params = &iwl50_mod_params,
@ -169,6 +169,9 @@ struct iwl_cfg iwl6000h_2agn_cfg = {
.valid_rx_ant = ANT_AB, .valid_rx_ant = ANT_AB,
.need_pll_cfg = false, .need_pll_cfg = false,
.pa_type = IWL_PA_HYBRID, .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, .ucode_api_min = IWL6000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl6000_ops, .ops = &iwl6000_ops,
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE, .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params, .mod_params = &iwl50_mod_params,
@ -189,6 +192,9 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
.valid_rx_ant = ANT_BC, .valid_rx_ant = ANT_BC,
.need_pll_cfg = false, .need_pll_cfg = false,
.pa_type = IWL_PA_INTERNAL, .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 = { struct iwl_cfg iwl6050_2agn_cfg = {
@ -198,7 +204,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
.ucode_api_min = IWL6050_UCODE_API_MIN, .ucode_api_min = IWL6050_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl6000_ops, .ops = &iwl6000_ops,
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE, .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params, .mod_params = &iwl50_mod_params,
@ -206,6 +212,9 @@ struct iwl_cfg iwl6050_2agn_cfg = {
.valid_rx_ant = ANT_AB, .valid_rx_ant = ANT_AB,
.need_pll_cfg = false, .need_pll_cfg = false,
.pa_type = IWL_PA_SYSTEM, .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 = { struct iwl_cfg iwl6000_3agn_cfg = {
@ -215,7 +224,7 @@ struct iwl_cfg iwl6000_3agn_cfg = {
.ucode_api_min = IWL6000_UCODE_API_MIN, .ucode_api_min = IWL6000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl6000_ops, .ops = &iwl6000_ops,
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE, .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params, .mod_params = &iwl50_mod_params,
@ -223,6 +232,9 @@ struct iwl_cfg iwl6000_3agn_cfg = {
.valid_rx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC,
.need_pll_cfg = false, .need_pll_cfg = false,
.pa_type = IWL_PA_SYSTEM, .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 = { struct iwl_cfg iwl6050_3agn_cfg = {
@ -232,7 +244,7 @@ struct iwl_cfg iwl6050_3agn_cfg = {
.ucode_api_min = IWL6050_UCODE_API_MIN, .ucode_api_min = IWL6050_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl6000_ops, .ops = &iwl6000_ops,
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE, .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params, .mod_params = &iwl50_mod_params,
@ -240,6 +252,9 @@ struct iwl_cfg iwl6050_3agn_cfg = {
.valid_rx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC,
.need_pll_cfg = false, .need_pll_cfg = false,
.pa_type = IWL_PA_SYSTEM, .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)); 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 } else
return MAX_TID_COUNT; return MAX_TID_COUNT;
if (unlikely(tid >= TID_MAX_LOAD_COUNT))
return MAX_TID_COUNT;
tl = &lq_data->load[tid]; tl = &lq_data->load[tid];
curr_time -= curr_time % TID_ROUND_VALUE; 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; return 1;
} }
/* in 4965 we don't use greenfield at all */ /**
static inline u8 rs_use_green(struct iwl_priv *priv, * Green-field mode is valid if the station supports it and
struct ieee80211_conf *conf) * 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; return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) &&
!(ht_conf->non_GF_STA_present);
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;
} }
/** /**
@ -1222,18 +1221,6 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
else else
tbl->is_ht40 = 0; 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); rs_set_expected_tpt_table(lq_sta, tbl);
rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); 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 else
tbl->is_ht40 = 0; 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); rs_set_expected_tpt_table(lq_sta, tbl);
rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); 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 else
tbl->is_ht40 = 0; 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) if (is_green)
tbl->is_SGI = 0; /*11n spec: no SGI in SISO+Greenfield*/ 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 = struct iwl_scale_tbl_info *search_tbl =
&(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
struct iwl_rate_scale_data *window = &(tbl->win[index]); 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) - u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action = tbl->action; u8 start_action = tbl->action;
@ -1586,13 +1550,11 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
goto out; goto out;
break; break;
case IWL_SISO_SWITCH_GI: case IWL_SISO_SWITCH_GI:
if (!tbl->is_ht40 && if (!tbl->is_ht40 && !(ht_cap->cap &
!(priv->current_ht_config.sgf & IEEE80211_HT_CAP_SGI_20))
HT_SHORT_GI_20MHZ))
break; break;
if (tbl->is_ht40 && if (tbl->is_ht40 && !(ht_cap->cap &
!(priv->current_ht_config.sgf & IEEE80211_HT_CAP_SGI_40))
HT_SHORT_GI_40MHZ))
break; break;
IWL_DEBUG_RATE(priv, "LQ: SISO toggle SGI/NGI\n"); 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 = struct iwl_scale_tbl_info *search_tbl =
&(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
struct iwl_rate_scale_data *window = &(tbl->win[index]); 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) - u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action = tbl->action; u8 start_action = tbl->action;
@ -1726,13 +1689,11 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
break; break;
case IWL_MIMO2_SWITCH_GI: case IWL_MIMO2_SWITCH_GI:
if (!tbl->is_ht40 && if (!tbl->is_ht40 && !(ht_cap->cap &
!(priv->current_ht_config.sgf & IEEE80211_HT_CAP_SGI_20))
HT_SHORT_GI_20MHZ))
break; break;
if (tbl->is_ht40 && if (tbl->is_ht40 && !(ht_cap->cap &
!(priv->current_ht_config.sgf & IEEE80211_HT_CAP_SGI_40))
HT_SHORT_GI_40MHZ))
break; break;
IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle SGI/NGI\n"); 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 = struct iwl_scale_tbl_info *search_tbl =
&(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
struct iwl_rate_scale_data *window = &(tbl->win[index]); 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) - u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action = tbl->action; u8 start_action = tbl->action;
@ -1890,13 +1852,11 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
break; break;
case IWL_MIMO3_SWITCH_GI: case IWL_MIMO3_SWITCH_GI:
if (!tbl->is_ht40 && if (!tbl->is_ht40 && !(ht_cap->cap &
!(priv->current_ht_config.sgf & IEEE80211_HT_CAP_SGI_20))
HT_SHORT_GI_20MHZ))
break; break;
if (tbl->is_ht40 && if (tbl->is_ht40 && !(ht_cap->cap &
!(priv->current_ht_config.sgf & IEEE80211_HT_CAP_SGI_40))
HT_SHORT_GI_40MHZ))
break; break;
IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle SGI/NGI\n"); 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)) if (is_legacy(tbl->lq_type))
lq_sta->is_green = 0; lq_sta->is_green = 0;
else 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; is_green = lq_sta->is_green;
/* current tx rate */ /* current tx rate */
@ -2466,7 +2426,7 @@ static void rs_initialize_lq(struct iwl_priv *priv,
int rate_idx; int rate_idx;
int i; int i;
u32 rate; 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 active_tbl = 0;
u8 valid_tx_ant; 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 ieee80211_supported_band *sband = txrc->sband;
struct iwl_priv *priv = (struct iwl_priv *)priv_r; struct iwl_priv *priv = (struct iwl_priv *)priv_r;
struct ieee80211_conf *conf = &priv->hw->conf; 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_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct iwl_lq_sta *lq_sta = priv_sta; 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", IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n",
hdr->addr1); hdr->addr1);
sta_id = iwl_add_station(priv, 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)) { if ((sta_id != IWL_INVALID_STATION)) {
lq_sta->lq.sta_id = sta_id; 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; int i, j;
struct iwl_priv *priv = (struct iwl_priv *)priv_r; struct iwl_priv *priv = (struct iwl_priv *)priv_r;
struct ieee80211_conf *conf = &priv->hw->conf; 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; struct iwl_lq_sta *lq_sta = priv_sta;
u16 mask_bit = 0; u16 mask_bit = 0;
int count; 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) { if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr);
sta_id = iwl_add_station(priv, sta->addr, false, sta_id = iwl_add_station(priv, sta->addr, false,
CMD_ASYNC, NULL); CMD_ASYNC, ht_cap);
} }
if ((sta_id != IWL_INVALID_STATION)) { if ((sta_id != IWL_INVALID_STATION)) {
lq_sta->lq.sta_id = sta_id; 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->is_dup = 0;
lq_sta->max_rate_idx = -1; lq_sta->max_rate_idx = -1;
lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; 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_legacy_rate = priv->active_rate & ~(0x1000);
lq_sta->active_rate_basic = priv->active_rate_basic; lq_sta->active_rate_basic = priv->active_rate_basic;
lq_sta->band = priv->band; 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), * 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. * 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 = 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] & 0x1;
lq_sta->active_siso_rate &= ~((u16)0x2); lq_sta->active_siso_rate &= ~((u16)0x2);
lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE;
/* Same here */ /* Same here */
lq_sta->active_mimo2_rate = sta->ht_cap.mcs.rx_mask[1] << 1; lq_sta->active_mimo2_rate = 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] & 0x1;
lq_sta->active_mimo2_rate &= ~((u16)0x2); lq_sta->active_mimo2_rate &= ~((u16)0x2);
lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; 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 = 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] & 0x1;
lq_sta->active_mimo3_rate &= ~((u16)0x2); lq_sta->active_mimo3_rate &= ~((u16)0x2);
lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE; 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_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_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_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_MSK (0x7 << 8)
#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8) #define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8)
@ -3481,7 +3482,7 @@ struct iwl_wimax_coex_cmd {
*****************************************************************************/ *****************************************************************************/
struct iwl_rx_packet { struct iwl_rx_packet {
__le32 len; __le32 len_n_flags;
struct iwl_cmd_header hdr; struct iwl_cmd_header hdr;
union { union {
struct iwl3945_rx_frame rx_frame; 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->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_SGI_20;
ht_info->cap |= (IEEE80211_HT_CAP_SM_PS & ht_info->cap |= (IEEE80211_HT_CAP_SM_PS &
(WLAN_HT_CAP_SM_PS_DISABLED << 2)); (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, void iwl_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *total_flags, unsigned int *total_flags,
int mc_count, struct dev_addr_list *mc_list) u64 multicast)
{ {
struct iwl_priv *priv = hw->priv; struct iwl_priv *priv = hw->priv;
__le32 *filter_flags = &priv->staging_rxon.filter_flags; __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 */ /* Firmware does not support this */
hw->wiphy->disable_beacon_hints = true; 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; hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
/* we create the 802.11 header and a zero-length SSID element */ /* we create the 802.11 header and a zero-length SSID element */
hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; 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_mem_buffer *rxb)
{ {
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; 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 " IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
"notification for %s:\n", "notification for %s:\n", len,
le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd)); get_cmd_string(pkt->hdr.cmd));
iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len)); iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
} }
EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif); 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; 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); iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2);
memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16);
iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0;
iwl_conf->ht_protection = iwl_conf->ht_protection =
bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
iwl_conf->non_GF_STA_present = 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; struct iwl_priv *priv = hw->priv;
const struct iwl_channel_info *ch_info; const struct iwl_channel_info *ch_info;
struct ieee80211_conf *conf = &hw->conf; struct ieee80211_conf *conf = &hw->conf;
struct iwl_ht_info *ht_conf = &priv->current_ht_config;
unsigned long flags = 0; unsigned long flags = 0;
int ret = 0; int ret = 0;
u16 ch; u16 ch;
@ -2777,10 +2757,32 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
goto set_ch_out; goto set_ch_out;
} }
priv->current_ht_config.is_ht = conf_is_ht(conf);
spin_lock_irqsave(&priv->lock, flags); 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 /* if we are switching from ht to 2.4 clear flags
* from any ht related info since 2.4 does not * 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_max: Highest version of uCode API supported by driver.
* @ucode_api_min: Lowest 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 * @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 * We enable the driver to be backward compatible wrt API version. The
* driver specifies which APIs it supports (with @ucode_api_max being 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 need_pll_cfg;
bool use_isr_legacy; bool use_isr_legacy;
enum iwl_pa_type pa_type; 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_irq_handle_error(struct iwl_priv *priv);
void iwl_configure_filter(struct ieee80211_hw *hw, void iwl_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *total_flags, unsigned int *total_flags, u64 multicast);
int mc_count, struct dev_addr_list *mc_list);
int iwl_hw_nic_init(struct iwl_priv *priv); int iwl_hw_nic_init(struct iwl_priv *priv);
int iwl_setup_mac(struct iwl_priv *priv); int iwl_setup_mac(struct iwl_priv *priv);
int iwl_set_hw_params(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 is_ht;
u8 supported_chan_width; u8 supported_chan_width;
u8 sm_ps; 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; struct ieee80211_mcs_info mcs;
/* BSS related data */ /* BSS related data */
u8 extension_chan_offset; u8 extension_chan_offset;
u8 tx_chan_width;
u8 ht_protection; u8 ht_protection;
u8 non_GF_STA_present; u8 non_GF_STA_present;
}; };
@ -732,9 +726,6 @@ struct iwl_dma_ptr {
size_t size; 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_20MHZ 0
#define IWL_CHANNEL_WIDTH_40MHZ 1 #define IWL_CHANNEL_WIDTH_40MHZ 1
@ -888,6 +879,17 @@ enum iwl_nvm_type {
NVM_DEVICE_TYPE_OTP, 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 * 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); 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) static int iwlcore_get_nvm_type(struct iwl_priv *priv)
{ {
u32 otpgp; u32 otpgp;
@ -252,6 +265,124 @@ static int iwl_init_otp_access(struct iwl_priv *priv)
return ret; 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 * iwl_eeprom_init - read EEPROM contents
* *
@ -266,15 +397,14 @@ int iwl_eeprom_init(struct iwl_priv *priv)
int sz; int sz;
int ret; int ret;
u16 addr; u16 addr;
u32 otpgp; u16 validblockaddr = 0;
u16 cache_addr = 0;
priv->nvm_device_type = iwlcore_get_nvm_type(priv); priv->nvm_device_type = iwlcore_get_nvm_type(priv);
if (priv->nvm_device_type == -ENOENT) if (priv->nvm_device_type == -ENOENT)
return -ENOENT; return -ENOENT;
/* allocate eeprom */ /* allocate eeprom */
if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) IWL_DEBUG_INFO(priv, "NVM size = %d\n", priv->cfg->eeprom_size);
priv->cfg->eeprom_size =
OTP_BLOCK_SIZE * OTP_LOWER_BLOCKS_TOTAL;
sz = priv->cfg->eeprom_size; sz = priv->cfg->eeprom_size;
priv->eeprom = kzalloc(sz, GFP_KERNEL); priv->eeprom = kzalloc(sz, GFP_KERNEL);
if (!priv->eeprom) { if (!priv->eeprom) {
@ -302,46 +432,31 @@ int iwl_eeprom_init(struct iwl_priv *priv)
if (ret) { if (ret) {
IWL_ERR(priv, "Failed to initialize OTP access.\n"); IWL_ERR(priv, "Failed to initialize OTP access.\n");
ret = -ENOENT; ret = -ENOENT;
goto err; goto done;
} }
_iwl_write32(priv, CSR_EEPROM_GP, _iwl_write32(priv, CSR_EEPROM_GP,
iwl_read32(priv, CSR_EEPROM_GP) & iwl_read32(priv, CSR_EEPROM_GP) &
~CSR_EEPROM_GP_IF_OWNER_MSK); ~CSR_EEPROM_GP_IF_OWNER_MSK);
/* clear */
_iwl_write32(priv, CSR_OTP_GP_REG, iwl_set_bit(priv, CSR_OTP_GP_REG,
iwl_read32(priv, CSR_OTP_GP_REG) |
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
/* traversing the linked list if no shadow ram supported */
for (addr = 0; addr < sz; addr += sizeof(u16)) { if (!priv->cfg->shadow_ram_support) {
u32 r; if (iwl_find_otp_image(priv, &validblockaddr)) {
ret = -ENOENT;
_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);
goto done; goto done;
} }
r = _iwl_read_direct32(priv, CSR_EEPROM_REG); }
/* check for ECC errors: */ for (addr = validblockaddr; addr < validblockaddr + sz;
otpgp = iwl_read32(priv, CSR_OTP_GP_REG); addr += sizeof(u16)) {
if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { u16 eeprom_data;
/* stop in this case */
IWL_ERR(priv, "Uncorrectable OTP ECC error, Abort OTP read\n"); ret = iwl_read_otp_word(priv, addr, &eeprom_data);
if (ret)
goto done; goto done;
} e[cache_addr / 2] = eeprom_data;
if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { cache_addr += sizeof(u16);
/* 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));
} }
} else { } else {
/* eeprom is an array of 16bit values */ /* eeprom is an array of 16bit values */
@ -484,14 +599,14 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
? # x " " : "") ? # 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. * 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, enum ieee80211_band band, u16 channel,
const struct iwl_eeprom_channel *eeprom_ch, const struct iwl_eeprom_channel *eeprom_ch,
u8 ht40_extension_channel) u8 clear_ht40_extension_channel)
{ {
struct iwl_channel_info *ch_info; 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_min_power = 0;
ch_info->ht40_scan_power = eeprom_ch->max_power_avg; ch_info->ht40_scan_power = eeprom_ch->max_power_avg;
ch_info->ht40_flags = eeprom_ch->flags; 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; 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 /* First write that ht40 is not enabled, and then enable
* one by one */ * one by one */
ch_info->ht40_extension_channel = ch_info->ht40_extension_channel =
(IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40;
IEEE80211_CHAN_NO_HT40MINUS);
if (!(is_channel_valid(ch_info))) { if (!(is_channel_valid(ch_info))) {
IWL_DEBUG_INFO(priv, "Ch. %d Flags %x [%sGHz] - " 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 */ /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */
for (band = 6; band <= 7; band++) { for (band = 6; band <= 7; band++) {
enum ieee80211_band ieeeband; enum ieee80211_band ieeeband;
u8 ht40_extension_chan;
iwl_init_band_reference(priv, band, &eeprom_ch_count, iwl_init_band_reference(priv, band, &eeprom_ch_count,
&eeprom_ch_info, &eeprom_ch_index); &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 */ /* Loop through each band adding each of the channels */
for (ch = 0; ch < eeprom_ch_count; ch++) { 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 */ /* 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_index[ch],
&(eeprom_ch_info[ch]), &eeprom_ch_info[ch],
ht40_extension_chan); IEEE80211_CHAN_NO_HT40PLUS);
/* Set up driver's info for upper half */ /* Set up driver's info for upper half */
iwl_set_ht40_chan_info(priv, ieeeband, iwl_mod_ht40_chan_info(priv, ieeeband,
(eeprom_ch_index[ch] + 4), eeprom_ch_index[ch] + 4,
&(eeprom_ch_info[ch]), &eeprom_ch_info[ch],
IEEE80211_CHAN_NO_HT40PLUS); IEEE80211_CHAN_NO_HT40MINUS);
} }
} }

View File

@ -180,8 +180,14 @@ struct iwl_eeprom_channel {
#define EEPROM_5050_EEPROM_VERSION (0x21E) #define EEPROM_5050_EEPROM_VERSION (0x21E)
/* OTP */ /* OTP */
#define OTP_LOWER_BLOCKS_TOTAL (3) /* lower blocks contain EEPROM image and calibration data */
#define OTP_BLOCK_SIZE (0x400) #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 */ /* 2.4 GHz */
extern const u8 iwl_eeprom_band_1[14]; 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; struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", 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 != change = ((priv->statistics.general.temperature !=
pkt->u.stats.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, static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
int include_phy, struct ieee80211_hdr *hdr,
struct iwl_rx_mem_buffer *rxb, u16 len,
struct ieee80211_rx_status *stats) 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 */ /* We only process data packets if the interface is open */
if (unlikely(!priv->is_open)) { if (unlikely(!priv->is_open)) {
IWL_DEBUG_DROP_LIMIT(priv, IWL_DEBUG_DROP_LIMIT(priv,
@ -915,13 +867,15 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
return; 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 && if (!priv->cfg->mod_params->sw_crypto &&
iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
return; 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); iwl_update_stats(priv, false, hdr->frame_control, len);
memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats)); memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
ieee80211_rx_irqsafe(priv->hw, rxb->skb); 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_hdr *header;
struct ieee80211_rx_status rx_status; struct ieee80211_rx_status rx_status;
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
/* Use phy data (Rx signal strength, etc.) contained within struct iwl_rx_phy_res *phy_res;
* this rx packet for legacy frames, __le32 rx_pkt_status;
* or phy data cached from REPLY_RX_PHY_CMD for HT frames. */ struct iwl4965_rx_mpdu_res_start *amsdu;
int include_phy = (pkt->hdr.cmd == REPLY_RX); u32 len;
struct iwl_rx_phy_res *rx_start = (include_phy) ? u32 ampdu_status;
(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;
u16 fc; 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 = rx_status.freq =
ieee80211_channel_to_frequency(le16_to_cpu(rx_start->channel)); ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel));
rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
rx_status.rate_idx = 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) if (rx_status.band == IEEE80211_BAND_5GHZ)
rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; 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 */ * this W/A doesn't propagate it to the mac80211 */
/*rx_status.flag |= RX_FLAG_TSFT;*/ /*rx_status.flag |= RX_FLAG_TSFT;*/
if ((unlikely(rx_start->cfg_phy_cnt > 20))) { priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
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);
/* Find max signal strength (dBm) among 3 antenna/receiver chains */ /* 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, /* Meaningful noise values are available only from beacon statistics,
* which are gathered only when associated, and indicate noise * 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)) if (!iwl_is_associated(priv))
priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
/* Set "1" to report good data frames in groups of 100 */
#ifdef CONFIG_IWLWIFI_DEBUG #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)) 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 #endif
iwl_dbg_log_rx_data_frame(priv, len, header); iwl_dbg_log_rx_data_frame(priv, len, header);
IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n", 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 * new 802.11n radiotap field "RX chains" that is defined
* as a bitmask. * as a bitmask.
*/ */
rx_status.antenna = le16_to_cpu(rx_start->phy_flags & rx_status.antenna =
RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4; 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 */ /* 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; rx_status.flag |= RX_FLAG_SHORTPRE;
network_packet = iwl_is_network_packet(priv, header); if (iwl_is_network_packet(priv, header)) {
if (network_packet) {
priv->last_rx_rssi = rx_status.signal; priv->last_rx_rssi = rx_status.signal;
priv->last_beacon_time = priv->ucode_beacon_time; 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); fc = le16_to_cpu(header->frame_control);
@ -1096,8 +1047,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
header->addr2); header->addr2);
/* fall through */ /* fall through */
default: default:
iwl_pass_packet_to_mac80211(priv, include_phy, rxb, iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status,
&rx_status); rxb, &rx_status);
break; 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)) { if (ieee80211_is_data_qos(fc)) {
qc = ieee80211_get_qos_ctl(hdr); qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; 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 = priv->stations[sta_id].tid[tid].seq_number;
seq_number &= IEEE80211_SCTL_SEQ; seq_number &= IEEE80211_SCTL_SEQ;
hdr->seq_ctrl = hdr->seq_ctrl & 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; return -EINVAL;
} }
if (unlikely(tid >= MAX_TID_COUNT))
return -EINVAL;
if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo))) if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo)))
tx_fifo_id = default_tid_to_tx_fifo[tid]; tx_fifo_id = default_tid_to_tx_fifo[tid];
else 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)) { if (ieee80211_is_data_qos(fc)) {
qc = ieee80211_get_qos_ctl(hdr); qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; 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 & seq_number = priv->stations[sta_id].tid[tid].seq_number &
IEEE80211_SCTL_SEQ; IEEE80211_SCTL_SEQ;
hdr->seq_ctrl = cpu_to_le16(seq_number) | 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; u8 *card_rates = lbs_bg_rates;
size_t num_card_rates = sizeof(lbs_bg_rates); size_t num_card_rates = sizeof(lbs_bg_rates);
int ret = 0, i, j; int ret = 0, i, j;
u8 tmp[30]; u8 *tmp;
size_t tmp_size = 0; 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 each rate in card_rates that exists in rate1, copy to tmp */
for (i = 0; card_rates[i] && (i < num_card_rates); i++) { for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
for (j = 0; rates[j] && (j < *rates_size); j++) { for (j = 0; rates[j] && (j < *rates_size); j++) {
@ -77,6 +82,7 @@ done:
memset(rates, 0, *rates_size); memset(rates, 0, *rates_size);
*rates_size = min_t(int, tmp_size, *rates_size); *rates_size = min_t(int, tmp_size, *rates_size);
memcpy(rates, tmp, *rates_size); memcpy(rates, tmp, *rates_size);
kfree(tmp);
return ret; return ret;
} }

View File

@ -366,15 +366,35 @@ static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed)
return 0; 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) #define SUPPORTED_FIF_FLAGS (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)
static void lbtf_op_configure_filter(struct ieee80211_hw *hw, static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *new_flags, unsigned int *new_flags,
int mc_count, struct dev_mc_list *mclist) u64 multicast)
{ {
struct lbtf_private *priv = hw->priv; struct lbtf_private *priv = hw->priv;
int old_mac_control = priv->mac_control; int old_mac_control = priv->mac_control;
int i;
changed_flags &= SUPPORTED_FIF_FLAGS; changed_flags &= SUPPORTED_FIF_FLAGS;
*new_flags &= SUPPORTED_FIF_FLAGS; *new_flags &= SUPPORTED_FIF_FLAGS;
@ -386,20 +406,12 @@ static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
else else
priv->mac_control &= ~CMD_ACT_MAC_PROMISCUOUS_ENABLE; priv->mac_control &= ~CMD_ACT_MAC_PROMISCUOUS_ENABLE;
if (*new_flags & (FIF_ALLMULTI) || 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_ALL_MULTICAST_ENABLE;
priv->mac_control &= ~CMD_ACT_MAC_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_MULTICAST_ENABLE;
priv->mac_control &= ~CMD_ACT_MAC_ALL_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); lbtf_cmd_set_mac_multicast_addr(priv);
} else { } else {
priv->mac_control &= ~(CMD_ACT_MAC_MULTICAST_ENABLE | 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, .add_interface = lbtf_op_add_interface,
.remove_interface = lbtf_op_remove_interface, .remove_interface = lbtf_op_remove_interface,
.config = lbtf_op_config, .config = lbtf_op_config,
.prepare_multicast = lbtf_op_prepare_multicast,
.configure_filter = lbtf_op_configure_filter, .configure_filter = lbtf_op_configure_filter,
.bss_info_changed = lbtf_op_bss_info_changed, .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, static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *total_flags, unsigned int *total_flags,u64 multicast)
int mc_count,
struct dev_addr_list *mc_list)
{ {
struct mac80211_hwsim_data *data = hw->priv; 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) if (orinoco_lock(priv, &flags) != 0)
return -EBUSY; return -EBUSY;
priv->ibss_port = val ; priv->ibss_port = val;
/* Actually update the mode we are using */ /* Actually update the mode we are using */
set_port_type(priv); set_port_type(priv);

View File

@ -302,7 +302,7 @@ out:
static void p54_configure_filter(struct ieee80211_hw *dev, static void p54_configure_filter(struct ieee80211_hw *dev,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *total_flags, unsigned int *total_flags,
int mc_count, struct dev_mc_list *mclist) u64 multicast)
{ {
struct p54_common *priv = dev->priv; 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 + dev->extra_tx_headroom = sizeof(struct p54_hdr) + 4 +
sizeof(struct p54_tx_data); 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->conf_mutex);
mutex_init(&priv->eeprom_mutex); mutex_init(&priv->eeprom_mutex);
init_completion(&priv->eeprom_comp); 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_ATIM_QUEUE, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
if (!modparam_nohwcrypt) { if (!modparam_nohwcrypt) {
__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_COPY_IV, &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. * 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++) { for (i = 0; i < 256; i++) {
u32 wcid[2] = { 0xffffffff, 0x00ffffff }; u32 wcid[2] = { 0xffffffff, 0x00ffffff };
rt2x00usb_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), 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); 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 * Clear all beacons
* For the Beacon base registers we only need to clear * 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); rt2x00usb_register_read(rt2x00dev, LG_FBK_CFG0, &reg);
rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS0FBK, 8); 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_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_OFDMMCS3FBK, 10);
rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS4FBK, 11); rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS4FBK, 11);
rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS5FBK, 12); 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_BW_WIN_SIZE, txdesc->ba_size);
rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? 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, rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
skb->len - txdesc->l2pad); skb->len - txdesc->l2pad);
rt2x00_set_field32(&word, TXWI_W1_PACKETID, rt2x00_set_field32(&word, TXWI_W1_PACKETID,
skbdesc->entry->entry_idx); skbdesc->entry->queue->qid + 1);
rt2x00_desc_write(txwi, 1, word); 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)) if (rt2x00_get_field32(rxd0, RXD_W0_MY_BSS))
rxdesc->dev_flags |= RXDONE_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; rxdesc->dev_flags |= RXDONE_L2PAD;
skbdesc->flags |= SKBDESC_L2_PADDED;
}
if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI))
rxdesc->flags |= RX_FLAG_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. * This device requires firmware.
*/ */
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
if (!modparam_nohwcrypt) if (!modparam_nohwcrypt)
__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);

View File

@ -36,6 +36,9 @@
* RF2750 2.4G/5G 1T2R * RF2750 2.4G/5G 1T2R
* RF3020 2.4G 1T1R * RF3020 2.4G 1T1R
* RF2020 2.4G B/G * RF2020 2.4G B/G
* RF3021 2.4G 1T2R
* RF3022 2.4G 2T2R
* RF3052 2.4G 2T2R
*/ */
#define RF2820 0x0001 #define RF2820 0x0001
#define RF2850 0x0002 #define RF2850 0x0002
@ -43,6 +46,9 @@
#define RF2750 0x0004 #define RF2750 0x0004
#define RF3020 0x0005 #define RF3020 0x0005
#define RF2020 0x0006 #define RF2020 0x0006
#define RF3021 0x0007
#define RF3022 0x0008
#define RF3052 0x0009
/* /*
* RT2870 version * RT2870 version
@ -1300,8 +1306,8 @@
* PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry
* MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry
* MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry
* SHARED_KEY_TABLE_BASE: 32-byte * 16-entry * SHARED_KEY_TABLE_BASE: 32 bytes * 32-entry
* SHARED_KEY_MODE_BASE: 4-byte * 16-entry * SHARED_KEY_MODE_BASE: 4 bits * 32-entry
*/ */
#define MAC_WCID_BASE 0x1800 #define MAC_WCID_BASE 0x1800
#define PAIRWISE_KEY_TABLE_BASE 0x4000 #define PAIRWISE_KEY_TABLE_BASE 0x4000

View File

@ -350,8 +350,6 @@ struct rt2x00_intf {
*/ */
unsigned int delayed_flags; unsigned int delayed_flags;
#define DELAYED_UPDATE_BEACON 0x00000001 #define DELAYED_UPDATE_BEACON 0x00000001
#define DELAYED_CONFIG_ERP 0x00000002
#define DELAYED_LED_ASSOC 0x00000004
/* /*
* Software sequence counter, this is only required * Software sequence counter, this is only required
@ -614,7 +612,6 @@ enum rt2x00_flags {
DRIVER_REQUIRE_FIRMWARE, DRIVER_REQUIRE_FIRMWARE,
DRIVER_REQUIRE_BEACON_GUARD, DRIVER_REQUIRE_BEACON_GUARD,
DRIVER_REQUIRE_ATIM_QUEUE, DRIVER_REQUIRE_ATIM_QUEUE,
DRIVER_REQUIRE_SCHEDULED,
DRIVER_REQUIRE_DMA, DRIVER_REQUIRE_DMA,
DRIVER_REQUIRE_COPY_IV, DRIVER_REQUIRE_COPY_IV,
DRIVER_REQUIRE_L2PAD, DRIVER_REQUIRE_L2PAD,
@ -826,7 +823,6 @@ struct rt2x00_dev {
* due to RTNL locking requirements. * due to RTNL locking requirements.
*/ */
struct work_struct intf_work; struct work_struct intf_work;
struct work_struct filter_work;
/* /*
* Data queue arrays for RX, TX and Beacon. * 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, void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *total_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, int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
bool set); bool set);
#ifdef CONFIG_RT2X00_LIB_CRYPTO #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); 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, static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
struct rt2x00_dev *rt2x00dev = data; struct rt2x00_dev *rt2x00dev = data;
struct rt2x00_intf *intf = vif_to_intf(vif); struct rt2x00_intf *intf = vif_to_intf(vif);
struct ieee80211_bss_conf conf;
int delayed_flags; int delayed_flags;
/* /*
@ -141,7 +132,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
*/ */
spin_lock(&intf->lock); spin_lock(&intf->lock);
memcpy(&conf, &vif->bss_conf, sizeof(conf));
delayed_flags = intf->delayed_flags; delayed_flags = intf->delayed_flags;
intf->delayed_flags = 0; intf->delayed_flags = 0;
@ -158,12 +148,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
if (delayed_flags & DELAYED_UPDATE_BEACON) if (delayed_flags & DELAYED_UPDATE_BEACON)
rt2x00queue_update_beacon(rt2x00dev, vif, true); 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) 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); struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); enum data_queue_qid qid = skb_get_queue_mapping(entry->skb);
unsigned int header_length = ieee80211_get_hdrlen_from_skb(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. * Unmap the skb.
@ -259,16 +244,27 @@ void rt2x00lib_txdone(struct queue_entry *entry,
rate_idx = skbdesc->tx_rate_idx; rate_idx = skbdesc->tx_rate_idx;
rate_flags = skbdesc->tx_rate_flags; rate_flags = skbdesc->tx_rate_flags;
retry_rates = test_bit(TXDONE_FALLBACK, &txdesc->flags) ?
(txdesc->retry + 1) : 1;
/* /*
* Initialize TX status * Initialize TX status
*/ */
memset(&tx_info->status, 0, sizeof(tx_info->status)); memset(&tx_info->status, 0, sizeof(tx_info->status));
tx_info->status.ack_signal = 0; 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; * Frame was send with retries, hardware tried
tx_info->status.rates[1].idx = -1; /* terminate */ * 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 (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
if (test_bit(TXDONE_SUCCESS, &txdesc->flags) || if (test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
@ -847,7 +843,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
* Initialize configuration work. * Initialize configuration work.
*/ */
INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled);
/* /*
* Allocate queue array. * Allocate queue array.
@ -895,7 +890,6 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
/* /*
* Stop all work. * Stop all work.
*/ */
cancel_work_sync(&rt2x00dev->filter_work);
cancel_work_sync(&rt2x00dev->intf_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, void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *total_flags, unsigned int *total_flags,
int mc_count, struct dev_addr_list *mc_list) u64 multicast)
{ {
struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_dev *rt2x00dev = hw->priv;
@ -430,10 +430,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
return; return;
rt2x00dev->packet_filter = *total_flags; rt2x00dev->packet_filter = *total_flags;
if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
else
ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->filter_work);
} }
EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
@ -639,23 +636,15 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
else else
rt2x00dev->intf_associated--; rt2x00dev->intf_associated--;
if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated);
rt2x00leds_led_assoc(rt2x00dev,
!!rt2x00dev->intf_associated);
else
delayed |= DELAYED_LED_ASSOC;
} }
/* /*
* When the erp information has changed, we should perform * When the erp information has changed, we should perform
* additional configuration steps. For all other changes we are done. * additional configuration steps. For all other changes we are done.
*/ */
if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) { if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT))
if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) rt2x00lib_config_erp(rt2x00dev, intf, bss_conf);
rt2x00lib_config_erp(rt2x00dev, intf, bss_conf);
else
delayed |= DELAYED_CONFIG_ERP;
}
spin_lock(&intf->lock); spin_lock(&intf->lock);
if (delayed) { if (delayed) {
@ -704,8 +693,8 @@ EXPORT_SYMBOL_GPL(rt2x00mac_conf_tx);
void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw) void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw)
{ {
struct rt2x00_dev *rt2x00dev = hw->priv; 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); 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_UNKNOWN: Hardware could not determine success of transmission.
* @TXDONE_SUCCESS: Frame was successfully send * @TXDONE_SUCCESS: Frame was successfully send
* @TXDONE_FALLBACK: Frame was successfully send using a fallback rate.
* @TXDONE_FAILURE: Frame was not successfully send * @TXDONE_FAILURE: Frame was not successfully send
* @TXDONE_EXCESSIVE_RETRY: In addition to &TXDONE_FAILURE, the * @TXDONE_EXCESSIVE_RETRY: In addition to &TXDONE_FAILURE, the
* frame transmission failed due to excessive retries. * frame transmission failed due to excessive retries.
@ -221,6 +222,7 @@ struct rxdone_entry_desc {
enum txdone_entry_desc_flags { enum txdone_entry_desc_flags {
TXDONE_UNKNOWN, TXDONE_UNKNOWN,
TXDONE_SUCCESS, TXDONE_SUCCESS,
TXDONE_FALLBACK,
TXDONE_FAILURE, TXDONE_FAILURE,
TXDONE_EXCESSIVE_RETRY, TXDONE_EXCESSIVE_RETRY,
}; };

View File

@ -2151,7 +2151,6 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
* This device requires firmware. * This device requires firmware.
*/ */
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
if (!modparam_nohwcrypt) if (!modparam_nohwcrypt)
__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); __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); 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, static void rtl8180_configure_filter(struct ieee80211_hw *dev,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *total_flags, unsigned int *total_flags,
int mc_count, struct dev_addr_list *mclist) u64 multicast)
{ {
struct rtl8180_priv *priv = dev->priv; 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; priv->rx_conf ^= RTL818X_RX_CONF_CTRL;
if (changed_flags & FIF_OTHER_BSS) if (changed_flags & FIF_OTHER_BSS)
priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; 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; priv->rx_conf |= RTL818X_RX_CONF_MULTICAST;
else else
priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST;
@ -768,6 +774,7 @@ static const struct ieee80211_ops rtl8180_ops = {
.remove_interface = rtl8180_remove_interface, .remove_interface = rtl8180_remove_interface,
.config = rtl8180_config, .config = rtl8180_config,
.bss_info_changed = rtl8180_bss_info_changed, .bss_info_changed = rtl8180_bss_info_changed,
.prepare_multicast = rtl8180_prepare_multicast,
.configure_filter = rtl8180_configure_filter, .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); 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, static void rtl8187_configure_filter(struct ieee80211_hw *dev,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *total_flags, unsigned int *total_flags,
int mc_count, struct dev_addr_list *mclist) u64 multicast)
{ {
struct rtl8187_priv *priv = dev->priv; 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; priv->rx_conf ^= RTL818X_RX_CONF_CTRL;
if (changed_flags & FIF_OTHER_BSS) if (changed_flags & FIF_OTHER_BSS)
priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; 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; priv->rx_conf |= RTL818X_RX_CONF_MULTICAST;
else else
priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST;
@ -1268,6 +1274,7 @@ static const struct ieee80211_ops rtl8187_ops = {
.remove_interface = rtl8187_remove_interface, .remove_interface = rtl8187_remove_interface,
.config = rtl8187_config, .config = rtl8187_config,
.bss_info_changed = rtl8187_bss_info_changed, .bss_info_changed = rtl8187_bss_info_changed,
.prepare_multicast = rtl8187_prepare_multicast,
.configure_filter = rtl8187_configure_filter, .configure_filter = rtl8187_configure_filter,
.conf_tx = rtl8187_conf_tx .conf_tx = rtl8187_conf_tx
}; };

View File

@ -465,6 +465,9 @@ int wl1251_boot(struct wl1251 *wl)
int ret = 0, minor_minor_e2_ver; int ret = 0, minor_minor_e2_ver;
u32 tmp, boot_data; 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); ret = wl1251_boot_soft_reset(wl);
if (ret < 0) if (ret < 0)
goto out; goto out;

View File

@ -652,9 +652,7 @@ out:
static void wl1251_op_configure_filter(struct ieee80211_hw *hw, static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed, unsigned int changed,
unsigned int *total, unsigned int *total,u64 multicast)
int mc_count,
struct dev_addr_list *mc_list)
{ {
struct wl1251 *wl = hw->priv; struct wl1251 *wl = hw->priv;

View File

@ -245,8 +245,8 @@ enum wl12xx_acx_int_reg {
ACX_REG_TABLE_LEN ACX_REG_TABLE_LEN
}; };
#define ACX_SLV_SOFT_RESET_BIT BIT(1) #define ACX_SLV_SOFT_RESET_BIT BIT(0)
#define ACX_REG_EEPROM_START_BIT BIT(1) #define ACX_REG_EEPROM_START_BIT BIT(0)
/* Command/Information Mailbox Pointers */ /* 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 ieee80211_if_init_conf *conf)
{ {
struct wl1271 *wl = hw->priv; struct wl1271 *wl = hw->priv;
DECLARE_MAC_BUF(mac);
int ret = 0; int ret = 0;
wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %s", wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
conf->type, print_mac(mac, conf->mac_addr)); conf->type, conf->mac_addr);
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
@ -793,9 +792,7 @@ out:
static void wl1271_op_configure_filter(struct ieee80211_hw *hw, static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed, unsigned int changed,
unsigned int *total, unsigned int *total,u64 multicast)
int mc_count,
struct dev_addr_list *mc_list)
{ {
struct wl1271 *wl = hw->priv; 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); 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 \ #define SUPPORTED_FIF_FLAGS \
(FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \ (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \
FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC) FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)
static void zd_op_configure_filter(struct ieee80211_hw *hw, static void zd_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *new_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); struct zd_mac *mac = zd_hw_mac(hw);
unsigned long flags; unsigned long flags;
int i;
/* Only deal with supported flags */ /* Only deal with supported flags */
changed_flags &= SUPPORTED_FIF_FLAGS; changed_flags &= SUPPORTED_FIF_FLAGS;
@ -819,25 +841,16 @@ static void zd_op_configure_filter(struct ieee80211_hw *hw,
if (!changed_flags) if (!changed_flags)
return; return;
if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) { if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI))
zd_mc_add_all(&hash); 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); spin_lock_irqsave(&mac->lock, flags);
mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL); mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL);
mac->pass_ctrl = !!(*new_flags & FIF_CONTROL); mac->pass_ctrl = !!(*new_flags & FIF_CONTROL);
mac->multicast_hash = hash; mac->multicast_hash = hash;
spin_unlock_irqrestore(&mac->lock, flags); 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); queue_work(zd_workqueue, &mac->set_multicast_hash_work);
if (changed_flags & FIF_CONTROL) if (changed_flags & FIF_CONTROL)
@ -940,6 +953,7 @@ static const struct ieee80211_ops zd_ops = {
.add_interface = zd_op_add_interface, .add_interface = zd_op_add_interface,
.remove_interface = zd_op_remove_interface, .remove_interface = zd_op_remove_interface,
.config = zd_op_config, .config = zd_op_config,
.prepare_multicast = zd_op_prepare_multicast,
.configure_filter = zd_op_configure_filter, .configure_filter = zd_op_configure_filter,
.bss_info_changed = zd_op_bss_info_changed, .bss_info_changed = zd_op_bss_info_changed,
.get_tsf = zd_op_get_tsf, .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 */ /* extract the MAC address */
for (i = 0; i < 3; i++) { 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); *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
} }
SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0); SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);

View File

@ -1325,6 +1325,8 @@ struct wireless_dev {
struct mutex mtx; struct mutex mtx;
struct work_struct cleanup_work;
/* currently used for IBSS and SME - might be rearranged later */ /* currently used for IBSS and SME - might be rearranged later */
u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 ssid_len; u8 ssid_len;

View File

@ -583,7 +583,6 @@ enum ieee80211_conf_flags {
/** /**
* enum ieee80211_conf_changed - denotes which configuration changed * 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_LISTEN_INTERVAL: the listen interval changed
* @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed
* @IEEE80211_CONF_CHANGE_PS: the PS flag or dynamic PS timeout 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 * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed
*/ */
enum ieee80211_conf_changed { enum ieee80211_conf_changed {
_IEEE80211_CONF_CHANGE_RADIO_ENABLED = BIT(0),
IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2), IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2),
IEEE80211_CONF_CHANGE_RADIOTAP = BIT(3), IEEE80211_CONF_CHANGE_RADIOTAP = BIT(3),
IEEE80211_CONF_CHANGE_PS = BIT(4), IEEE80211_CONF_CHANGE_PS = BIT(4),
@ -603,14 +601,6 @@ enum ieee80211_conf_changed {
IEEE80211_CONF_CHANGE_IDLE = BIT(8), 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 * struct ieee80211_conf - configuration of the device
* *
@ -618,9 +608,6 @@ __IEEE80211_CONF_CHANGE_RADIO_ENABLED(void)
* *
* @flags: configuration flags defined above * @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 * @listen_interval: listen interval in units of beacon interval
* @max_sleep_period: the maximum number of beacon intervals to sleep for * @max_sleep_period: the maximum number of beacon intervals to sleep for
* before checking the beacon for a TIM bit (managed mode only); this * 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 * number of transmissions not the number of retries
*/ */
struct ieee80211_conf { struct ieee80211_conf {
int __deprecated beacon_int;
u32 flags; u32 flags;
int power_level, dynamic_ps_timeout; int power_level, dynamic_ps_timeout;
int max_sleep_period; int max_sleep_period;
u16 listen_interval; u16 listen_interval;
bool __deprecated radio_enabled;
u8 long_frame_max_tx_count, short_frame_max_tx_count; 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 * the driver's configure_filter() function which frames should be
* passed to mac80211 and which should be filtered out. * passed to mac80211 and which should be filtered out.
* *
* The configure_filter() callback is invoked with the parameters * Before configure_filter() is invoked, the prepare_multicast()
* @mc_count and @mc_list for the combined multicast address list * callback is invoked with the parameters @mc_count and @mc_list
* of all virtual interfaces, @changed_flags telling which flags * for the combined multicast address list of all virtual interfaces.
* were changed and @total_flags with the new flag states. * 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 * If your device has no multicast address filters your driver will
* need to check both the %FIF_ALLMULTI flag and the @mc_count * 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 * for association indication. The @changed parameter indicates which
* of the bss parameters has changed when a call is made. * 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. * @configure_filter: Configure the device's RX filter.
* See the section "Frame filtering" for more information. * 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 * @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. * 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_vif *vif,
struct ieee80211_bss_conf *info, struct ieee80211_bss_conf *info,
u32 changed); 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, void (*configure_filter)(struct ieee80211_hw *hw,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *total_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, int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
bool set); bool set);
int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, 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 #ifdef CONFIG_MAC80211_MESH
/* Mesh stats attributes */ /* 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(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_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC);
IEEE80211_IF_FILE(dropped_frames_no_route, 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->mesh_stats_dir = debugfs_create_dir("mesh_stats",
sdata->debugfsdir); sdata->debugfsdir);
MESHSTATS_ADD(fwded_mcast);
MESHSTATS_ADD(fwded_unicast);
MESHSTATS_ADD(fwded_frames); MESHSTATS_ADD(fwded_frames);
MESHSTATS_ADD(dropped_frames_ttl); MESHSTATS_ADD(dropped_frames_ttl);
MESHSTATS_ADD(dropped_frames_no_route); 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) 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(fwded_frames);
MESHSTATS_DEL(dropped_frames_ttl); MESHSTATS_DEL(dropped_frames_ttl);
MESHSTATS_DEL(dropped_frames_no_route); 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); trace_drv_bss_info_changed(local, vif, info, changed);
} }
static inline void drv_configure_filter(struct ieee80211_local *local, static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
unsigned int changed_flags,
unsigned int *total_flags,
int mc_count, int mc_count,
struct dev_addr_list *mc_list) 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, local->ops->configure_filter(&local->hw, changed_flags, total_flags,
mc_count, mc_list); multicast);
trace_drv_configure_filter(local, changed_flags, total_flags, trace_drv_configure_filter(local, changed_flags, total_flags,
mc_count); multicast);
} }
static inline int drv_set_tim(struct ieee80211_local *local, 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, TRACE_EVENT(drv_configure_filter,
TP_PROTO(struct ieee80211_local *local, TP_PROTO(struct ieee80211_local *local,
unsigned int changed_flags, unsigned int changed_flags,
unsigned int *total_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( TP_STRUCT__entry(
LOCAL_ENTRY LOCAL_ENTRY
__field(unsigned int, changed) __field(unsigned int, changed)
__field(unsigned int, total) __field(unsigned int, total)
__field(int, mc) __field(u64, multicast)
), ),
TP_fast_assign( TP_fast_assign(
LOCAL_ASSIGN; LOCAL_ASSIGN;
__entry->changed = changed_flags; __entry->changed = changed_flags;
__entry->total = *total_flags; __entry->total = *total_flags;
__entry->mc = mc_count; __entry->multicast = multicast;
), ),
TP_printk( TP_printk(
LOCAL_PR_FMT " changed:%#x total:%#x mc:%d", LOCAL_PR_FMT " changed:%#x total:%#x",
LOCAL_PR_ARG, __entry->changed, __entry->total, __entry->mc LOCAL_PR_ARG, __entry->changed, __entry->total
) )
); );

View File

@ -212,7 +212,9 @@ struct ieee80211_if_vlan {
}; };
struct mesh_stats { 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_ttl; /* Not transmitted since mesh_ttl == 0*/
__u32 dropped_frames_no_route; /* Not transmitted, no route found */ __u32 dropped_frames_no_route; /* Not transmitted, no route found */
atomic_t estab_plinks; atomic_t estab_plinks;
@ -506,6 +508,8 @@ struct ieee80211_sub_if_data {
#ifdef CONFIG_MAC80211_MESH #ifdef CONFIG_MAC80211_MESH
struct dentry *mesh_stats_dir; struct dentry *mesh_stats_dir;
struct { struct {
struct dentry *fwded_mcast;
struct dentry *fwded_unicast;
struct dentry *fwded_frames; struct dentry *fwded_frames;
struct dentry *dropped_frames_ttl; struct dentry *dropped_frames_ttl;
struct dentry *dropped_frames_no_route; struct dentry *dropped_frames_no_route;
@ -636,6 +640,9 @@ struct ieee80211_local {
/* protects the aggregated multicast list and filter calls */ /* protects the aggregated multicast list and filter calls */
spinlock_t filter_lock; spinlock_t filter_lock;
/* used for uploading changed mc list */
struct work_struct reconfig_filter;
/* aggregated multicast list */ /* aggregated multicast list */
struct dev_addr_list *mc_list; struct dev_addr_list *mc_list;
int mc_count; 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) if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
local->fif_other_bss++; local->fif_other_bss++;
spin_lock_bh(&local->filter_lock);
ieee80211_configure_filter(local); ieee80211_configure_filter(local);
spin_unlock_bh(&local->filter_lock);
break; break;
default: default:
conf.vif = &sdata->vif; conf.vif = &sdata->vif;
@ -241,17 +239,13 @@ static int ieee80211_open(struct net_device *dev)
if (ieee80211_vif_is_mesh(&sdata->vif)) { if (ieee80211_vif_is_mesh(&sdata->vif)) {
local->fif_other_bss++; local->fif_other_bss++;
spin_lock_bh(&local->filter_lock);
ieee80211_configure_filter(local); ieee80211_configure_filter(local);
spin_unlock_bh(&local->filter_lock);
ieee80211_start_mesh(sdata); ieee80211_start_mesh(sdata);
} else if (sdata->vif.type == NL80211_IFTYPE_AP) { } else if (sdata->vif.type == NL80211_IFTYPE_AP) {
local->fif_pspoll++; local->fif_pspoll++;
spin_lock_bh(&local->filter_lock);
ieee80211_configure_filter(local); ieee80211_configure_filter(local);
spin_unlock_bh(&local->filter_lock);
} }
changed |= ieee80211_reset_erp_info(sdata); changed |= ieee80211_reset_erp_info(sdata);
@ -404,10 +398,11 @@ static int ieee80211_stop(struct net_device *dev)
spin_lock_bh(&local->filter_lock); spin_lock_bh(&local->filter_lock);
__dev_addr_unsync(&local->mc_list, &local->mc_count, __dev_addr_unsync(&local->mc_list, &local->mc_count,
&dev->mc_list, &dev->mc_count); &dev->mc_list, &dev->mc_count);
ieee80211_configure_filter(local);
spin_unlock_bh(&local->filter_lock); spin_unlock_bh(&local->filter_lock);
netif_addr_unlock_bh(dev); netif_addr_unlock_bh(dev);
ieee80211_configure_filter(local);
del_timer_sync(&local->dynamic_ps_timer); del_timer_sync(&local->dynamic_ps_timer);
cancel_work_sync(&local->dynamic_ps_enable_work); 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) if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
local->fif_other_bss--; local->fif_other_bss--;
spin_lock_bh(&local->filter_lock);
ieee80211_configure_filter(local); ieee80211_configure_filter(local);
spin_unlock_bh(&local->filter_lock);
break; break;
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
del_timer_sync(&sdata->u.mgd.chswitch_timer); del_timer_sync(&sdata->u.mgd.chswitch_timer);
@ -503,9 +496,7 @@ static int ieee80211_stop(struct net_device *dev)
local->fif_other_bss--; local->fif_other_bss--;
atomic_dec(&local->iff_allmultis); atomic_dec(&local->iff_allmultis);
spin_lock_bh(&local->filter_lock);
ieee80211_configure_filter(local); ieee80211_configure_filter(local);
spin_unlock_bh(&local->filter_lock);
ieee80211_stop_mesh(sdata); ieee80211_stop_mesh(sdata);
} }
@ -622,8 +613,8 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
spin_lock_bh(&local->filter_lock); spin_lock_bh(&local->filter_lock);
__dev_addr_sync(&local->mc_list, &local->mc_count, __dev_addr_sync(&local->mc_list, &local->mc_count,
&dev->mc_list, &dev->mc_count); &dev->mc_list, &dev->mc_count);
ieee80211_configure_filter(local);
spin_unlock_bh(&local->filter_lock); 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)); } __attribute__ ((packed));
/* must be called under mdev tx lock */
void ieee80211_configure_filter(struct ieee80211_local *local) void ieee80211_configure_filter(struct ieee80211_local *local)
{ {
u64 mc;
unsigned int changed_flags; unsigned int changed_flags;
unsigned int new_flags = 0; unsigned int new_flags = 0;
@ -62,7 +62,7 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
if (atomic_read(&local->iff_allmultis)) if (atomic_read(&local->iff_allmultis))
new_flags |= FIF_ALLMULTI; new_flags |= FIF_ALLMULTI;
if (local->monitors) if (local->monitors || local->scanning)
new_flags |= FIF_BCN_PRBRESP_PROMISC; new_flags |= FIF_BCN_PRBRESP_PROMISC;
if (local->fif_fcsfail) if (local->fif_fcsfail)
@ -80,20 +80,30 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
if (local->fif_pspoll) if (local->fif_pspoll)
new_flags |= FIF_PSPOLL; new_flags |= FIF_PSPOLL;
spin_lock_bh(&local->filter_lock);
changed_flags = local->filter_flags ^ new_flags; 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 */ /* be a bit nasty */
new_flags |= (1<<31); new_flags |= (1<<31);
drv_configure_filter(local, changed_flags, &new_flags, drv_configure_filter(local, changed_flags, &new_flags, mc);
local->mc_count,
local->mc_list);
WARN_ON(new_flags & (1<<31)); WARN_ON(new_flags & (1<<31));
local->filter_flags = 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) int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
{ {
struct ieee80211_channel *chan, *scan_chan; 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, drv_bss_info_changed(local, &sdata->vif,
&sdata->vif.bss_conf, changed); &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) 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); 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(); 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.max_rates = 1;
local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; 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.short_frame_max_tx_count = wiphy->retry_short;
local->hw.conf.radio_enabled = true;
local->user_power_level = -1; local->user_power_level = -1;
INIT_LIST_HEAD(&local->interfaces); 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->restart_work, ieee80211_restart_work);
INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
INIT_WORK(&local->dynamic_ps_enable_work, INIT_WORK(&local->dynamic_ps_enable_work,
ieee80211_dynamic_ps_enable_work); ieee80211_dynamic_ps_enable_work);
INIT_WORK(&local->dynamic_ps_disable_work, INIT_WORK(&local->dynamic_ps_disable_work,
@ -920,7 +930,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
fail_workqueue: fail_workqueue:
wiphy_unregister(local->hw.wiphy); wiphy_unregister(local->hw.wiphy);
fail_wiphy_register: fail_wiphy_register:
kfree(local->int_scan_req->channels); kfree(local->int_scan_req);
return result; return result;
} }
EXPORT_SYMBOL(ieee80211_register_hw); EXPORT_SYMBOL(ieee80211_register_hw);
@ -946,6 +956,8 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
rtnl_unlock(); rtnl_unlock();
cancel_work_sync(&local->reconfig_filter);
ieee80211_clear_tx_pending(local); ieee80211_clear_tx_pending(local);
sta_info_stop(local); sta_info_stop(local);
rate_control_deinitialize(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); void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
void ieee80211s_init(void); 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 ieee80211s_stop(void);
void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
ieee80211_rx_result ieee80211_rx_result

View File

@ -201,6 +201,24 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra,
return 0; 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, static u32 airtime_link_metric_get(struct ieee80211_local *local,
struct sta_info *sta) 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), hopcount, ttl, cpu_to_le32(lifetime),
cpu_to_le32(metric), cpu_to_le32(preq_id), cpu_to_le32(metric), cpu_to_le32(preq_id),
sdata); sdata);
ifmsh->mshstats.fwded_mcast++;
ifmsh->mshstats.fwded_frames++; 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), cpu_to_le32(lifetime), cpu_to_le32(metric),
0, sdata); 0, sdata);
rcu_read_unlock(); rcu_read_unlock();
sdata->u.mesh.mshstats.fwded_unicast++;
sdata->u.mesh.mshstats.fwded_frames++; sdata->u.mesh.mshstats.fwded_frames++;
return; return;

View File

@ -51,7 +51,6 @@
#include <linux/random.h> #include <linux/random.h>
#include <linux/ieee80211.h> #include <linux/ieee80211.h>
#include <net/mac80211.h> #include <net/mac80211.h>
#include "mesh.h"
#include "rate.h" #include "rate.h"
#include "rc80211_minstrel.h" #include "rc80211_minstrel.h"
@ -156,16 +155,12 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct minstrel_sta_info *mi = priv_sta; 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_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *ar = info->status.rates; 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 i, ndx;
int success; int success;
success = !!(info->flags & IEEE80211_TX_STAT_ACK); success = !!(info->flags & IEEE80211_TX_STAT_ACK);
si = sta_info_get(local, sta->addr);
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
if (ar[i].idx < 0) 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; 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; 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)) 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. */ * still a good measurement and copy it. */
if (unlikely(spinfo->tx_num_xmit == 0)) if (unlikely(spinfo->tx_num_xmit == 0))
pf = spinfo->last_pf; pf = spinfo->last_pf;
else { else
/* XXX: BAD HACK!!! */
struct sta_info *si = container_of(sta, struct sta_info, sta);
pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; 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_xmit = 0;
spinfo->tx_num_failed = 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_sta_info *spinfo = priv_sta;
struct rc_pid_info *pinfo = priv; struct rc_pid_info *pinfo = priv;
struct rc_pid_rateinfo *rinfo = pinfo->rinfo; struct rc_pid_rateinfo *rinfo = pinfo->rinfo;
struct sta_info *si;
int i, j, tmp; int i, j, tmp;
bool s; 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); 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, 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->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
info->control.vif = &rx->sdata->vif; info->control.vif = &rx->sdata->vif;
ieee80211_select_queue(local, fwd_skb); 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; int err;
/* /*
* Save TA to addr1 to send TA a path error if a * 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. */ * later to the pending skb queue. */
if (err) if (err)
return RX_DROP_MONITOR; return RX_DROP_MONITOR;
IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
fwded_unicast);
} }
IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
fwded_frames); fwded_frames);

View File

@ -292,13 +292,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
if (was_hw_scan) if (was_hw_scan)
goto done; goto done;
spin_lock_bh(&local->filter_lock); ieee80211_configure_filter(local);
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);
drv_sw_scan_complete(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->next_scan_state = SCAN_DECISION;
local->scan_channel_idx = 0; local->scan_channel_idx = 0;
spin_lock_bh(&local->filter_lock); ieee80211_configure_filter(local);
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);
/* TODO: start scan as soon as all nullfunc frames are ACKed */ /* TODO: start scan as soon as all nullfunc frames are ACKed */
ieee80211_queue_delayed_work(&local->hw, ieee80211_queue_delayed_work(&local->hw,

View File

@ -1076,9 +1076,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
/* reconfigure hardware */ /* reconfigure hardware */
ieee80211_hw_config(local, ~0); ieee80211_hw_config(local, ~0);
spin_lock_bh(&local->filter_lock);
ieee80211_configure_filter(local); ieee80211_configure_filter(local);
spin_unlock_bh(&local->filter_lock);
/* Finally also reconfigure all the BSS information */ /* Finally also reconfigure all the BSS information */
list_for_each_entry(sdata, &local->interfaces, list) { list_for_each_entry(sdata, &local->interfaces, list) {

View File

@ -12,6 +12,7 @@
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/etherdevice.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <net/genetlink.h> #include <net/genetlink.h>
#include <net/cfg80211.h> #include <net/cfg80211.h>
@ -309,7 +310,8 @@ static void cfg80211_process_events(struct wireless_dev *wdev)
switch (ev->type) { switch (ev->type) {
case EVENT_CONNECT_RESULT: case EVENT_CONNECT_RESULT:
__cfg80211_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.req_ie, ev->cr.req_ie_len,
ev->cr.resp_ie, ev->cr.resp_ie_len, ev->cr.resp_ie, ev->cr.resp_ie_len,
ev->cr.status, 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->conn_work, cfg80211_conn_work);
INIT_WORK(&rdev->event_work, cfg80211_event_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. * Initialize wiphy parameters to IEEE 802.11 MIB default values.
* Fragmentation and RTS threshold are disabled by default with the * Fragmentation and RTS threshold are disabled by default with the
@ -574,7 +578,23 @@ void wiphy_unregister(struct wiphy *wiphy)
/* protect the device list */ /* protect the device list */
mutex_lock(&cfg80211_mutex); 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)); 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, * 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 * down the device already. We wait for this command to complete
* before unlinking the item from the list. * before unlinking the item from the list.
* Note: as codified by the BUG_ON above we cannot get here if * Note: as codified by the BUG_ON above we cannot get here if
* a virtual interface is still associated. Hence, we can only * a virtual interface is still present. Hence, we can only get
* get to lock contention here if userspace issues a command * to lock contention here if userspace issues a command that
* that identified the hardware by wiphy index. * identified the hardware by wiphy index.
*/ */
mutex_lock(&rdev->mtx); cfg80211_lock_rdev(rdev);
/* unlock again before freeing */ /* nothing */
mutex_unlock(&rdev->mtx); cfg80211_unlock_rdev(rdev);
cfg80211_debugfs_rdev_del(rdev);
/* If this device got a regulatory hint tell core its /* If this device got a regulatory hint tell core its
* free to listen now to a new shiny device regulatory hint */ * free to listen now to a new shiny device regulatory hint */
reg_device_remove(wiphy); reg_device_remove(wiphy);
list_del(&rdev->list);
cfg80211_rdev_list_generation++; cfg80211_rdev_list_generation++;
device_del(&rdev->wiphy.dev); device_del(&rdev->wiphy.dev);
debugfs_remove(rdev->wiphy.debugfsdir); debugfs_remove(rdev->wiphy.debugfsdir);
@ -605,7 +622,6 @@ void wiphy_unregister(struct wiphy *wiphy)
flush_work(&rdev->scan_done_wk); flush_work(&rdev->scan_done_wk);
cancel_work_sync(&rdev->conn_work); cancel_work_sync(&rdev->conn_work);
kfree(rdev->scan_req);
flush_work(&rdev->event_work); flush_work(&rdev->event_work);
} }
EXPORT_SYMBOL(wiphy_unregister); 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); 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, static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
unsigned long state, unsigned long state,
void *ndev) void *ndev)
@ -653,7 +694,13 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
switch (state) { switch (state) {
case NETDEV_REGISTER: 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); mutex_init(&wdev->mtx);
INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work);
INIT_LIST_HEAD(&wdev->event_list); INIT_LIST_HEAD(&wdev->event_list);
spin_lock_init(&wdev->event_lock); spin_lock_init(&wdev->event_lock);
mutex_lock(&rdev->devlist_mtx); mutex_lock(&rdev->devlist_mtx);
@ -708,8 +755,22 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
default: default:
break; break;
} }
dev_hold(dev);
schedule_work(&wdev->cleanup_work);
break; break;
case NETDEV_UP: 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 #ifdef CONFIG_WIRELESS_EXT
cfg80211_lock_rdev(rdev); cfg80211_lock_rdev(rdev);
mutex_lock(&rdev->devlist_mtx); mutex_lock(&rdev->devlist_mtx);
@ -725,18 +786,17 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
break; break;
} }
wdev_unlock(wdev); wdev_unlock(wdev);
rdev->opencount++;
mutex_unlock(&rdev->devlist_mtx); mutex_unlock(&rdev->devlist_mtx);
cfg80211_unlock_rdev(rdev); cfg80211_unlock_rdev(rdev);
#endif #endif
break; break;
case NETDEV_UNREGISTER: case NETDEV_UNREGISTER:
cfg80211_lock_rdev(rdev); /*
* NB: cannot take rdev->mtx here because this may be
if (WARN_ON(rdev->scan_req && rdev->scan_req->dev == dev)) { * called within code protected by it when interfaces
rdev->scan_req->aborted = true; * are removed with nl80211.
___cfg80211_scan_done(rdev); */
}
mutex_lock(&rdev->devlist_mtx); mutex_lock(&rdev->devlist_mtx);
/* /*
* It is possible to get NETDEV_UNREGISTER * 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"); sysfs_remove_link(&dev->dev.kobj, "phy80211");
list_del_init(&wdev->list); list_del_init(&wdev->list);
rdev->devlist_generation++; rdev->devlist_generation++;
mutex_destroy(&wdev->mtx);
#ifdef CONFIG_WIRELESS_EXT #ifdef CONFIG_WIRELESS_EXT
kfree(wdev->wext.keys); kfree(wdev->wext.keys);
#endif #endif
} }
mutex_unlock(&rdev->devlist_mtx); mutex_unlock(&rdev->devlist_mtx);
cfg80211_unlock_rdev(rdev);
break; break;
case NETDEV_PRE_UP: case NETDEV_PRE_UP:
if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))

View File

@ -50,6 +50,8 @@ struct cfg80211_registered_device {
struct mutex devlist_mtx; struct mutex devlist_mtx;
struct list_head netdev_list; struct list_head netdev_list;
int devlist_generation; int devlist_generation;
int opencount; /* also protected by devlist_mtx */
wait_queue_head_t dev_wait;
/* BSSes/scanning */ /* BSSes/scanning */
spinlock_t bss_lock; 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); 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) */ /* this consumes one bss reference (unless bss is NULL) */
__cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
status_code, 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)) if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
return; return;
if (wdev->sme_state == CFG80211_SME_CONNECTED) if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING))
nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), dev, return;
nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev,
bssid, req_ie, req_ie_len, bssid, req_ie, req_ie_len,
resp_ie, resp_ie_len, GFP_KERNEL); resp_ie, resp_ie_len,
else status, GFP_KERNEL);
nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev,
bssid, req_ie, req_ie_len,
resp_ie, resp_ie_len,
status, GFP_KERNEL);
#ifdef CONFIG_WIRELESS_EXT #ifdef CONFIG_WIRELESS_EXT
if (wextev) { if (wextev) {
@ -392,18 +390,13 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
wdev->current_bss = NULL; 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) if (wdev->conn)
wdev->conn->state = CFG80211_CONN_IDLE; wdev->conn->state = CFG80211_CONN_IDLE;
if (status != WLAN_STATUS_SUCCESS) { if (status != WLAN_STATUS_SUCCESS) {
wdev->sme_state = CFG80211_SME_IDLE; wdev->sme_state = CFG80211_SME_IDLE;
if (wdev->conn)
kfree(wdev->conn->ie);
kfree(wdev->conn); kfree(wdev->conn);
wdev->conn = NULL; wdev->conn = NULL;
kfree(wdev->connect_keys); kfree(wdev->connect_keys);
@ -412,7 +405,6 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
return; return;
} }
success:
if (!bss) if (!bss)
bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
wdev->ssid, wdev->ssid_len, wdev->ssid, wdev->ssid_len,
@ -458,7 +450,8 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
return; return;
ev->type = EVENT_CONNECT_RESULT; 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 = ((u8 *)ev) + sizeof(*ev);
ev->cr.req_ie_len = req_ie_len; ev->cr.req_ie_len = req_ie_len;
memcpy((void *)ev->cr.req_ie, req_ie, 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) { if (err) {
kfree(wdev->conn->ie);
kfree(wdev->conn); kfree(wdev->conn);
wdev->conn = NULL; wdev->conn = NULL;
wdev->sme_state = CFG80211_SME_IDLE; 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_SCANNING ||
wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)) { wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)) {
wdev->sme_state = CFG80211_SME_IDLE; wdev->sme_state = CFG80211_SME_IDLE;
kfree(wdev->conn->ie);
kfree(wdev->conn); kfree(wdev->conn);
wdev->conn = NULL; wdev->conn = NULL;
wdev->ssid_len = 0; wdev->ssid_len = 0;

View File

@ -771,6 +771,7 @@ int cfg80211_wext_siwfreq(struct net_device *dev,
return err; return err;
} }
} }
EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq);
int cfg80211_wext_giwfreq(struct net_device *dev, int cfg80211_wext_giwfreq(struct net_device *dev,
struct iw_request_info *info, struct iw_request_info *info,