diff --git a/[refs] b/[refs]
index e3695e477bdf..992cc58aa312 100644
--- a/[refs]
+++ b/[refs]
@@ -1,2 +1,2 @@
---
-refs/heads/master: 64463da913bc8f791980ba28d93ac5e716ab9cc5
+refs/heads/master: 89612124d6d62230043ebd827a2b54ea5ea5280c
diff --git a/trunk/Documentation/DocBook/mac80211.tmpl b/trunk/Documentation/DocBook/mac80211.tmpl
index affb15a344a1..f3f37f141dbd 100644
--- a/trunk/Documentation/DocBook/mac80211.tmpl
+++ b/trunk/Documentation/DocBook/mac80211.tmpl
@@ -144,7 +144,7 @@ usage should require reading the full document.
this though and the recommendation to allow only a single
interface in STA mode at first!
-!Finclude/net/mac80211.h ieee80211_vif
+!Finclude/net/mac80211.h ieee80211_if_init_conf
@@ -234,6 +234,7 @@ usage should require reading the full document.
Multiple queues and QoS support
TBD
!Finclude/net/mac80211.h ieee80211_tx_queue_params
+!Finclude/net/mac80211.h ieee80211_tx_queue_stats
diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt
index 86f2ec90af87..591e94448e63 100644
--- a/trunk/Documentation/feature-removal-schedule.txt
+++ b/trunk/Documentation/feature-removal-schedule.txt
@@ -88,6 +88,27 @@ Who: Luis R. Rodriguez
---------------------------
+What: CONFIG_WIRELESS_OLD_REGULATORY - old static regulatory information
+When: March 2010 / desktop catchup
+
+Why: The old regulatory infrastructure has been replaced with a new one
+ which does not require statically defined regulatory domains. We do
+ not want to keep static regulatory domains in the kernel due to the
+ the dynamic nature of regulatory law and localization. We kept around
+ the old static definitions for the regulatory domains of:
+
+ * US
+ * JP
+ * EU
+
+ and used by default the US when CONFIG_WIRELESS_OLD_REGULATORY was
+ set. We will remove this option once the standard Linux desktop catches
+ up with the new userspace APIs we have implemented.
+
+Who: Luis R. Rodriguez
+
+---------------------------
+
What: dev->power.power_state
When: July 2007
Why: Broken design for runtime control over driver power states, confusing
diff --git a/trunk/Documentation/networking/regulatory.txt b/trunk/Documentation/networking/regulatory.txt
index 9551622d0a7b..ee31369e9e5b 100644
--- a/trunk/Documentation/networking/regulatory.txt
+++ b/trunk/Documentation/networking/regulatory.txt
@@ -188,27 +188,3 @@ Then in some part of your code after your wiphy has been registered:
&mydriver_jp_regdom.reg_rules[i],
sizeof(struct ieee80211_reg_rule));
regulatory_struct_hint(rd);
-
-Statically compiled regulatory database
----------------------------------------
-
-In most situations the userland solution using CRDA as described
-above is the preferred solution. However in some cases a set of
-rules built into the kernel itself may be desirable. To account
-for this situation, a configuration option has been provided
-(i.e. CONFIG_CFG80211_INTERNAL_REGDB). With this option enabled,
-the wireless database information contained in net/wireless/db.txt is
-used to generate a data structure encoded in net/wireless/regdb.c.
-That option also enables code in net/wireless/reg.c which queries
-the data in regdb.c as an alternative to using CRDA.
-
-The file net/wireless/db.txt should be kept up-to-date with the db.txt
-file available in the git repository here:
-
- git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-regdb.git
-
-Again, most users in most situations should be using the CRDA package
-provided with their distribution, and in most other situations users
-should be building and using CRDA on their own rather than using
-this option. If you are not absolutely sure that you should be using
-CONFIG_CFG80211_INTERNAL_REGDB then _DO_NOT_USE_IT_.
diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS
index 2b4a4d2f2ece..ea781c1cfb5a 100644
--- a/trunk/MAINTAINERS
+++ b/trunk/MAINTAINERS
@@ -5863,7 +5863,7 @@ S: Maintained
F: drivers/input/misc/wistron_btns.c
WL1251 WIRELESS DRIVER
-M: Kalle Valo
+M: Kalle Valo
L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
diff --git a/trunk/arch/powerpc/configs/ppc64_defconfig b/trunk/arch/powerpc/configs/ppc64_defconfig
index 070587ae4f74..252401824575 100644
--- a/trunk/arch/powerpc/configs/ppc64_defconfig
+++ b/trunk/arch/powerpc/configs/ppc64_defconfig
@@ -1000,6 +1000,7 @@ CONFIG_TIGON3=y
CONFIG_SPIDER_NET=m
CONFIG_GELIC_NET=m
CONFIG_GELIC_WIRELESS=y
+# CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
diff --git a/trunk/arch/powerpc/configs/ps3_defconfig b/trunk/arch/powerpc/configs/ps3_defconfig
index 32f7058bb173..7de127e4ceef 100644
--- a/trunk/arch/powerpc/configs/ps3_defconfig
+++ b/trunk/arch/powerpc/configs/ps3_defconfig
@@ -593,6 +593,7 @@ CONFIG_MII=m
CONFIG_NETDEV_1000=y
CONFIG_GELIC_NET=y
CONFIG_GELIC_WIRELESS=y
+# CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE is not set
# CONFIG_NETDEV_10000 is not set
#
diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig
index 6460505ab24c..18ff622703be 100644
--- a/trunk/drivers/net/Kconfig
+++ b/trunk/drivers/net/Kconfig
@@ -2354,6 +2354,20 @@ config GELIC_WIRELESS
the driver automatically distinguishes the models, you can
safely enable this option even if you have a wireless-less model.
+config GELIC_WIRELESS_OLD_PSK_INTERFACE
+ bool "PS3 Wireless private PSK interface (OBSOLETE)"
+ depends on GELIC_WIRELESS
+ select WEXT_PRIV
+ help
+ This option retains the obsolete private interface to pass
+ the PSK from user space programs to the driver. The PSK
+ stands for 'Pre Shared Key' and is used for WPA[2]-PSK
+ (WPA-Personal) environment.
+ If WPA[2]-PSK is used and you need to use old programs that
+ support only this old interface, say Y. Otherwise N.
+
+ If unsure, say N.
+
config FSL_PQ_MDIO
tristate "Freescale PQ MDIO"
depends on FSL_SOC
diff --git a/trunk/drivers/net/ps3_gelic_wireless.c b/trunk/drivers/net/ps3_gelic_wireless.c
index 2663b2fdc0bb..227b141c4fbd 100644
--- a/trunk/drivers/net/ps3_gelic_wireless.c
+++ b/trunk/drivers/net/ps3_gelic_wireless.c
@@ -1389,6 +1389,113 @@ static int gelic_wl_get_mode(struct net_device *netdev,
return 0;
}
+#ifdef CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE
+/* SIOCIWFIRSTPRIV */
+static int hex2bin(u8 *str, u8 *bin, unsigned int len)
+{
+ unsigned int i;
+ static unsigned char *hex = "0123456789ABCDEF";
+ unsigned char *p, *q;
+ u8 tmp;
+
+ if (len != WPA_PSK_LEN * 2)
+ return -EINVAL;
+
+ for (i = 0; i < WPA_PSK_LEN * 2; i += 2) {
+ p = strchr(hex, toupper(str[i]));
+ q = strchr(hex, toupper(str[i + 1]));
+ if (!p || !q) {
+ pr_info("%s: unconvertible PSK digit=%d\n",
+ __func__, i);
+ return -EINVAL;
+ }
+ tmp = ((p - hex) << 4) + (q - hex);
+ *bin++ = tmp;
+ }
+ return 0;
+};
+
+static int gelic_wl_priv_set_psk(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data, char *extra)
+{
+ struct gelic_wl_info *wl = port_wl(netdev_priv(net_dev));
+ unsigned int len;
+ unsigned long irqflag;
+ int ret = 0;
+
+ pr_debug("%s:<- len=%d\n", __func__, data->data.length);
+ len = data->data.length - 1;
+ if (len <= 2)
+ return -EINVAL;
+
+ spin_lock_irqsave(&wl->lock, irqflag);
+ if (extra[0] == '"' && extra[len - 1] == '"') {
+ pr_debug("%s: passphrase mode\n", __func__);
+ /* pass phrase */
+ if (GELIC_WL_EURUS_PSK_MAX_LEN < (len - 2)) {
+ pr_info("%s: passphrase too long\n", __func__);
+ ret = -E2BIG;
+ goto out;
+ }
+ memset(wl->psk, 0, sizeof(wl->psk));
+ wl->psk_len = len - 2;
+ memcpy(wl->psk, &(extra[1]), wl->psk_len);
+ wl->psk_type = GELIC_EURUS_WPA_PSK_PASSPHRASE;
+ } else {
+ ret = hex2bin(extra, wl->psk, len);
+ if (ret)
+ goto out;
+ wl->psk_len = WPA_PSK_LEN;
+ wl->psk_type = GELIC_EURUS_WPA_PSK_BIN;
+ }
+ set_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat);
+out:
+ spin_unlock_irqrestore(&wl->lock, irqflag);
+ pr_debug("%s:->\n", __func__);
+ return ret;
+}
+
+static int gelic_wl_priv_get_psk(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data, char *extra)
+{
+ struct gelic_wl_info *wl = port_wl(netdev_priv(net_dev));
+ char *p;
+ unsigned long irqflag;
+ unsigned int i;
+
+ pr_debug("%s:<-\n", __func__);
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ spin_lock_irqsave(&wl->lock, irqflag);
+ p = extra;
+ if (test_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat)) {
+ if (wl->psk_type == GELIC_EURUS_WPA_PSK_BIN) {
+ for (i = 0; i < wl->psk_len; i++) {
+ sprintf(p, "%02xu", wl->psk[i]);
+ p += 2;
+ }
+ *p = '\0';
+ data->data.length = wl->psk_len * 2;
+ } else {
+ *p++ = '"';
+ memcpy(p, wl->psk, wl->psk_len);
+ p += wl->psk_len;
+ *p++ = '"';
+ *p = '\0';
+ data->data.length = wl->psk_len + 2;
+ }
+ } else
+ /* no psk set */
+ data->data.length = 0;
+ spin_unlock_irqrestore(&wl->lock, irqflag);
+ pr_debug("%s:-> %d\n", __func__, data->data.length);
+ return 0;
+}
+#endif
+
/* SIOCGIWNICKN */
static int gelic_wl_get_nick(struct net_device *net_dev,
struct iw_request_info *info,
@@ -1464,10 +1571,8 @@ static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan,
init_completion(&wl->scan_done);
/*
* If we have already a bss list, don't try to get new
- * unless we are doing an ESSID scan
*/
- if ((!essid_len && !always_scan)
- && wl->scan_stat == GELIC_WL_SCAN_STAT_GOT_LIST) {
+ if (!always_scan && wl->scan_stat == GELIC_WL_SCAN_STAT_GOT_LIST) {
pr_debug("%s: already has the list\n", __func__);
complete(&wl->scan_done);
goto out;
@@ -1568,7 +1673,7 @@ static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl)
}
}
- /* put them in the network_list */
+ /* put them in the newtork_list */
for (i = 0, scan_info_size = 0, scan_info = buf;
scan_info_size < data_len;
i++, scan_info_size += be16_to_cpu(scan_info->size),
@@ -1904,7 +2009,7 @@ static int gelic_wl_do_wpa_setup(struct gelic_wl_info *wl)
/* PSK type */
wpa->psk_type = cpu_to_be16(wl->psk_type);
#ifdef DEBUG
- pr_debug("%s: sec=%s psktype=%s\n", __func__,
+ pr_debug("%s: sec=%s psktype=%s\nn", __func__,
wpasecstr(wpa->security),
(wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ?
"BIN" : "passphrase");
@@ -1914,9 +2019,9 @@ static int gelic_wl_do_wpa_setup(struct gelic_wl_info *wl)
* the debug log because this dumps your precious
* passphrase/key.
*/
- pr_debug("%s: psk=%s\n", __func__,
+ pr_debug("%s: psk=%s\n",
(wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ?
- "N/A" : wpa->psk);
+ (char *)"N/A" : (char *)wpa->psk);
#endif
#endif
/* issue wpa setup */
@@ -2301,10 +2406,40 @@ static const iw_handler gelic_wl_wext_handler[] =
IW_IOCTL(SIOCGIWNICKN) = gelic_wl_get_nick,
};
+#ifdef CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE
+static struct iw_priv_args gelic_wl_private_args[] =
+{
+ {
+ .cmd = GELIC_WL_PRIV_SET_PSK,
+ .set_args = IW_PRIV_TYPE_CHAR |
+ (GELIC_WL_EURUS_PSK_MAX_LEN + 2),
+ .name = "set_psk"
+ },
+ {
+ .cmd = GELIC_WL_PRIV_GET_PSK,
+ .get_args = IW_PRIV_TYPE_CHAR |
+ (GELIC_WL_EURUS_PSK_MAX_LEN + 2),
+ .name = "get_psk"
+ }
+};
+
+static const iw_handler gelic_wl_private_handler[] =
+{
+ gelic_wl_priv_set_psk,
+ gelic_wl_priv_get_psk,
+};
+#endif
+
static const struct iw_handler_def gelic_wl_wext_handler_def = {
.num_standard = ARRAY_SIZE(gelic_wl_wext_handler),
.standard = gelic_wl_wext_handler,
.get_wireless_stats = gelic_wl_get_wireless_stats,
+#ifdef CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE
+ .num_private = ARRAY_SIZE(gelic_wl_private_handler),
+ .num_private_args = ARRAY_SIZE(gelic_wl_private_args),
+ .private = gelic_wl_private_handler,
+ .private_args = gelic_wl_private_args,
+#endif
};
static struct net_device * __devinit gelic_wl_alloc(struct gelic_card *card)
diff --git a/trunk/drivers/net/wireless/Kconfig b/trunk/drivers/net/wireless/Kconfig
index 588943660755..56dd6650c97a 100644
--- a/trunk/drivers/net/wireless/Kconfig
+++ b/trunk/drivers/net/wireless/Kconfig
@@ -112,7 +112,6 @@ config AIRO_CS
depends on PCMCIA && (BROKEN || !M32R)
select WIRELESS_EXT
select WEXT_SPY
- select WEXT_PRIV
select CRYPTO
select CRYPTO_AES
---help---
diff --git a/trunk/drivers/net/wireless/adm8211.c b/trunk/drivers/net/wireless/adm8211.c
index 6508515feed3..39410016b4ff 100644
--- a/trunk/drivers/net/wireless/adm8211.c
+++ b/trunk/drivers/net/wireless/adm8211.c
@@ -302,6 +302,18 @@ static int adm8211_get_stats(struct ieee80211_hw *dev,
return 0;
}
+static int adm8211_get_tx_stats(struct ieee80211_hw *dev,
+ struct ieee80211_tx_queue_stats *stats)
+{
+ struct adm8211_priv *priv = dev->priv;
+
+ stats[0].len = priv->cur_tx - priv->dirty_tx;
+ stats[0].limit = priv->tx_ring_size - 2;
+ stats[0].count = priv->dirty_tx;
+
+ return 0;
+}
+
static void adm8211_interrupt_tci(struct ieee80211_hw *dev)
{
struct adm8211_priv *priv = dev->priv;
@@ -1388,15 +1400,15 @@ static void adm8211_configure_filter(struct ieee80211_hw *dev,
}
static int adm8211_add_interface(struct ieee80211_hw *dev,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct adm8211_priv *priv = dev->priv;
if (priv->mode != NL80211_IFTYPE_MONITOR)
return -EOPNOTSUPP;
- switch (vif->type) {
+ switch (conf->type) {
case NL80211_IFTYPE_STATION:
- priv->mode = vif->type;
+ priv->mode = conf->type;
break;
default:
return -EOPNOTSUPP;
@@ -1404,8 +1416,8 @@ static int adm8211_add_interface(struct ieee80211_hw *dev,
ADM8211_IDLE();
- ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)vif->addr));
- ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(vif->addr + 4)));
+ ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)conf->mac_addr));
+ ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(conf->mac_addr + 4)));
adm8211_update_mode(dev);
@@ -1415,7 +1427,7 @@ static int adm8211_add_interface(struct ieee80211_hw *dev,
}
static void adm8211_remove_interface(struct ieee80211_hw *dev,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct adm8211_priv *priv = dev->priv;
priv->mode = NL80211_IFTYPE_MONITOR;
@@ -1761,6 +1773,7 @@ static const struct ieee80211_ops adm8211_ops = {
.prepare_multicast = adm8211_prepare_multicast,
.configure_filter = adm8211_configure_filter,
.get_stats = adm8211_get_stats,
+ .get_tx_stats = adm8211_get_tx_stats,
.get_tsf = adm8211_get_tsft
};
diff --git a/trunk/drivers/net/wireless/airo.c b/trunk/drivers/net/wireless/airo.c
index 260fb9905e97..4331d675fcc6 100644
--- a/trunk/drivers/net/wireless/airo.c
+++ b/trunk/drivers/net/wireless/airo.c
@@ -51,7 +51,6 @@
#include
#include
-#include
#include "airo.h"
@@ -5255,7 +5254,11 @@ static int set_wep_key(struct airo_info *ai, u16 index, const char *key,
WepKeyRid wkr;
int rc;
- WARN_ON(keylen == 0);
+ if (keylen == 0) {
+ airo_print_err(ai->dev->name, "%s: key length to set was zero",
+ __func__);
+ return -1;
+ }
memset(&wkr, 0, sizeof(wkr));
wkr.len = cpu_to_le16(sizeof(wkr));
@@ -6402,7 +6405,11 @@ static int airo_set_encode(struct net_device *dev,
if (dwrq->length > MIN_KEY_SIZE)
key.len = MAX_KEY_SIZE;
else
- key.len = MIN_KEY_SIZE;
+ if (dwrq->length > 0)
+ key.len = MIN_KEY_SIZE;
+ else
+ /* Disable the key */
+ key.len = 0;
/* Check if the key is not marked as invalid */
if(!(dwrq->flags & IW_ENCODE_NOKEY)) {
/* Cleanup */
@@ -6583,22 +6590,12 @@ static int airo_set_encodeext(struct net_device *dev,
default:
return -EINVAL;
}
- if (key.len == 0) {
- rc = set_wep_tx_idx(local, idx, perm, 1);
- if (rc < 0) {
- airo_print_err(local->dev->name,
- "failed to set WEP transmit index to %d: %d.",
- idx, rc);
- return rc;
- }
- } else {
- rc = set_wep_key(local, idx, key.key, key.len, perm, 1);
- if (rc < 0) {
- airo_print_err(local->dev->name,
- "failed to set WEP key at index %d: %d.",
- idx, rc);
- return rc;
- }
+ /* Send the key to the card */
+ rc = set_wep_key(local, idx, key.key, key.len, perm, 1);
+ if (rc < 0) {
+ airo_print_err(local->dev->name, "failed to set WEP key"
+ " at index %d: %d.", idx, rc);
+ return rc;
}
}
diff --git a/trunk/drivers/net/wireless/at76c50x-usb.c b/trunk/drivers/net/wireless/at76c50x-usb.c
index 0fb419936dff..2517364d3ebe 100644
--- a/trunk/drivers/net/wireless/at76c50x-usb.c
+++ b/trunk/drivers/net/wireless/at76c50x-usb.c
@@ -1789,7 +1789,7 @@ static void at76_mac80211_stop(struct ieee80211_hw *hw)
}
static int at76_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct at76_priv *priv = hw->priv;
int ret = 0;
@@ -1798,7 +1798,7 @@ static int at76_add_interface(struct ieee80211_hw *hw,
mutex_lock(&priv->mtx);
- switch (vif->type) {
+ switch (conf->type) {
case NL80211_IFTYPE_STATION:
priv->iw_mode = IW_MODE_INFRA;
break;
@@ -1814,7 +1814,7 @@ static int at76_add_interface(struct ieee80211_hw *hw,
}
static void at76_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
at76_dbg(DBG_MAC80211, "%s()", __func__);
}
diff --git a/trunk/drivers/net/wireless/ath/ar9170/ar9170.h b/trunk/drivers/net/wireless/ath/ar9170/ar9170.h
index 8c8ce67971e9..9f9459860d82 100644
--- a/trunk/drivers/net/wireless/ath/ar9170/ar9170.h
+++ b/trunk/drivers/net/wireless/ath/ar9170/ar9170.h
@@ -109,6 +109,7 @@ struct ar9170_rxstream_mpdu_merge {
bool has_plcp;
};
+#define AR9170_NUM_MAX_BA_RETRY 5
#define AR9170_NUM_TID 16
#define WME_BA_BMP_SIZE 64
#define AR9170_NUM_MAX_AGG_LEN (2 * WME_BA_BMP_SIZE)
@@ -142,12 +143,7 @@ struct ar9170_sta_tid {
u16 tid;
enum ar9170_tid_state state;
bool active;
-};
-
-struct ar9170_tx_queue_stats {
- unsigned int len;
- unsigned int limit;
- unsigned int count;
+ u8 retry;
};
#define AR9170_QUEUE_TIMEOUT 64
@@ -158,8 +154,6 @@ struct ar9170_tx_queue_stats {
#define AR9170_NUM_TX_STATUS 128
#define AR9170_NUM_TX_AGG_MAX 30
-#define AR9170_NUM_TX_LIMIT_HARD AR9170_TXQ_DEPTH
-#define AR9170_NUM_TX_LIMIT_SOFT (AR9170_TXQ_DEPTH - 10)
struct ar9170 {
struct ieee80211_hw *hw;
@@ -217,7 +211,7 @@ struct ar9170 {
/* qos queue settings */
spinlock_t tx_stats_lock;
- struct ar9170_tx_queue_stats tx_stats[5];
+ struct ieee80211_tx_queue_stats tx_stats[5];
struct ieee80211_tx_queue_params edcf[5];
spinlock_t cmdlock;
@@ -254,8 +248,13 @@ struct ar9170_sta_info {
unsigned int ampdu_max_len;
};
+#define AR9170_TX_FLAG_WAIT_FOR_ACK BIT(0)
+#define AR9170_TX_FLAG_NO_ACK BIT(1)
+#define AR9170_TX_FLAG_BLOCK_ACK BIT(2)
+
struct ar9170_tx_info {
unsigned long timeout;
+ unsigned int flags;
};
#define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED)
diff --git a/trunk/drivers/net/wireless/ath/ar9170/hw.h b/trunk/drivers/net/wireless/ath/ar9170/hw.h
index 0a1d4c28e68a..701ddb7d8400 100644
--- a/trunk/drivers/net/wireless/ath/ar9170/hw.h
+++ b/trunk/drivers/net/wireless/ath/ar9170/hw.h
@@ -276,7 +276,6 @@ struct ar9170_tx_control {
#define AR9170_TX_MAC_RATE_PROBE 0x8000
/* either-or */
-#define AR9170_TX_PHY_MOD_MASK 0x00000003
#define AR9170_TX_PHY_MOD_CCK 0x00000000
#define AR9170_TX_PHY_MOD_OFDM 0x00000001
#define AR9170_TX_PHY_MOD_HT 0x00000002
diff --git a/trunk/drivers/net/wireless/ath/ar9170/mac.c b/trunk/drivers/net/wireless/ath/ar9170/mac.c
index 857e86104295..ddc8c09dc79e 100644
--- a/trunk/drivers/net/wireless/ath/ar9170/mac.c
+++ b/trunk/drivers/net/wireless/ath/ar9170/mac.c
@@ -117,7 +117,7 @@ int ar9170_set_qos(struct ar9170 *ar)
ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP,
ar->edcf[0].txop | ar->edcf[1].txop << 16);
ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP,
- ar->edcf[2].txop | ar->edcf[3].txop << 16);
+ ar->edcf[1].txop | ar->edcf[3].txop << 16);
ar9170_regwrite_finish();
diff --git a/trunk/drivers/net/wireless/ath/ar9170/main.c b/trunk/drivers/net/wireless/ath/ar9170/main.c
index 8a964f130367..f9d6db8d013e 100644
--- a/trunk/drivers/net/wireless/ath/ar9170/main.c
+++ b/trunk/drivers/net/wireless/ath/ar9170/main.c
@@ -194,15 +194,12 @@ static inline u16 ar9170_get_seq(struct sk_buff *skb)
return ar9170_get_seq_h((void *) txc->frame_data);
}
-static inline u16 ar9170_get_tid_h(struct ieee80211_hdr *hdr)
-{
- return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK;
-}
-
static inline u16 ar9170_get_tid(struct sk_buff *skb)
{
struct ar9170_tx_control *txc = (void *) skb->data;
- return ar9170_get_tid_h((struct ieee80211_hdr *) txc->frame_data);
+ struct ieee80211_hdr *hdr = (void *) txc->frame_data;
+
+ return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK;
}
#define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff)
@@ -216,10 +213,10 @@ static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb)
struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
struct ieee80211_hdr *hdr = (void *) txc->frame_data;
- printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] s:%d "
+ printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x s:%d "
"mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n",
wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb),
- ieee80211_get_DA(hdr), ar9170_get_seq_h(hdr),
+ ieee80211_get_DA(hdr), arinfo->flags, ar9170_get_seq_h(hdr),
le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control),
jiffies_to_msecs(arinfo->timeout - jiffies));
}
@@ -433,7 +430,7 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb)
spin_lock_irqsave(&ar->tx_stats_lock, flags);
ar->tx_stats[queue].len--;
- if (ar->tx_stats[queue].len < AR9170_NUM_TX_LIMIT_SOFT) {
+ if (skb_queue_empty(&ar->tx_pending[queue])) {
#ifdef AR9170_QUEUE_STOP_DEBUG
printk(KERN_DEBUG "%s: wake queue %d\n",
wiphy_name(ar->hw->wiphy), queue);
@@ -443,17 +440,22 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb)
}
spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
- if (info->flags & IEEE80211_TX_CTL_NO_ACK) {
- ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED);
- } else {
- if (info->flags & IEEE80211_TX_CTL_AMPDU) {
- ar9170_tx_ampdu_callback(ar, skb);
- } else {
- arinfo->timeout = jiffies +
+ if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) {
+ ar9170_tx_ampdu_callback(ar, skb);
+ } else if (arinfo->flags & AR9170_TX_FLAG_WAIT_FOR_ACK) {
+ arinfo->timeout = jiffies +
msecs_to_jiffies(AR9170_TX_TIMEOUT);
- skb_queue_tail(&ar->tx_status[queue], skb);
- }
+ skb_queue_tail(&ar->tx_status[queue], skb);
+ } else if (arinfo->flags & AR9170_TX_FLAG_NO_ACK) {
+ ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED);
+ } else {
+#ifdef AR9170_QUEUE_DEBUG
+ printk(KERN_DEBUG "%s: unsupported frame flags!\n",
+ wiphy_name(ar->hw->wiphy));
+ ar9170_print_txheader(ar, skb);
+#endif /* AR9170_QUEUE_DEBUG */
+ dev_kfree_skb_any(skb);
}
if (!ar->tx_stats[queue].len &&
@@ -1405,6 +1407,17 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
(is_valid_ether_addr(ieee80211_get_DA(hdr)))) {
+ if (info->flags & IEEE80211_TX_CTL_AMPDU) {
+ if (unlikely(!info->control.sta))
+ goto err_out;
+
+ txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR);
+ arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK;
+
+ goto out;
+ }
+
+ txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE);
/*
* WARNING:
* Putting the QoS queue bits into an unexplored territory is
@@ -1418,17 +1431,12 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
txc->phy_control |=
cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT);
-
- if (info->flags & IEEE80211_TX_CTL_AMPDU) {
- if (unlikely(!info->control.sta))
- goto err_out;
-
- txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR);
- } else {
- txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE);
- }
+ arinfo->flags = AR9170_TX_FLAG_WAIT_FOR_ACK;
+ } else {
+ arinfo->flags = AR9170_TX_FLAG_NO_ACK;
}
+out:
return 0;
err_out:
@@ -1663,7 +1671,8 @@ static bool ar9170_tx_ampdu(struct ar9170 *ar)
* tell the FW/HW that this is the last frame,
* that way it will wait for the immediate block ack.
*/
- ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg));
+ if (likely(skb_peek_tail(&agg)))
+ ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg));
#ifdef AR9170_TXAGG_DEBUG
printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n",
@@ -1707,21 +1716,6 @@ static void ar9170_tx(struct ar9170 *ar)
for (i = 0; i < __AR9170_NUM_TXQ; i++) {
spin_lock_irqsave(&ar->tx_stats_lock, flags);
- frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len,
- skb_queue_len(&ar->tx_pending[i]));
-
- if (remaining_space < frames) {
-#ifdef AR9170_QUEUE_DEBUG
- printk(KERN_DEBUG "%s: tx quota reached queue:%d, "
- "remaining slots:%d, needed:%d\n",
- wiphy_name(ar->hw->wiphy), i, remaining_space,
- frames);
-#endif /* AR9170_QUEUE_DEBUG */
- frames = remaining_space;
- }
-
- ar->tx_stats[i].len += frames;
- ar->tx_stats[i].count += frames;
if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) {
#ifdef AR9170_QUEUE_DEBUG
printk(KERN_DEBUG "%s: queue %d full\n",
@@ -1739,8 +1733,25 @@ static void ar9170_tx(struct ar9170 *ar)
__ar9170_dump_txstats(ar);
#endif /* AR9170_QUEUE_STOP_DEBUG */
ieee80211_stop_queue(ar->hw, i);
+ spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
+ continue;
+ }
+
+ frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len,
+ skb_queue_len(&ar->tx_pending[i]));
+
+ if (remaining_space < frames) {
+#ifdef AR9170_QUEUE_DEBUG
+ printk(KERN_DEBUG "%s: tx quota reached queue:%d, "
+ "remaining slots:%d, needed:%d\n",
+ wiphy_name(ar->hw->wiphy), i, remaining_space,
+ frames);
+#endif /* AR9170_QUEUE_DEBUG */
+ frames = remaining_space;
}
+ ar->tx_stats[i].len += frames;
+ ar->tx_stats[i].count += frames;
spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
if (!frames)
@@ -1762,7 +1773,7 @@ static void ar9170_tx(struct ar9170 *ar)
arinfo->timeout = jiffies +
msecs_to_jiffies(AR9170_TX_TIMEOUT);
- if (info->flags & IEEE80211_TX_CTL_AMPDU)
+ if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK)
atomic_inc(&ar->tx_ampdu_pending);
#ifdef AR9170_QUEUE_DEBUG
@@ -1773,7 +1784,7 @@ static void ar9170_tx(struct ar9170 *ar)
err = ar->tx(ar, skb);
if (unlikely(err)) {
- if (info->flags & IEEE80211_TX_CTL_AMPDU)
+ if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK)
atomic_dec(&ar->tx_ampdu_pending);
frames_failed++;
@@ -1939,7 +1950,7 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
}
static int ar9170_op_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct ar9170 *ar = hw->priv;
struct ath_common *common = &ar->common;
@@ -1952,8 +1963,8 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw,
goto unlock;
}
- ar->vif = vif;
- memcpy(common->macaddr, vif->addr, ETH_ALEN);
+ ar->vif = conf->vif;
+ memcpy(common->macaddr, conf->mac_addr, ETH_ALEN);
if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) {
ar->rx_software_decryption = true;
@@ -1973,7 +1984,7 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw,
}
static void ar9170_op_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct ar9170 *ar = hw->priv;
@@ -2329,55 +2340,55 @@ static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return err;
}
-static int ar9170_sta_add(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+static void ar9170_sta_notify(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ enum sta_notify_cmd cmd,
+ struct ieee80211_sta *sta)
{
struct ar9170 *ar = hw->priv;
struct ar9170_sta_info *sta_info = (void *) sta->drv_priv;
unsigned int i;
- memset(sta_info, 0, sizeof(*sta_info));
+ switch (cmd) {
+ case STA_NOTIFY_ADD:
+ memset(sta_info, 0, sizeof(*sta_info));
- if (!sta->ht_cap.ht_supported)
- return 0;
+ if (!sta->ht_cap.ht_supported)
+ break;
- if (sta->ht_cap.ampdu_density > ar->global_ampdu_density)
- ar->global_ampdu_density = sta->ht_cap.ampdu_density;
+ if (sta->ht_cap.ampdu_density > ar->global_ampdu_density)
+ ar->global_ampdu_density = sta->ht_cap.ampdu_density;
- if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor)
- ar->global_ampdu_factor = sta->ht_cap.ampdu_factor;
+ if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor)
+ ar->global_ampdu_factor = sta->ht_cap.ampdu_factor;
- for (i = 0; i < AR9170_NUM_TID; i++) {
- sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN;
- sta_info->agg[i].active = false;
- sta_info->agg[i].ssn = 0;
- sta_info->agg[i].tid = i;
- INIT_LIST_HEAD(&sta_info->agg[i].list);
- skb_queue_head_init(&sta_info->agg[i].queue);
- }
+ for (i = 0; i < AR9170_NUM_TID; i++) {
+ sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN;
+ sta_info->agg[i].active = false;
+ sta_info->agg[i].ssn = 0;
+ sta_info->agg[i].retry = 0;
+ sta_info->agg[i].tid = i;
+ INIT_LIST_HEAD(&sta_info->agg[i].list);
+ skb_queue_head_init(&sta_info->agg[i].queue);
+ }
- sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor);
+ sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor);
+ break;
- return 0;
-}
+ case STA_NOTIFY_REMOVE:
+ if (!sta->ht_cap.ht_supported)
+ break;
-static int ar9170_sta_remove(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
-{
- struct ar9170_sta_info *sta_info = (void *) sta->drv_priv;
- unsigned int i;
+ for (i = 0; i < AR9170_NUM_TID; i++) {
+ sta_info->agg[i].state = AR9170_TID_STATE_INVALID;
+ skb_queue_purge(&sta_info->agg[i].queue);
+ }
- if (!sta->ht_cap.ht_supported)
- return 0;
+ break;
- for (i = 0; i < AR9170_NUM_TID; i++) {
- sta_info->agg[i].state = AR9170_TID_STATE_INVALID;
- skb_queue_purge(&sta_info->agg[i].queue);
+ default:
+ break;
}
-
- return 0;
}
static int ar9170_get_stats(struct ieee80211_hw *hw,
@@ -2397,6 +2408,18 @@ static int ar9170_get_stats(struct ieee80211_hw *hw,
return 0;
}
+static int ar9170_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *tx_stats)
+{
+ struct ar9170 *ar = hw->priv;
+
+ spin_lock_bh(&ar->tx_stats_lock);
+ memcpy(tx_stats, ar->tx_stats, sizeof(tx_stats[0]) * hw->queues);
+ spin_unlock_bh(&ar->tx_stats_lock);
+
+ return 0;
+}
+
static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *param)
{
@@ -2496,9 +2519,9 @@ static const struct ieee80211_ops ar9170_ops = {
.bss_info_changed = ar9170_op_bss_info_changed,
.get_tsf = ar9170_op_get_tsf,
.set_key = ar9170_set_key,
- .sta_add = ar9170_sta_add,
- .sta_remove = ar9170_sta_remove,
+ .sta_notify = ar9170_sta_notify,
.get_stats = ar9170_get_stats,
+ .get_tx_stats = ar9170_get_tx_stats,
.ampdu_action = ar9170_ampdu_action,
};
diff --git a/trunk/drivers/net/wireless/ath/ar9170/usb.c b/trunk/drivers/net/wireless/ath/ar9170/usb.c
index 0f361186b78f..e0799d924057 100644
--- a/trunk/drivers/net/wireless/ath/ar9170/usb.c
+++ b/trunk/drivers/net/wireless/ath/ar9170/usb.c
@@ -84,8 +84,6 @@ static struct usb_device_id ar9170_usb_ids[] = {
{ USB_DEVICE(0x0cde, 0x0023) },
/* Z-Com UB82 ABG */
{ USB_DEVICE(0x0cde, 0x0026) },
- /* Sphairon Homelink 1202 */
- { USB_DEVICE(0x0cde, 0x0027) },
/* Arcadyan WN7512 */
{ USB_DEVICE(0x083a, 0xf522) },
/* Planex GWUS300 */
diff --git a/trunk/drivers/net/wireless/ath/ath.h b/trunk/drivers/net/wireless/ath/ath.h
index 71fc960814f0..9e05648356fe 100644
--- a/trunk/drivers/net/wireless/ath/ath.h
+++ b/trunk/drivers/net/wireless/ath/ath.h
@@ -74,6 +74,7 @@ struct ath_common;
struct ath_bus_ops {
void (*read_cachesize)(struct ath_common *common, int *csz);
+ void (*cleanup)(struct ath_common *common);
bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
void (*bt_coex_prep)(struct ath_common *common);
};
diff --git a/trunk/drivers/net/wireless/ath/ath5k/ath5k.h b/trunk/drivers/net/wireless/ath/ath5k/ath5k.h
index ac67f02e26d8..6a2a96761111 100644
--- a/trunk/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/trunk/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -535,12 +535,13 @@ struct ath5k_txq_info {
u32 tqi_cbr_period; /* Constant bit rate period */
u32 tqi_cbr_overflow_limit;
u32 tqi_burst_time;
- u32 tqi_ready_time; /* Time queue waits after an event */
+ u32 tqi_ready_time; /* Not used */
};
/*
* Transmit packet types.
* used on tx control descriptor
+ * TODO: Use them inside base.c corectly
*/
enum ath5k_pkt_type {
AR5K_PKT_TYPE_NORMAL = 0,
@@ -1062,7 +1063,6 @@ struct ath5k_hw {
u32 ah_cw_min;
u32 ah_cw_max;
u32 ah_limit_tx_retries;
- u8 ah_coverage_class;
/* Antenna Control */
u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
@@ -1200,7 +1200,6 @@ extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah);
/* Protocol Control Unit Functions */
extern int ath5k_hw_set_opmode(struct ath5k_hw *ah);
-extern void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class);
/* BSSID Functions */
extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
extern void ath5k_hw_set_associd(struct ath5k_hw *ah);
@@ -1232,10 +1231,6 @@ extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout);
extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah);
extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout);
extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah);
-/* Clock rate related functions */
-unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec);
-unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock);
-unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah);
/* Key table (WEP) functions */
extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry);
extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry);
@@ -1315,6 +1310,24 @@ extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower);
* Functions used internaly
*/
+/*
+ * Translate usec to hw clock units
+ * TODO: Half/quarter rate
+ */
+static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
+{
+ return turbo ? (usec * 80) : (usec * 40);
+}
+
+/*
+ * Translate hw clock units to usec
+ * TODO: Half/quarter rate
+ */
+static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
+{
+ return turbo ? (clock / 80) : (clock / 40);
+}
+
static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah)
{
return &ah->common;
diff --git a/trunk/drivers/net/wireless/ath/ath5k/base.c b/trunk/drivers/net/wireless/ath/ath5k/base.c
index 2468c64d6c12..e63b7c40d0ee 100644
--- a/trunk/drivers/net/wireless/ath/ath5k/base.c
+++ b/trunk/drivers/net/wireless/ath/ath5k/base.c
@@ -225,9 +225,9 @@ static int ath5k_reset_wake(struct ath5k_softc *sc);
static int ath5k_start(struct ieee80211_hw *hw);
static void ath5k_stop(struct ieee80211_hw *hw);
static int ath5k_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
+ struct ieee80211_if_init_conf *conf);
static void ath5k_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
+ struct ieee80211_if_init_conf *conf);
static int ath5k_config(struct ieee80211_hw *hw, u32 changed);
static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw,
int mc_count, struct dev_addr_list *mc_list);
@@ -241,6 +241,8 @@ static int ath5k_set_key(struct ieee80211_hw *hw,
struct ieee80211_key_conf *key);
static int ath5k_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats);
+static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats);
static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf);
static void ath5k_reset_tsf(struct ieee80211_hw *hw);
@@ -252,8 +254,6 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
u32 changes);
static void ath5k_sw_scan_start(struct ieee80211_hw *hw);
static void ath5k_sw_scan_complete(struct ieee80211_hw *hw);
-static void ath5k_set_coverage_class(struct ieee80211_hw *hw,
- u8 coverage_class);
static const struct ieee80211_ops ath5k_hw_ops = {
.tx = ath5k_tx,
@@ -267,13 +267,13 @@ static const struct ieee80211_ops ath5k_hw_ops = {
.set_key = ath5k_set_key,
.get_stats = ath5k_get_stats,
.conf_tx = NULL,
+ .get_tx_stats = ath5k_get_tx_stats,
.get_tsf = ath5k_get_tsf,
.set_tsf = ath5k_set_tsf,
.reset_tsf = ath5k_reset_tsf,
.bss_info_changed = ath5k_bss_info_changed,
.sw_scan_start = ath5k_sw_scan_start,
.sw_scan_complete = ath5k_sw_scan_complete,
- .set_coverage_class = ath5k_set_coverage_class,
};
/*
@@ -1246,29 +1246,6 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
return 0;
}
-static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb)
-{
- struct ieee80211_hdr *hdr;
- enum ath5k_pkt_type htype;
- __le16 fc;
-
- hdr = (struct ieee80211_hdr *)skb->data;
- fc = hdr->frame_control;
-
- if (ieee80211_is_beacon(fc))
- htype = AR5K_PKT_TYPE_BEACON;
- else if (ieee80211_is_probe_resp(fc))
- htype = AR5K_PKT_TYPE_PROBE_RESP;
- else if (ieee80211_is_atim(fc))
- htype = AR5K_PKT_TYPE_ATIM;
- else if (ieee80211_is_pspoll(fc))
- htype = AR5K_PKT_TYPE_PSPOLL;
- else
- htype = AR5K_PKT_TYPE_NORMAL;
-
- return htype;
-}
-
static int
ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
struct ath5k_txq *txq)
@@ -1323,8 +1300,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
sc->vif, pktlen, info));
}
ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
- ieee80211_get_hdrlen_from_skb(skb),
- get_hw_packet_type(skb),
+ ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
(sc->power_level * 2),
hw_rate,
info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags,
@@ -1353,6 +1329,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
spin_lock_bh(&txq->lock);
list_add_tail(&bf->list, &txq->q);
+ sc->tx_stats[txq->qnum].len++;
if (txq->link == NULL) /* is this first packet? */
ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr);
else /* no, so only link it */
@@ -1536,8 +1513,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi);
if (ret)
- goto err;
-
+ return ret;
if (sc->opmode == NL80211_IFTYPE_AP ||
sc->opmode == NL80211_IFTYPE_MESH_POINT) {
/*
@@ -1564,25 +1540,10 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
if (ret) {
ATH5K_ERR(sc, "%s: unable to update parameters for beacon "
"hardware queue!\n", __func__);
- goto err;
+ return ret;
}
- ret = ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */
- if (ret)
- goto err;
-
- /* reconfigure cabq with ready time to 80% of beacon_interval */
- ret = ath5k_hw_get_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi);
- if (ret)
- goto err;
-
- qi.tqi_ready_time = (sc->bintval * 80) / 100;
- ret = ath5k_hw_set_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi);
- if (ret)
- goto err;
- ret = ath5k_hw_reset_tx_queue(ah, AR5K_TX_QUEUE_ID_CAB);
-err:
- return ret;
+ return ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */;
}
static void
@@ -1601,6 +1562,7 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
ath5k_txbuf_free(sc, bf);
spin_lock_bh(&sc->txbuflock);
+ sc->tx_stats[txq->qnum].len--;
list_move_tail(&bf->list, &sc->txbuf);
sc->txbuf_len++;
spin_unlock_bh(&sc->txbuflock);
@@ -2030,8 +1992,10 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
}
ieee80211_tx_status(sc->hw, skb);
+ sc->tx_stats[txq->qnum].count++;
spin_lock(&sc->txbuflock);
+ sc->tx_stats[txq->qnum].len--;
list_move_tail(&bf->list, &sc->txbuf);
sc->txbuf_len++;
spin_unlock(&sc->txbuflock);
@@ -2809,7 +2773,7 @@ static void ath5k_stop(struct ieee80211_hw *hw)
}
static int ath5k_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct ath5k_softc *sc = hw->priv;
int ret;
@@ -2820,22 +2784,22 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
goto end;
}
- sc->vif = vif;
+ sc->vif = conf->vif;
- switch (vif->type) {
+ switch (conf->type) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_MONITOR:
- sc->opmode = vif->type;
+ sc->opmode = conf->type;
break;
default:
ret = -EOPNOTSUPP;
goto end;
}
- ath5k_hw_set_lladdr(sc->ah, vif->addr);
+ ath5k_hw_set_lladdr(sc->ah, conf->mac_addr);
ath5k_mode_setup(sc);
ret = 0;
@@ -2846,13 +2810,13 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
static void
ath5k_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct ath5k_softc *sc = hw->priv;
u8 mac[ETH_ALEN] = {};
mutex_lock(&sc->lock);
- if (sc->vif != vif)
+ if (sc->vif != conf->vif)
goto end;
ath5k_hw_set_lladdr(sc->ah, mac);
@@ -3133,6 +3097,17 @@ ath5k_get_stats(struct ieee80211_hw *hw,
return 0;
}
+static int
+ath5k_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats)
+{
+ struct ath5k_softc *sc = hw->priv;
+
+ memcpy(stats, &sc->tx_stats, sizeof(sc->tx_stats));
+
+ return 0;
+}
+
static u64
ath5k_get_tsf(struct ieee80211_hw *hw)
{
@@ -3287,22 +3262,3 @@ static void ath5k_sw_scan_complete(struct ieee80211_hw *hw)
ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
AR5K_LED_ASSOC : AR5K_LED_INIT);
}
-
-/**
- * ath5k_set_coverage_class - Set IEEE 802.11 coverage class
- *
- * @hw: struct ieee80211_hw pointer
- * @coverage_class: IEEE 802.11 coverage class number
- *
- * Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given
- * coverage class. The values are persistent, they are restored after device
- * reset.
- */
-static void ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
-{
- struct ath5k_softc *sc = hw->priv;
-
- mutex_lock(&sc->lock);
- ath5k_hw_set_coverage_class(sc->ah, coverage_class);
- mutex_unlock(&sc->lock);
-}
diff --git a/trunk/drivers/net/wireless/ath/ath5k/base.h b/trunk/drivers/net/wireless/ath/ath5k/base.h
index 9c2fbf230ce7..b72338c9bde7 100644
--- a/trunk/drivers/net/wireless/ath/ath5k/base.h
+++ b/trunk/drivers/net/wireless/ath/ath5k/base.h
@@ -117,6 +117,7 @@ struct ath5k_softc {
struct pci_dev *pdev; /* for dma mapping */
void __iomem *iobase; /* address of the device */
struct mutex lock; /* dev-level lock */
+ struct ieee80211_tx_queue_stats tx_stats[AR5K_NUM_TX_QUEUES];
struct ieee80211_low_level_stats ll_stats;
struct ieee80211_hw *hw; /* IEEE 802.11 common */
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
diff --git a/trunk/drivers/net/wireless/ath/ath5k/led.c b/trunk/drivers/net/wireless/ath/ath5k/led.c
index 67aa52e9bf94..60f547503d75 100644
--- a/trunk/drivers/net/wireless/ath/ath5k/led.c
+++ b/trunk/drivers/net/wireless/ath/ath5k/led.c
@@ -77,8 +77,6 @@ static const struct pci_device_id ath5k_led_devices[] = {
{ ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137a), ATH_LED(3, 1) },
/* HP Compaq C700 (nitrousnrg@gmail.com) */
{ ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) },
- /* LiteOn AR5BXB63 (magooz@salug.it) */
- { ATH_SDEVICE(PCI_VENDOR_ID_ATHEROS, 0x3067), ATH_LED(3, 0) },
/* IBM-specific AR5212 (all others) */
{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) },
/* Dell Vostro A860 (shahar@shahar-or.co.il) */
diff --git a/trunk/drivers/net/wireless/ath/ath5k/pcu.c b/trunk/drivers/net/wireless/ath/ath5k/pcu.c
index aefe84f9c04b..64fc1eb9b6d9 100644
--- a/trunk/drivers/net/wireless/ath/ath5k/pcu.c
+++ b/trunk/drivers/net/wireless/ath/ath5k/pcu.c
@@ -187,8 +187,8 @@ unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
{
ATH5K_TRACE(ah->ah_sc);
- return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah,
- AR5K_TIME_OUT), AR5K_TIME_OUT_ACK));
+ return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
+ AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo);
}
/**
@@ -200,12 +200,12 @@ unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
{
ATH5K_TRACE(ah->ah_sc);
- if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK))
- <= timeout)
+ if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK),
+ ah->ah_turbo) <= timeout)
return -EINVAL;
AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK,
- ath5k_hw_htoclock(ah, timeout));
+ ath5k_hw_htoclock(timeout, ah->ah_turbo));
return 0;
}
@@ -218,8 +218,8 @@ int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
{
ATH5K_TRACE(ah->ah_sc);
- return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah,
- AR5K_TIME_OUT), AR5K_TIME_OUT_CTS));
+ return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
+ AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo);
}
/**
@@ -231,96 +231,16 @@ unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
{
ATH5K_TRACE(ah->ah_sc);
- if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS))
- <= timeout)
+ if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS),
+ ah->ah_turbo) <= timeout)
return -EINVAL;
AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS,
- ath5k_hw_htoclock(ah, timeout));
+ ath5k_hw_htoclock(timeout, ah->ah_turbo));
return 0;
}
-/**
- * ath5k_hw_htoclock - Translate usec to hw clock units
- *
- * @ah: The &struct ath5k_hw
- * @usec: value in microseconds
- */
-unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec)
-{
- return usec * ath5k_hw_get_clockrate(ah);
-}
-
-/**
- * ath5k_hw_clocktoh - Translate hw clock units to usec
- * @clock: value in hw clock units
- */
-unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock)
-{
- return clock / ath5k_hw_get_clockrate(ah);
-}
-
-/**
- * ath5k_hw_get_clockrate - Get the clock rate for current mode
- *
- * @ah: The &struct ath5k_hw
- */
-unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah)
-{
- struct ieee80211_channel *channel = ah->ah_current_channel;
- int clock;
-
- if (channel->hw_value & CHANNEL_5GHZ)
- clock = 40; /* 802.11a */
- else if (channel->hw_value & CHANNEL_CCK)
- clock = 22; /* 802.11b */
- else
- clock = 44; /* 802.11g */
-
- /* Clock rate in turbo modes is twice the normal rate */
- if (channel->hw_value & CHANNEL_TURBO)
- clock *= 2;
-
- return clock;
-}
-
-/**
- * ath5k_hw_get_default_slottime - Get the default slot time for current mode
- *
- * @ah: The &struct ath5k_hw
- */
-unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
-{
- struct ieee80211_channel *channel = ah->ah_current_channel;
-
- if (channel->hw_value & CHANNEL_TURBO)
- return 6; /* both turbo modes */
-
- if (channel->hw_value & CHANNEL_CCK)
- return 20; /* 802.11b */
-
- return 9; /* 802.11 a/g */
-}
-
-/**
- * ath5k_hw_get_default_sifs - Get the default SIFS for current mode
- *
- * @ah: The &struct ath5k_hw
- */
-unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
-{
- struct ieee80211_channel *channel = ah->ah_current_channel;
-
- if (channel->hw_value & CHANNEL_TURBO)
- return 8; /* both turbo modes */
-
- if (channel->hw_value & CHANNEL_5GHZ)
- return 16; /* 802.11a */
-
- return 10; /* 802.11 b/g */
-}
-
/**
* ath5k_hw_set_lladdr - Set station id
*
@@ -1130,24 +1050,3 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
return 0;
}
-/**
- * ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class
- *
- * @ah: The &struct ath5k_hw
- * @coverage_class: IEEE 802.11 coverage class number
- *
- * Sets slot time, ACK timeout and CTS timeout for given coverage class.
- */
-void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
-{
- /* As defined by IEEE 802.11-2007 17.3.8.6 */
- int slot_time = ath5k_hw_get_default_slottime(ah) + 3 * coverage_class;
- int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time;
- int cts_timeout = ack_timeout;
-
- ath5k_hw_set_slot_time(ah, slot_time);
- ath5k_hw_set_ack_timeout(ah, ack_timeout);
- ath5k_hw_set_cts_timeout(ah, cts_timeout);
-
- ah->ah_coverage_class = coverage_class;
-}
diff --git a/trunk/drivers/net/wireless/ath/ath5k/qcu.c b/trunk/drivers/net/wireless/ath/ath5k/qcu.c
index 9122a8556f45..eeebb9aef206 100644
--- a/trunk/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/trunk/drivers/net/wireless/ath/ath5k/qcu.c
@@ -408,13 +408,12 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
break;
case AR5K_TX_QUEUE_CAB:
- /* XXX: use BCN_SENT_GT, if we can figure out how */
AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
- AR5K_QCU_MISC_FRSHED_DBA_GT |
+ AR5K_QCU_MISC_FRSHED_BCN_SENT_GT |
AR5K_QCU_MISC_CBREXP_DIS |
AR5K_QCU_MISC_CBREXP_BCN_DIS);
- ath5k_hw_reg_write(ah, ((tq->tqi_ready_time -
+ ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL -
(AR5K_TUNE_SW_BEACON_RESP -
AR5K_TUNE_DMA_BEACON_RESP) -
AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
@@ -521,16 +520,12 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
*/
unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah)
{
- unsigned int slot_time_clock;
-
ATH5K_TRACE(ah->ah_sc);
-
if (ah->ah_version == AR5K_AR5210)
- slot_time_clock = ath5k_hw_reg_read(ah, AR5K_SLOT_TIME);
+ return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah,
+ AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo);
else
- slot_time_clock = ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT);
-
- return ath5k_hw_clocktoh(ah, slot_time_clock & 0xffff);
+ return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff;
}
/*
@@ -538,17 +533,15 @@ unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah)
*/
int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
{
- u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time);
-
ATH5K_TRACE(ah->ah_sc);
-
- if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX)
+ if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX)
return -EINVAL;
if (ah->ah_version == AR5K_AR5210)
- ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME);
+ ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time,
+ ah->ah_turbo), AR5K_SLOT_TIME);
else
- ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT);
+ ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT);
return 0;
}
diff --git a/trunk/drivers/net/wireless/ath/ath5k/reset.c b/trunk/drivers/net/wireless/ath/ath5k/reset.c
index a35a7db0fc4c..62954fc77869 100644
--- a/trunk/drivers/net/wireless/ath/ath5k/reset.c
+++ b/trunk/drivers/net/wireless/ath/ath5k/reset.c
@@ -60,11 +60,12 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
!(channel->hw_value & CHANNEL_OFDM));
/* Get coefficient
- * ALGO: coef = (5 * clock / carrier_freq) / 2
+ * ALGO: coef = (5 * clock * carrier_freq) / 2)
* we scale coef by shifting clock value by 24 for
* better precision since we use integers */
/* TODO: Half/quarter rate */
- clock = (channel->hw_value & CHANNEL_TURBO) ? 80 : 40;
+ clock = ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO);
+
coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq;
/* Get exponent
@@ -1316,10 +1317,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
/* Restore antenna mode */
ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
- /* Restore slot time and ACK timeouts */
- if (ah->ah_coverage_class > 0)
- ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class);
-
/*
* Configure QCUs/DCUs
*/
@@ -1374,9 +1371,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
* Set clocks to 32KHz operation and use an
* external 32KHz crystal when sleeping if one
* exists */
- if (ah->ah_version == AR5K_AR5212 &&
- ah->ah_op_mode != NL80211_IFTYPE_AP)
- ath5k_hw_set_sleep_clock(ah, true);
+ if (ah->ah_version == AR5K_AR5212)
+ ath5k_hw_set_sleep_clock(ah, true);
/*
* Disable beacons and reset the register
diff --git a/trunk/drivers/net/wireless/ath/ath9k/Makefile b/trunk/drivers/net/wireless/ath/ath9k/Makefile
index 6b50d5eb9ec3..4985b2b1b0a9 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/Makefile
+++ b/trunk/drivers/net/wireless/ath/ath9k/Makefile
@@ -1,6 +1,4 @@
ath9k-y += beacon.o \
- gpio.o \
- init.o \
main.o \
recv.o \
xmit.o \
diff --git a/trunk/drivers/net/wireless/ath/ath9k/ahb.c b/trunk/drivers/net/wireless/ath/ath9k/ahb.c
index ca4994f13151..329e6bc137ab 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/trunk/drivers/net/wireless/ath/ath9k/ahb.c
@@ -27,6 +27,12 @@ static void ath_ahb_read_cachesize(struct ath_common *common, int *csz)
*csz = L1_CACHE_BYTES >> 2;
}
+static void ath_ahb_cleanup(struct ath_common *common)
+{
+ struct ath_softc *sc = (struct ath_softc *)common->priv;
+ iounmap(sc->mem);
+}
+
static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
{
struct ath_softc *sc = (struct ath_softc *)common->priv;
@@ -48,6 +54,8 @@ static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
static struct ath_bus_ops ath_ahb_bus_ops = {
.read_cachesize = ath_ahb_read_cachesize,
+ .cleanup = ath_ahb_cleanup,
+
.eeprom_read = ath_ahb_eeprom_read,
};
@@ -113,19 +121,16 @@ static int ath_ahb_probe(struct platform_device *pdev)
sc->mem = mem;
sc->irq = irq;
- /* Will be cleared in ath9k_start() */
- sc->sc_flags |= SC_OP_INVALID;
-
- ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
+ ret = ath_init_device(AR5416_AR9100_DEVID, sc, 0x0, &ath_ahb_bus_ops);
if (ret) {
- dev_err(&pdev->dev, "request_irq failed\n");
+ dev_err(&pdev->dev, "failed to initialize device\n");
goto err_free_hw;
}
- ret = ath9k_init_device(AR5416_AR9100_DEVID, sc, 0x0, &ath_ahb_bus_ops);
+ ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
if (ret) {
- dev_err(&pdev->dev, "failed to initialize device\n");
- goto err_irq;
+ dev_err(&pdev->dev, "request_irq failed\n");
+ goto err_detach;
}
ah = sc->sc_ah;
@@ -138,8 +143,8 @@ static int ath_ahb_probe(struct platform_device *pdev)
return 0;
- err_irq:
- free_irq(irq, sc);
+ err_detach:
+ ath_detach(sc);
err_free_hw:
ieee80211_free_hw(hw);
platform_set_drvdata(pdev, NULL);
@@ -156,12 +161,8 @@ static int ath_ahb_remove(struct platform_device *pdev)
if (hw) {
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
- void __iomem *mem = sc->mem;
- ath9k_deinit_device(sc);
- free_irq(sc->irq, sc);
- ieee80211_free_hw(sc->hw);
- iounmap(mem);
+ ath_cleanup(sc);
platform_set_drvdata(pdev, NULL);
}
diff --git a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h
index 83c7ea4c007f..1597a42731ed 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -267,7 +267,6 @@ void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
u16 tid, u16 *ssn);
void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
-void ath9k_enable_ps(struct ath_softc *sc);
/********/
/* VIFs */
@@ -342,12 +341,6 @@ int ath_beaconq_config(struct ath_softc *sc);
#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */
#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */
-void ath_ani_calibrate(unsigned long data);
-
-/**********/
-/* BTCOEX */
-/**********/
-
/* Defines the BT AR_BT_COEX_WGHT used */
enum ath_stomp_type {
ATH_BTCOEX_NO_STOMP,
@@ -365,14 +358,9 @@ struct ath_btcoex {
int bt_stomp_type; /* Types of BT stomping */
u32 btcoex_no_stomp; /* in usec */
u32 btcoex_period; /* in usec */
- u32 btscan_no_stomp; /* in usec */
struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
};
-int ath_init_btcoex_timer(struct ath_softc *sc);
-void ath9k_btcoex_timer_resume(struct ath_softc *sc);
-void ath9k_btcoex_timer_pause(struct ath_softc *sc);
-
/********************/
/* LED Control */
/********************/
@@ -397,9 +385,6 @@ struct ath_led {
bool registered;
};
-void ath_init_leds(struct ath_softc *sc);
-void ath_deinit_leds(struct ath_softc *sc);
-
/********************/
/* Main driver core */
/********************/
@@ -418,29 +403,26 @@ void ath_deinit_leds(struct ath_softc *sc);
#define ATH_TXPOWER_MAX 100 /* .5 dBm units */
#define ATH_RATE_DUMMY_MARKER 0
-#define SC_OP_INVALID BIT(0)
-#define SC_OP_BEACONS BIT(1)
-#define SC_OP_RXAGGR BIT(2)
-#define SC_OP_TXAGGR BIT(3)
-#define SC_OP_FULL_RESET BIT(4)
-#define SC_OP_PREAMBLE_SHORT BIT(5)
-#define SC_OP_PROTECT_ENABLE BIT(6)
-#define SC_OP_RXFLUSH BIT(7)
-#define SC_OP_LED_ASSOCIATED BIT(8)
-#define SC_OP_LED_ON BIT(9)
-#define SC_OP_SCANNING BIT(10)
-#define SC_OP_TSF_RESET BIT(11)
-#define SC_OP_BT_PRIORITY_DETECTED BIT(12)
-#define SC_OP_BT_SCAN BIT(13)
-
-/* Powersave flags */
-#define PS_WAIT_FOR_BEACON BIT(0)
-#define PS_WAIT_FOR_CAB BIT(1)
-#define PS_WAIT_FOR_PSPOLL_DATA BIT(2)
-#define PS_WAIT_FOR_TX_ACK BIT(3)
-#define PS_BEACON_SYNC BIT(4)
-#define PS_NULLFUNC_COMPLETED BIT(5)
-#define PS_ENABLED BIT(6)
+#define SC_OP_INVALID BIT(0)
+#define SC_OP_BEACONS BIT(1)
+#define SC_OP_RXAGGR BIT(2)
+#define SC_OP_TXAGGR BIT(3)
+#define SC_OP_FULL_RESET BIT(4)
+#define SC_OP_PREAMBLE_SHORT BIT(5)
+#define SC_OP_PROTECT_ENABLE BIT(6)
+#define SC_OP_RXFLUSH BIT(7)
+#define SC_OP_LED_ASSOCIATED BIT(8)
+#define SC_OP_WAIT_FOR_BEACON BIT(12)
+#define SC_OP_LED_ON BIT(13)
+#define SC_OP_SCANNING BIT(14)
+#define SC_OP_TSF_RESET BIT(15)
+#define SC_OP_WAIT_FOR_CAB BIT(16)
+#define SC_OP_WAIT_FOR_PSPOLL_DATA BIT(17)
+#define SC_OP_WAIT_FOR_TX_ACK BIT(18)
+#define SC_OP_BEACON_SYNC BIT(19)
+#define SC_OP_BT_PRIORITY_DETECTED BIT(21)
+#define SC_OP_NULLFUNC_COMPLETED BIT(22)
+#define SC_OP_PS_ENABLED BIT(23)
struct ath_wiphy;
struct ath_rate_table;
@@ -471,17 +453,16 @@ struct ath_softc {
int irq;
spinlock_t sc_resetlock;
spinlock_t sc_serial_rw;
+ spinlock_t ani_lock;
spinlock_t sc_pm_lock;
struct mutex mutex;
u32 intrstatus;
u32 sc_flags; /* SC_OP_* */
- u16 ps_flags; /* PS_* */
u16 curtxpow;
u8 nbcnvifs;
u16 nvifs;
bool ps_enabled;
- bool ps_idle;
unsigned long ps_usecount;
enum ath9k_int imask;
@@ -528,7 +509,6 @@ struct ath_wiphy {
int chan_is_ht;
};
-void ath9k_tasklet(unsigned long data);
int ath_reset(struct ath_softc *sc, bool retry_tx);
int ath_get_hal_qnum(u16 queue, struct ath_softc *sc);
int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
@@ -539,16 +519,21 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
common->bus_ops->read_cachesize(common, csz);
}
+static inline void ath_bus_cleanup(struct ath_common *common)
+{
+ common->bus_ops->cleanup(common);
+}
+
extern struct ieee80211_ops ath9k_ops;
-extern int modparam_nohwcrypt;
irqreturn_t ath_isr(int irq, void *dev);
-int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
+void ath_cleanup(struct ath_softc *sc);
+int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
const struct ath_bus_ops *bus_ops);
-void ath9k_deinit_device(struct ath_softc *sc);
+void ath_detach(struct ath_softc *sc);
const char *ath_mac_bb_name(u32 mac_bb_version);
const char *ath_rf_name(u16 rf_version);
-void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
+void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
struct ath9k_channel *ichan);
void ath_update_chainmask(struct ath_softc *sc, int is_ht);
@@ -557,7 +542,6 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw);
void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
-bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);
#ifdef CONFIG_PCI
int ath_pci_init(void);
@@ -599,8 +583,4 @@ void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue);
void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue);
int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype);
-
-void ath_start_rfkill_poll(struct ath_softc *sc);
-extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw);
-
#endif /* ATH9K_H */
diff --git a/trunk/drivers/net/wireless/ath/ath9k/beacon.c b/trunk/drivers/net/wireless/ath/ath9k/beacon.c
index b4a31a43a62c..1660ef17aaf5 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/trunk/drivers/net/wireless/ath/ath9k/beacon.c
@@ -62,7 +62,7 @@ int ath_beaconq_config(struct ath_softc *sc)
* Beacons are always sent out at the lowest rate, and are not retried.
*/
static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
- struct ath_buf *bf, int rateidx)
+ struct ath_buf *bf)
{
struct sk_buff *skb = bf->bf_mpdu;
struct ath_hw *ah = sc->sc_ah;
@@ -96,9 +96,9 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
ds->ds_data = bf->bf_buf_addr;
sband = &sc->sbands[common->hw->conf.channel->band];
- rate = sband->bitrates[rateidx].hw_value;
+ rate = sband->bitrates[0].hw_value;
if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
- rate |= sband->bitrates[rateidx].hw_value_short;
+ rate |= sband->bitrates[0].hw_value_short;
ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN,
ATH9K_PKT_TYPE_BEACON,
@@ -206,7 +206,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
}
}
- ath_beacon_setup(sc, avp, bf, info->control.rates[0].idx);
+ ath_beacon_setup(sc, avp, bf);
while (skb) {
ath_tx_cabq(hw, skb);
@@ -237,7 +237,7 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc,
bf = avp->av_bcbuf;
skb = bf->bf_mpdu;
- ath_beacon_setup(sc, avp, bf, 0);
+ ath_beacon_setup(sc, avp, bf);
/* NB: caller is known to have already stopped tx dma */
ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
@@ -480,8 +480,7 @@ void ath_beacon_tasklet(unsigned long data)
sc->beacon.updateslot = COMMIT; /* commit next beacon */
sc->beacon.slotupdate = slot;
} else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) {
- ah->slottime = sc->beacon.slottime;
- ath9k_hw_init_global_settings(ah);
+ ath9k_hw_setslottime(sc->sc_ah, sc->beacon.slottime);
sc->beacon.updateslot = OK;
}
if (bfaddr != 0) {
@@ -526,13 +525,16 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
{
u32 nexttbtt, intval;
+ /* Configure the timers only when the TSF has to be reset */
+
+ if (!(sc->sc_flags & SC_OP_TSF_RESET))
+ return;
+
/* NB: the beacon interval is kept internally in TU's */
intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
intval /= ATH_BCBUF; /* for staggered beacons */
nexttbtt = intval;
-
- if (sc->sc_flags & SC_OP_TSF_RESET)
- intval |= ATH9K_BEACON_RESET_TSF;
+ intval |= ATH9K_BEACON_RESET_TSF;
/*
* In AP mode we enable the beacon timers and SWBA interrupts to
@@ -574,13 +576,6 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
u64 tsf;
int num_beacons, offset, dtim_dec_count, cfp_dec_count;
- /* No need to configure beacon if we are not associated */
- if (!common->curaid) {
- ath_print(common, ATH_DBG_BEACON,
- "STA is not yet associated..skipping beacon config\n");
- return;
- }
-
memset(&bs, 0, sizeof(bs));
intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
@@ -743,6 +738,7 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
enum nl80211_iftype iftype;
/* Setup the beacon configuration parameters */
+
if (vif) {
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
diff --git a/trunk/drivers/net/wireless/ath/ath9k/btcoex.h b/trunk/drivers/net/wireless/ath/ath9k/btcoex.h
index 1ee5a15ccbb1..1ba31a73317c 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/btcoex.h
+++ b/trunk/drivers/net/wireless/ath/ath9k/btcoex.h
@@ -25,12 +25,10 @@
#define ATH_BTCOEX_DEF_BT_PERIOD 45
#define ATH_BTCOEX_DEF_DUTY_CYCLE 55
-#define ATH_BTCOEX_BTSCAN_DUTY_CYCLE 90
#define ATH_BTCOEX_BMISS_THRESH 50
#define ATH_BT_PRIORITY_TIME_THRESHOLD 1000 /* ms */
#define ATH_BT_CNT_THRESHOLD 3
-#define ATH_BT_CNT_SCAN_THRESHOLD 15
enum ath_btcoex_scheme {
ATH_BTCOEX_CFG_NONE,
diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.c b/trunk/drivers/net/wireless/ath/ath9k/debug.c
index 42d2a506845a..b66f72dbf7b9 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/debug.c
+++ b/trunk/drivers/net/wireless/ath/ath9k/debug.c
@@ -75,24 +75,17 @@ static const struct file_operations fops_debug = {
#endif
-#define DMA_BUF_LEN 1024
-
static ssize_t read_file_dma(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
struct ath_hw *ah = sc->sc_ah;
- char *buf;
- int retval;
+ char buf[1024];
unsigned int len = 0;
u32 val[ATH9K_NUM_DMA_DEBUG_REGS];
int i, qcuOffset = 0, dcuOffset = 0;
u32 *qcuBase = &val[0], *dcuBase = &val[4];
- buf = kmalloc(DMA_BUF_LEN, GFP_KERNEL);
- if (!buf)
- return 0;
-
ath9k_ps_wakeup(sc);
REG_WRITE_D(ah, AR_MACMISC,
@@ -100,20 +93,20 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
(AR_MACMISC_MISC_OBS_BUS_1 <<
AR_MACMISC_MISC_OBS_BUS_MSB_S)));
- len += snprintf(buf + len, DMA_BUF_LEN - len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"Raw DMA Debug values:\n");
for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
if (i % 4 == 0)
- len += snprintf(buf + len, DMA_BUF_LEN - len, "\n");
+ len += snprintf(buf + len, sizeof(buf) - len, "\n");
val[i] = REG_READ_D(ah, AR_DMADBG_0 + (i * sizeof(u32)));
- len += snprintf(buf + len, DMA_BUF_LEN - len, "%d: %08x ",
+ len += snprintf(buf + len, sizeof(buf) - len, "%d: %08x ",
i, val[i]);
}
- len += snprintf(buf + len, DMA_BUF_LEN - len, "\n\n");
- len += snprintf(buf + len, DMA_BUF_LEN - len,
+ len += snprintf(buf + len, sizeof(buf) - len, "\n\n");
+ len += snprintf(buf + len, sizeof(buf) - len,
"Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) {
@@ -127,7 +120,7 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
dcuBase++;
}
- len += snprintf(buf + len, DMA_BUF_LEN - len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"%2d %2x %1x %2x %2x\n",
i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
(*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
@@ -135,37 +128,35 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
(*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
}
- len += snprintf(buf + len, DMA_BUF_LEN - len, "\n");
+ len += snprintf(buf + len, sizeof(buf) - len, "\n");
- len += snprintf(buf + len, DMA_BUF_LEN - len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"qcu_stitch state: %2x qcu_fetch state: %2x\n",
(val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
- len += snprintf(buf + len, DMA_BUF_LEN - len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"qcu_complete state: %2x dcu_complete state: %2x\n",
(val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
- len += snprintf(buf + len, DMA_BUF_LEN - len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"dcu_arb state: %2x dcu_fp state: %2x\n",
(val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
- len += snprintf(buf + len, DMA_BUF_LEN - len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"chan_idle_dur: %3d chan_idle_dur_valid: %1d\n",
(val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
- len += snprintf(buf + len, DMA_BUF_LEN - len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"txfifo_valid_0: %1d txfifo_valid_1: %1d\n",
(val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
- len += snprintf(buf + len, DMA_BUF_LEN - len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n",
(val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
- len += snprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x \n",
+ len += snprintf(buf + len, sizeof(buf) - len, "pcu observe: 0x%x \n",
REG_READ_D(ah, AR_OBS_BUS_1));
- len += snprintf(buf + len, DMA_BUF_LEN - len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR_CR: 0x%x \n", REG_READ_D(ah, AR_CR));
ath9k_ps_restore(sc);
- retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
- kfree(buf);
- return retval;
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static const struct file_operations fops_dma = {
@@ -298,49 +289,23 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
if (sc->cur_rate_table == NULL)
return 0;
- max = 80 + sc->cur_rate_table->rate_cnt * 1024;
+ max = 80 + sc->cur_rate_table->rate_cnt * 64;
buf = kmalloc(max + 1, GFP_KERNEL);
if (buf == NULL)
return 0;
buf[max] = 0;
- len += sprintf(buf, "%6s %6s %6s "
- "%10s %10s %10s %10s\n",
- "HT", "MCS", "Rate",
- "Success", "Retries", "XRetries", "PER");
+ len += sprintf(buf, "%5s %15s %8s %9s %3s\n\n", "Rate", "Success",
+ "Retries", "XRetries", "PER");
for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) {
u32 ratekbps = sc->cur_rate_table->info[i].ratekbps;
struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i];
- char mcs[5];
- char htmode[5];
- int used_mcs = 0, used_htmode = 0;
-
- if (WLAN_RC_PHY_HT(sc->cur_rate_table->info[i].phy)) {
- used_mcs = snprintf(mcs, 5, "%d",
- sc->cur_rate_table->info[i].ratecode);
-
- if (WLAN_RC_PHY_40(sc->cur_rate_table->info[i].phy))
- used_htmode = snprintf(htmode, 5, "HT40");
- else if (WLAN_RC_PHY_20(sc->cur_rate_table->info[i].phy))
- used_htmode = snprintf(htmode, 5, "HT20");
- else
- used_htmode = snprintf(htmode, 5, "????");
- }
-
- mcs[used_mcs] = '\0';
- htmode[used_htmode] = '\0';
len += snprintf(buf + len, max - len,
- "%6s %6s %3u.%d: "
- "%10u %10u %10u %10u\n",
- htmode,
- mcs,
- ratekbps / 1000,
- (ratekbps % 1000) / 100,
- stats->success,
- stats->retries,
- stats->xretries,
+ "%3u.%d: %8u %8u %8u %8u\n", ratekbps / 1000,
+ (ratekbps % 1000) / 100, stats->success,
+ stats->retries, stats->xretries,
stats->per);
}
@@ -589,116 +554,6 @@ static const struct file_operations fops_xmit = {
.owner = THIS_MODULE
};
-static ssize_t read_file_recv(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
-#define PHY_ERR(s, p) \
- len += snprintf(buf + len, size - len, "%18s : %10u\n", s, \
- sc->debug.stats.rxstats.phy_err_stats[p]);
-
- struct ath_softc *sc = file->private_data;
- char *buf;
- unsigned int len = 0, size = 1152;
- ssize_t retval = 0;
-
- buf = kzalloc(size, GFP_KERNEL);
- if (buf == NULL)
- return 0;
-
- len += snprintf(buf + len, size - len,
- "%18s : %10u\n", "CRC ERR",
- sc->debug.stats.rxstats.crc_err);
- len += snprintf(buf + len, size - len,
- "%18s : %10u\n", "DECRYPT CRC ERR",
- sc->debug.stats.rxstats.decrypt_crc_err);
- len += snprintf(buf + len, size - len,
- "%18s : %10u\n", "PHY ERR",
- sc->debug.stats.rxstats.phy_err);
- len += snprintf(buf + len, size - len,
- "%18s : %10u\n", "MIC ERR",
- sc->debug.stats.rxstats.mic_err);
- len += snprintf(buf + len, size - len,
- "%18s : %10u\n", "PRE-DELIM CRC ERR",
- sc->debug.stats.rxstats.pre_delim_crc_err);
- len += snprintf(buf + len, size - len,
- "%18s : %10u\n", "POST-DELIM CRC ERR",
- sc->debug.stats.rxstats.post_delim_crc_err);
- len += snprintf(buf + len, size - len,
- "%18s : %10u\n", "DECRYPT BUSY ERR",
- sc->debug.stats.rxstats.decrypt_busy_err);
-
- PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN);
- PHY_ERR("TIMING", ATH9K_PHYERR_TIMING);
- PHY_ERR("PARITY", ATH9K_PHYERR_PARITY);
- PHY_ERR("RATE", ATH9K_PHYERR_RATE);
- PHY_ERR("LENGTH", ATH9K_PHYERR_LENGTH);
- PHY_ERR("RADAR", ATH9K_PHYERR_RADAR);
- PHY_ERR("SERVICE", ATH9K_PHYERR_SERVICE);
- PHY_ERR("TOR", ATH9K_PHYERR_TOR);
- PHY_ERR("OFDM-TIMING", ATH9K_PHYERR_OFDM_TIMING);
- PHY_ERR("OFDM-SIGNAL-PARITY", ATH9K_PHYERR_OFDM_SIGNAL_PARITY);
- PHY_ERR("OFDM-RATE", ATH9K_PHYERR_OFDM_RATE_ILLEGAL);
- PHY_ERR("OFDM-LENGTH", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL);
- PHY_ERR("OFDM-POWER-DROP", ATH9K_PHYERR_OFDM_POWER_DROP);
- PHY_ERR("OFDM-SERVICE", ATH9K_PHYERR_OFDM_SERVICE);
- PHY_ERR("OFDM-RESTART", ATH9K_PHYERR_OFDM_RESTART);
- PHY_ERR("FALSE-RADAR-EXT", ATH9K_PHYERR_FALSE_RADAR_EXT);
- PHY_ERR("CCK-TIMING", ATH9K_PHYERR_CCK_TIMING);
- PHY_ERR("CCK-HEADER-CRC", ATH9K_PHYERR_CCK_HEADER_CRC);
- PHY_ERR("CCK-RATE", ATH9K_PHYERR_CCK_RATE_ILLEGAL);
- PHY_ERR("CCK-SERVICE", ATH9K_PHYERR_CCK_SERVICE);
- PHY_ERR("CCK-RESTART", ATH9K_PHYERR_CCK_RESTART);
- PHY_ERR("CCK-LENGTH", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL);
- PHY_ERR("CCK-POWER-DROP", ATH9K_PHYERR_CCK_POWER_DROP);
- PHY_ERR("HT-CRC", ATH9K_PHYERR_HT_CRC_ERROR);
- PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
- PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL);
-
- retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
- kfree(buf);
-
- return retval;
-
-#undef PHY_ERR
-}
-
-void ath_debug_stat_rx(struct ath_softc *sc, struct ath_buf *bf)
-{
-#define RX_STAT_INC(c) sc->debug.stats.rxstats.c++
-#define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++
-
- struct ath_desc *ds = bf->bf_desc;
- u32 phyerr;
-
- if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC)
- RX_STAT_INC(crc_err);
- if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT)
- RX_STAT_INC(decrypt_crc_err);
- if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC)
- RX_STAT_INC(mic_err);
- if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_PRE)
- RX_STAT_INC(pre_delim_crc_err);
- if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_POST)
- RX_STAT_INC(post_delim_crc_err);
- if (ds->ds_rxstat.rs_status & ATH9K_RX_DECRYPT_BUSY)
- RX_STAT_INC(decrypt_busy_err);
-
- if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) {
- RX_STAT_INC(phy_err);
- phyerr = ds->ds_rxstat.rs_phyerr & 0x24;
- RX_PHY_ERR_INC(phyerr);
- }
-
-#undef RX_STAT_INC
-#undef RX_PHY_ERR_INC
-}
-
-static const struct file_operations fops_recv = {
- .read = read_file_recv,
- .open = ath9k_debugfs_open,
- .owner = THIS_MODULE
-};
-
int ath9k_init_debug(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
@@ -751,13 +606,6 @@ int ath9k_init_debug(struct ath_hw *ah)
if (!sc->debug.debugfs_xmit)
goto err;
- sc->debug.debugfs_recv = debugfs_create_file("recv",
- S_IRUSR,
- sc->debug.debugfs_phy,
- sc, &fops_recv);
- if (!sc->debug.debugfs_recv)
- goto err;
-
return 0;
err:
ath9k_exit_debug(ah);
@@ -769,7 +617,6 @@ void ath9k_exit_debug(struct ath_hw *ah)
struct ath_common *common = ath9k_hw_common(ah);
struct ath_softc *sc = (struct ath_softc *) common->priv;
- debugfs_remove(sc->debug.debugfs_recv);
debugfs_remove(sc->debug.debugfs_xmit);
debugfs_remove(sc->debug.debugfs_wiphy);
debugfs_remove(sc->debug.debugfs_rcstat);
diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.h b/trunk/drivers/net/wireless/ath/ath9k/debug.h
index 86780e68b31e..536663e3ee11 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/debug.h
+++ b/trunk/drivers/net/wireless/ath/ath9k/debug.h
@@ -116,35 +116,10 @@ struct ath_tx_stats {
u32 delim_underrun;
};
-/**
- * struct ath_rx_stats - RX Statistics
- * @crc_err: No. of frames with incorrect CRC value
- * @decrypt_crc_err: No. of frames whose CRC check failed after
- decryption process completed
- * @phy_err: No. of frames whose reception failed because the PHY
- encountered an error
- * @mic_err: No. of frames with incorrect TKIP MIC verification failure
- * @pre_delim_crc_err: Pre-Frame delimiter CRC error detections
- * @post_delim_crc_err: Post-Frame delimiter CRC error detections
- * @decrypt_busy_err: Decryption interruptions counter
- * @phy_err_stats: Individual PHY error statistics
- */
-struct ath_rx_stats {
- u32 crc_err;
- u32 decrypt_crc_err;
- u32 phy_err;
- u32 mic_err;
- u32 pre_delim_crc_err;
- u32 post_delim_crc_err;
- u32 decrypt_busy_err;
- u32 phy_err_stats[ATH9K_PHYERR_MAX];
-};
-
struct ath_stats {
struct ath_interrupt_stats istats;
struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
- struct ath_rx_stats rxstats;
};
struct ath9k_debug {
@@ -155,7 +130,6 @@ struct ath9k_debug {
struct dentry *debugfs_rcstat;
struct dentry *debugfs_wiphy;
struct dentry *debugfs_xmit;
- struct dentry *debugfs_recv;
struct ath_stats stats;
};
@@ -168,7 +142,6 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
void ath_debug_stat_rc(struct ath_softc *sc, int final_rate);
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf);
-void ath_debug_stat_rx(struct ath_softc *sc, struct ath_buf *bf);
void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries, u8 per);
@@ -208,11 +181,6 @@ static inline void ath_debug_stat_tx(struct ath_softc *sc,
{
}
-static inline void ath_debug_stat_rx(struct ath_softc *sc,
- struct ath_buf *bf)
-{
-}
-
static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries, u8 per)
{
diff --git a/trunk/drivers/net/wireless/ath/ath9k/gpio.c b/trunk/drivers/net/wireless/ath/ath9k/gpio.c
deleted file mode 100644
index deab8beb0680..000000000000
--- a/trunk/drivers/net/wireless/ath/ath9k/gpio.c
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "ath9k.h"
-
-/********************************/
-/* LED functions */
-/********************************/
-
-static void ath_led_blink_work(struct work_struct *work)
-{
- struct ath_softc *sc = container_of(work, struct ath_softc,
- ath_led_blink_work.work);
-
- if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED))
- return;
-
- if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
- (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
- else
- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin,
- (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0);
-
- ieee80211_queue_delayed_work(sc->hw,
- &sc->ath_led_blink_work,
- (sc->sc_flags & SC_OP_LED_ON) ?
- msecs_to_jiffies(sc->led_off_duration) :
- msecs_to_jiffies(sc->led_on_duration));
-
- sc->led_on_duration = sc->led_on_cnt ?
- max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) :
- ATH_LED_ON_DURATION_IDLE;
- sc->led_off_duration = sc->led_off_cnt ?
- max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) :
- ATH_LED_OFF_DURATION_IDLE;
- sc->led_on_cnt = sc->led_off_cnt = 0;
- if (sc->sc_flags & SC_OP_LED_ON)
- sc->sc_flags &= ~SC_OP_LED_ON;
- else
- sc->sc_flags |= SC_OP_LED_ON;
-}
-
-static void ath_led_brightness(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
- struct ath_softc *sc = led->sc;
-
- switch (brightness) {
- case LED_OFF:
- if (led->led_type == ATH_LED_ASSOC ||
- led->led_type == ATH_LED_RADIO) {
- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin,
- (led->led_type == ATH_LED_RADIO));
- sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
- if (led->led_type == ATH_LED_RADIO)
- sc->sc_flags &= ~SC_OP_LED_ON;
- } else {
- sc->led_off_cnt++;
- }
- break;
- case LED_FULL:
- if (led->led_type == ATH_LED_ASSOC) {
- sc->sc_flags |= SC_OP_LED_ASSOCIATED;
- ieee80211_queue_delayed_work(sc->hw,
- &sc->ath_led_blink_work, 0);
- } else if (led->led_type == ATH_LED_RADIO) {
- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
- sc->sc_flags |= SC_OP_LED_ON;
- } else {
- sc->led_on_cnt++;
- }
- break;
- default:
- break;
- }
-}
-
-static int ath_register_led(struct ath_softc *sc, struct ath_led *led,
- char *trigger)
-{
- int ret;
-
- led->sc = sc;
- led->led_cdev.name = led->name;
- led->led_cdev.default_trigger = trigger;
- led->led_cdev.brightness_set = ath_led_brightness;
-
- ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev);
- if (ret)
- ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
- "Failed to register led:%s", led->name);
- else
- led->registered = 1;
- return ret;
-}
-
-static void ath_unregister_led(struct ath_led *led)
-{
- if (led->registered) {
- led_classdev_unregister(&led->led_cdev);
- led->registered = 0;
- }
-}
-
-void ath_deinit_leds(struct ath_softc *sc)
-{
- ath_unregister_led(&sc->assoc_led);
- sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
- ath_unregister_led(&sc->tx_led);
- ath_unregister_led(&sc->rx_led);
- ath_unregister_led(&sc->radio_led);
- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
-}
-
-void ath_init_leds(struct ath_softc *sc)
-{
- char *trigger;
- int ret;
-
- if (AR_SREV_9287(sc->sc_ah))
- sc->sc_ah->led_pin = ATH_LED_PIN_9287;
- else
- sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
-
- /* Configure gpio 1 for output */
- ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin,
- AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
- /* LED off, active low */
- 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);
-
- trigger = ieee80211_get_radio_led_name(sc->hw);
- snprintf(sc->radio_led.name, sizeof(sc->radio_led.name),
- "ath9k-%s::radio", wiphy_name(sc->hw->wiphy));
- ret = ath_register_led(sc, &sc->radio_led, trigger);
- sc->radio_led.led_type = ATH_LED_RADIO;
- if (ret)
- goto fail;
-
- trigger = ieee80211_get_assoc_led_name(sc->hw);
- snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name),
- "ath9k-%s::assoc", wiphy_name(sc->hw->wiphy));
- ret = ath_register_led(sc, &sc->assoc_led, trigger);
- sc->assoc_led.led_type = ATH_LED_ASSOC;
- if (ret)
- goto fail;
-
- trigger = ieee80211_get_tx_led_name(sc->hw);
- snprintf(sc->tx_led.name, sizeof(sc->tx_led.name),
- "ath9k-%s::tx", wiphy_name(sc->hw->wiphy));
- ret = ath_register_led(sc, &sc->tx_led, trigger);
- sc->tx_led.led_type = ATH_LED_TX;
- if (ret)
- goto fail;
-
- trigger = ieee80211_get_rx_led_name(sc->hw);
- snprintf(sc->rx_led.name, sizeof(sc->rx_led.name),
- "ath9k-%s::rx", wiphy_name(sc->hw->wiphy));
- ret = ath_register_led(sc, &sc->rx_led, trigger);
- sc->rx_led.led_type = ATH_LED_RX;
- if (ret)
- goto fail;
-
- return;
-
-fail:
- cancel_delayed_work_sync(&sc->ath_led_blink_work);
- ath_deinit_leds(sc);
-}
-
-/*******************/
-/* Rfkill */
-/*******************/
-
-static bool ath_is_rfkill_set(struct ath_softc *sc)
-{
- struct ath_hw *ah = sc->sc_ah;
-
- return ath9k_hw_gpio_get(ah, ah->rfkill_gpio) ==
- ah->rfkill_polarity;
-}
-
-void ath9k_rfkill_poll_state(struct ieee80211_hw *hw)
-{
- struct ath_wiphy *aphy = hw->priv;
- struct ath_softc *sc = aphy->sc;
- bool blocked = !!ath_is_rfkill_set(sc);
-
- wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
-}
-
-void ath_start_rfkill_poll(struct ath_softc *sc)
-{
- struct ath_hw *ah = sc->sc_ah;
-
- if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
- wiphy_rfkill_start_polling(sc->hw->wiphy);
-}
-
-/******************/
-/* BTCOEX */
-/******************/
-
-/*
- * Detects if there is any priority bt traffic
- */
-static void ath_detect_bt_priority(struct ath_softc *sc)
-{
- struct ath_btcoex *btcoex = &sc->btcoex;
- struct ath_hw *ah = sc->sc_ah;
-
- if (ath9k_hw_gpio_get(sc->sc_ah, ah->btcoex_hw.btpriority_gpio))
- btcoex->bt_priority_cnt++;
-
- if (time_after(jiffies, btcoex->bt_priority_time +
- msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
- sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN);
- /* Detect if colocated bt started scanning */
- if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) {
- ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX,
- "BT scan detected");
- sc->sc_flags |= (SC_OP_BT_SCAN |
- SC_OP_BT_PRIORITY_DETECTED);
- } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
- ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX,
- "BT priority traffic detected");
- sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED;
- }
-
- btcoex->bt_priority_cnt = 0;
- btcoex->bt_priority_time = jiffies;
- }
-}
-
-/*
- * Configures appropriate weight based on stomp type.
- */
-static void ath9k_btcoex_bt_stomp(struct ath_softc *sc,
- enum ath_stomp_type stomp_type)
-{
- struct ath_hw *ah = sc->sc_ah;
-
- switch (stomp_type) {
- case ATH_BTCOEX_STOMP_ALL:
- ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
- AR_STOMP_ALL_WLAN_WGHT);
- break;
- case ATH_BTCOEX_STOMP_LOW:
- ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
- AR_STOMP_LOW_WLAN_WGHT);
- break;
- case ATH_BTCOEX_STOMP_NONE:
- ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
- AR_STOMP_NONE_WLAN_WGHT);
- break;
- default:
- ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
- "Invalid Stomptype\n");
- break;
- }
-
- ath9k_hw_btcoex_enable(ah);
-}
-
-static void ath9k_gen_timer_start(struct ath_hw *ah,
- struct ath_gen_timer *timer,
- u32 timer_next,
- u32 timer_period)
-{
- struct ath_common *common = ath9k_hw_common(ah);
- struct ath_softc *sc = (struct ath_softc *) common->priv;
-
- ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period);
-
- if ((sc->imask & ATH9K_INT_GENTIMER) == 0) {
- ath9k_hw_set_interrupts(ah, 0);
- sc->imask |= ATH9K_INT_GENTIMER;
- ath9k_hw_set_interrupts(ah, sc->imask);
- }
-}
-
-static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
-{
- struct ath_common *common = ath9k_hw_common(ah);
- struct ath_softc *sc = (struct ath_softc *) common->priv;
- struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
-
- ath9k_hw_gen_timer_stop(ah, timer);
-
- /* if no timer is enabled, turn off interrupt mask */
- if (timer_table->timer_mask.val == 0) {
- ath9k_hw_set_interrupts(ah, 0);
- sc->imask &= ~ATH9K_INT_GENTIMER;
- ath9k_hw_set_interrupts(ah, sc->imask);
- }
-}
-
-/*
- * This is the master bt coex timer which runs for every
- * 45ms, bt traffic will be given priority during 55% of this
- * period while wlan gets remaining 45%
- */
-static void ath_btcoex_period_timer(unsigned long data)
-{
- struct ath_softc *sc = (struct ath_softc *) data;
- struct ath_hw *ah = sc->sc_ah;
- struct ath_btcoex *btcoex = &sc->btcoex;
- u32 timer_period;
- bool is_btscan;
-
- ath_detect_bt_priority(sc);
-
- is_btscan = sc->sc_flags & SC_OP_BT_SCAN;
-
- spin_lock_bh(&btcoex->btcoex_lock);
-
- ath9k_btcoex_bt_stomp(sc, is_btscan ? ATH_BTCOEX_STOMP_ALL :
- btcoex->bt_stomp_type);
-
- spin_unlock_bh(&btcoex->btcoex_lock);
-
- if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) {
- if (btcoex->hw_timer_enabled)
- ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
-
- timer_period = is_btscan ? btcoex->btscan_no_stomp :
- btcoex->btcoex_no_stomp;
- ath9k_gen_timer_start(ah,
- btcoex->no_stomp_timer,
- (ath9k_hw_gettsf32(ah) +
- timer_period), timer_period * 10);
- btcoex->hw_timer_enabled = true;
- }
-
- mod_timer(&btcoex->period_timer, jiffies +
- msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD));
-}
-
-/*
- * Generic tsf based hw timer which configures weight
- * registers to time slice between wlan and bt traffic
- */
-static void ath_btcoex_no_stomp_timer(void *arg)
-{
- struct ath_softc *sc = (struct ath_softc *)arg;
- struct ath_hw *ah = sc->sc_ah;
- struct ath_btcoex *btcoex = &sc->btcoex;
- bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN;
-
- ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
- "no stomp timer running \n");
-
- spin_lock_bh(&btcoex->btcoex_lock);
-
- if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan)
- ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE);
- else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
- ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW);
-
- spin_unlock_bh(&btcoex->btcoex_lock);
-}
-
-int ath_init_btcoex_timer(struct ath_softc *sc)
-{
- struct ath_btcoex *btcoex = &sc->btcoex;
-
- btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000;
- btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
- btcoex->btcoex_period / 100;
- btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) *
- btcoex->btcoex_period / 100;
-
- setup_timer(&btcoex->period_timer, ath_btcoex_period_timer,
- (unsigned long) sc);
-
- spin_lock_init(&btcoex->btcoex_lock);
-
- btcoex->no_stomp_timer = ath_gen_timer_alloc(sc->sc_ah,
- ath_btcoex_no_stomp_timer,
- ath_btcoex_no_stomp_timer,
- (void *) sc, AR_FIRST_NDP_TIMER);
-
- if (!btcoex->no_stomp_timer)
- return -ENOMEM;
-
- return 0;
-}
-
-/*
- * (Re)start btcoex timers
- */
-void ath9k_btcoex_timer_resume(struct ath_softc *sc)
-{
- struct ath_btcoex *btcoex = &sc->btcoex;
- struct ath_hw *ah = sc->sc_ah;
-
- ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
- "Starting btcoex timers");
-
- /* make sure duty cycle timer is also stopped when resuming */
- if (btcoex->hw_timer_enabled)
- ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
-
- btcoex->bt_priority_cnt = 0;
- btcoex->bt_priority_time = jiffies;
- sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN);
-
- mod_timer(&btcoex->period_timer, jiffies);
-}
-
-
-/*
- * Pause btcoex timer and bt duty cycle timer
- */
-void ath9k_btcoex_timer_pause(struct ath_softc *sc)
-{
- struct ath_btcoex *btcoex = &sc->btcoex;
- struct ath_hw *ah = sc->sc_ah;
-
- del_timer_sync(&btcoex->period_timer);
-
- if (btcoex->hw_timer_enabled)
- ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
-
- btcoex->hw_timer_enabled = false;
-}
diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.c b/trunk/drivers/net/wireless/ath/ath9k/hw.c
index f00f5c744f48..ae371448b5a0 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/hw.c
+++ b/trunk/drivers/net/wireless/ath/ath9k/hw.c
@@ -52,6 +52,28 @@ module_exit(ath9k_exit);
/* Helper Functions */
/********************/
+static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks)
+{
+ struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
+
+ if (!ah->curchan) /* should really check for CCK instead */
+ return clks / ATH9K_CLOCK_RATE_CCK;
+ if (conf->channel->band == IEEE80211_BAND_2GHZ)
+ return clks / ATH9K_CLOCK_RATE_2GHZ_OFDM;
+
+ return clks / ATH9K_CLOCK_RATE_5GHZ_OFDM;
+}
+
+static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks)
+{
+ struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
+
+ if (conf_is_ht40(conf))
+ return ath9k_hw_mac_usec(ah, clks) / 2;
+ else
+ return ath9k_hw_mac_usec(ah, clks);
+}
+
static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs)
{
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
@@ -321,6 +343,30 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah)
return true;
}
+static const char *ath9k_hw_devname(u16 devid)
+{
+ switch (devid) {
+ case AR5416_DEVID_PCI:
+ return "Atheros 5416";
+ case AR5416_DEVID_PCIE:
+ return "Atheros 5418";
+ case AR9160_DEVID_PCI:
+ return "Atheros 9160";
+ case AR5416_AR9100_DEVID:
+ return "Atheros 9100";
+ case AR9280_DEVID_PCI:
+ case AR9280_DEVID_PCIE:
+ return "Atheros 9280";
+ case AR9285_DEVID_PCIE:
+ return "Atheros 9285";
+ case AR5416_DEVID_AR9287_PCI:
+ case AR5416_DEVID_AR9287_PCIE:
+ return "Atheros 9287";
+ }
+
+ return NULL;
+}
+
static void ath9k_hw_init_config(struct ath_hw *ah)
{
int i;
@@ -334,6 +380,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
ah->config.pcie_clock_req = 0;
ah->config.pcie_waen = 0;
ah->config.analog_shiftreg = 1;
+ ah->config.ht_enable = 1;
ah->config.ofdm_trig_low = 200;
ah->config.ofdm_trig_high = 500;
ah->config.cck_trig_high = 200;
@@ -345,12 +392,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
ah->config.spurchans[i][1] = AR_NO_SPUR;
}
- if (ah->hw_version.devid != AR2427_DEVID_PCIE)
- ah->config.ht_enable = 1;
- else
- ah->config.ht_enable = 0;
-
- ah->config.rx_intr_mitigation = true;
+ ah->config.intr_mitigation = true;
/*
* We need this for PCI devices only (Cardbus, PCI, miniPCI)
@@ -395,6 +437,8 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
ah->beacon_interval = 100;
ah->enable_32kHz_clock = DONT_USE_32KHZ;
ah->slottime = (u32) -1;
+ ah->acktimeout = (u32) -1;
+ ah->ctstimeout = (u32) -1;
ah->globaltxtimeout = (u32) -1;
ah->power_mode = ATH9K_PM_UNDEFINED;
}
@@ -546,7 +590,6 @@ static bool ath9k_hw_devid_supported(u16 devid)
case AR5416_DEVID_AR9287_PCI:
case AR5416_DEVID_AR9287_PCIE:
case AR9271_USB:
- case AR2427_DEVID_PCIE:
return true;
default:
break;
@@ -1140,7 +1183,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
AR_IMR_RXORN |
AR_IMR_BCNMISC;
- if (ah->config.rx_intr_mitigation)
+ if (ah->config.intr_mitigation)
ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
else
ah->mask_reg |= AR_IMR_RXOK;
@@ -1160,25 +1203,34 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
}
}
-static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
+static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us)
{
- u32 val = ath9k_hw_mac_to_clks(ah, us);
- val = min(val, (u32) 0xFFFF);
- REG_WRITE(ah, AR_D_GBL_IFS_SLOT, val);
-}
-
-static void ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us)
-{
- u32 val = ath9k_hw_mac_to_clks(ah, us);
- val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_ACK));
- REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, val);
+ if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
+ ath_print(ath9k_hw_common(ah), ATH_DBG_RESET,
+ "bad ack timeout %u\n", us);
+ ah->acktimeout = (u32) -1;
+ return false;
+ } else {
+ REG_RMW_FIELD(ah, AR_TIME_OUT,
+ AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us));
+ ah->acktimeout = us;
+ return true;
+ }
}
-static void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us)
+static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us)
{
- u32 val = ath9k_hw_mac_to_clks(ah, us);
- val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_CTS));
- REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_CTS, val);
+ if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
+ ath_print(ath9k_hw_common(ah), ATH_DBG_RESET,
+ "bad cts timeout %u\n", us);
+ ah->ctstimeout = (u32) -1;
+ return false;
+ } else {
+ REG_RMW_FIELD(ah, AR_TIME_OUT,
+ AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us));
+ ah->ctstimeout = us;
+ return true;
+ }
}
static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
@@ -1195,48 +1247,31 @@ static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
}
}
-void ath9k_hw_init_global_settings(struct ath_hw *ah)
+static void ath9k_hw_init_user_settings(struct ath_hw *ah)
{
- struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
- int acktimeout;
- int slottime;
- int sifstime;
-
ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n",
ah->misc_mode);
if (ah->misc_mode != 0)
REG_WRITE(ah, AR_PCU_MISC,
REG_READ(ah, AR_PCU_MISC) | ah->misc_mode);
-
- if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ)
- sifstime = 16;
- else
- sifstime = 10;
-
- /* As defined by IEEE 802.11-2007 17.3.8.6 */
- slottime = ah->slottime + 3 * ah->coverage_class;
- acktimeout = slottime + sifstime;
-
- /*
- * Workaround for early ACK timeouts, add an offset to match the
- * initval's 64us ack timeout value.
- * This was initially only meant to work around an issue with delayed
- * BA frames in some implementations, but it has been found to fix ACK
- * timeout issues in other cases as well.
- */
- if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ)
- acktimeout += 64 - sifstime - ah->slottime;
-
- ath9k_hw_setslottime(ah, slottime);
- ath9k_hw_set_ack_timeout(ah, acktimeout);
- ath9k_hw_set_cts_timeout(ah, acktimeout);
+ if (ah->slottime != (u32) -1)
+ ath9k_hw_setslottime(ah, ah->slottime);
+ if (ah->acktimeout != (u32) -1)
+ ath9k_hw_set_ack_timeout(ah, ah->acktimeout);
+ if (ah->ctstimeout != (u32) -1)
+ ath9k_hw_set_cts_timeout(ah, ah->ctstimeout);
if (ah->globaltxtimeout != (u32) -1)
ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
}
-EXPORT_SYMBOL(ath9k_hw_init_global_settings);
-void ath9k_hw_deinit(struct ath_hw *ah)
+const char *ath9k_hw_probe(u16 vendorid, u16 devid)
+{
+ return vendorid == ATHEROS_VENDOR_ID ?
+ ath9k_hw_devname(devid) : NULL;
+}
+
+void ath9k_hw_detach(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
@@ -1254,7 +1289,7 @@ void ath9k_hw_deinit(struct ath_hw *ah)
kfree(ah);
ah = NULL;
}
-EXPORT_SYMBOL(ath9k_hw_deinit);
+EXPORT_SYMBOL(ath9k_hw_detach);
/*******/
/* INI */
@@ -2055,7 +2090,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
ath9k_enable_rfkill(ah);
- ath9k_hw_init_global_settings(ah);
+ ath9k_hw_init_user_settings(ah);
if (AR_SREV_9287_12_OR_LATER(ah)) {
REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
@@ -2085,7 +2120,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
REG_WRITE(ah, AR_OBS, 8);
- if (ah->config.rx_intr_mitigation) {
+ if (ah->config.intr_mitigation) {
REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
}
@@ -2745,7 +2780,7 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
*masked = isr & ATH9K_INT_COMMON;
- if (ah->config.rx_intr_mitigation) {
+ if (ah->config.intr_mitigation) {
if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
*masked |= ATH9K_INT_RX;
}
@@ -2878,7 +2913,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
}
if (ints & ATH9K_INT_RX) {
mask |= AR_IMR_RXERR;
- if (ah->config.rx_intr_mitigation)
+ if (ah->config.intr_mitigation)
mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
else
mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
@@ -3652,6 +3687,21 @@ u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp)
}
EXPORT_SYMBOL(ath9k_hw_extend_tsf);
+bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
+{
+ if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) {
+ ath_print(ath9k_hw_common(ah), ATH_DBG_RESET,
+ "bad slot time %u\n", us);
+ ah->slottime = (u32) -1;
+ return false;
+ } else {
+ REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us));
+ ah->slottime = us;
+ return true;
+ }
+}
+EXPORT_SYMBOL(ath9k_hw_setslottime);
+
void ath9k_hw_set11nmac2040(struct ath_hw *ah)
{
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.h b/trunk/drivers/net/wireless/ath/ath9k/hw.h
index dbbf7ca5f97d..e2b0c73a616f 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/hw.h
+++ b/trunk/drivers/net/wireless/ath/ath9k/hw.h
@@ -40,7 +40,6 @@
#define AR9280_DEVID_PCI 0x0029
#define AR9280_DEVID_PCIE 0x002a
#define AR9285_DEVID_PCIE 0x002b
-#define AR2427_DEVID_PCIE 0x002c
#define AR5416_AR9100_DEVID 0x000b
@@ -213,7 +212,7 @@ struct ath9k_ops_config {
u32 cck_trig_low;
u32 enable_ani;
int serialize_regmode;
- bool rx_intr_mitigation;
+ bool intr_mitigation;
#define SPUR_DISABLE 0
#define SPUR_ENABLE_IOCTL 1
#define SPUR_ENABLE_EEPROM 2
@@ -552,9 +551,10 @@ struct ath_hw {
u32 *bank6Temp;
int16_t txpower_indexoffset;
- int coverage_class;
u32 beacon_interval;
u32 slottime;
+ u32 acktimeout;
+ u32 ctstimeout;
u32 globaltxtimeout;
/* ANI */
@@ -616,7 +616,7 @@ static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah)
/* Initialization, Detach, Reset */
const char *ath9k_hw_probe(u16 vendorid, u16 devid);
-void ath9k_hw_deinit(struct ath_hw *ah);
+void ath9k_hw_detach(struct ath_hw *ah);
int ath9k_hw_init(struct ath_hw *ah);
int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
bool bChannelChange);
@@ -668,7 +668,7 @@ void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
void ath9k_hw_reset_tsf(struct ath_hw *ah);
void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp);
-void ath9k_hw_init_global_settings(struct ath_hw *ah);
+bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us);
void ath9k_hw_set11nmac2040(struct ath_hw *ah);
void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
diff --git a/trunk/drivers/net/wireless/ath/ath9k/init.c b/trunk/drivers/net/wireless/ath/ath9k/init.c
deleted file mode 100644
index 623c2f884987..000000000000
--- a/trunk/drivers/net/wireless/ath/ath9k/init.c
+++ /dev/null
@@ -1,863 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "ath9k.h"
-
-static char *dev_info = "ath9k";
-
-MODULE_AUTHOR("Atheros Communications");
-MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
-MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
-MODULE_LICENSE("Dual BSD/GPL");
-
-static unsigned int ath9k_debug = ATH_DBG_DEFAULT;
-module_param_named(debug, ath9k_debug, uint, 0);
-MODULE_PARM_DESC(debug, "Debugging mask");
-
-int modparam_nohwcrypt;
-module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
-MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
-
-/* We use the hw_value as an index into our private channel structure */
-
-#define CHAN2G(_freq, _idx) { \
- .center_freq = (_freq), \
- .hw_value = (_idx), \
- .max_power = 20, \
-}
-
-#define CHAN5G(_freq, _idx) { \
- .band = IEEE80211_BAND_5GHZ, \
- .center_freq = (_freq), \
- .hw_value = (_idx), \
- .max_power = 20, \
-}
-
-/* Some 2 GHz radios are actually tunable on 2312-2732
- * on 5 MHz steps, we support the channels which we know
- * we have calibration data for all cards though to make
- * this static */
-static struct ieee80211_channel ath9k_2ghz_chantable[] = {
- CHAN2G(2412, 0), /* Channel 1 */
- CHAN2G(2417, 1), /* Channel 2 */
- CHAN2G(2422, 2), /* Channel 3 */
- CHAN2G(2427, 3), /* Channel 4 */
- CHAN2G(2432, 4), /* Channel 5 */
- CHAN2G(2437, 5), /* Channel 6 */
- CHAN2G(2442, 6), /* Channel 7 */
- CHAN2G(2447, 7), /* Channel 8 */
- CHAN2G(2452, 8), /* Channel 9 */
- CHAN2G(2457, 9), /* Channel 10 */
- CHAN2G(2462, 10), /* Channel 11 */
- CHAN2G(2467, 11), /* Channel 12 */
- CHAN2G(2472, 12), /* Channel 13 */
- CHAN2G(2484, 13), /* Channel 14 */
-};
-
-/* Some 5 GHz radios are actually tunable on XXXX-YYYY
- * on 5 MHz steps, we support the channels which we know
- * we have calibration data for all cards though to make
- * this static */
-static struct ieee80211_channel ath9k_5ghz_chantable[] = {
- /* _We_ call this UNII 1 */
- CHAN5G(5180, 14), /* Channel 36 */
- CHAN5G(5200, 15), /* Channel 40 */
- CHAN5G(5220, 16), /* Channel 44 */
- CHAN5G(5240, 17), /* Channel 48 */
- /* _We_ call this UNII 2 */
- CHAN5G(5260, 18), /* Channel 52 */
- CHAN5G(5280, 19), /* Channel 56 */
- CHAN5G(5300, 20), /* Channel 60 */
- CHAN5G(5320, 21), /* Channel 64 */
- /* _We_ call this "Middle band" */
- CHAN5G(5500, 22), /* Channel 100 */
- CHAN5G(5520, 23), /* Channel 104 */
- CHAN5G(5540, 24), /* Channel 108 */
- CHAN5G(5560, 25), /* Channel 112 */
- CHAN5G(5580, 26), /* Channel 116 */
- CHAN5G(5600, 27), /* Channel 120 */
- CHAN5G(5620, 28), /* Channel 124 */
- CHAN5G(5640, 29), /* Channel 128 */
- CHAN5G(5660, 30), /* Channel 132 */
- CHAN5G(5680, 31), /* Channel 136 */
- CHAN5G(5700, 32), /* Channel 140 */
- /* _We_ call this UNII 3 */
- CHAN5G(5745, 33), /* Channel 149 */
- CHAN5G(5765, 34), /* Channel 153 */
- CHAN5G(5785, 35), /* Channel 157 */
- CHAN5G(5805, 36), /* Channel 161 */
- CHAN5G(5825, 37), /* Channel 165 */
-};
-
-/* Atheros hardware rate code addition for short premble */
-#define SHPCHECK(__hw_rate, __flags) \
- ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0)
-
-#define RATE(_bitrate, _hw_rate, _flags) { \
- .bitrate = (_bitrate), \
- .flags = (_flags), \
- .hw_value = (_hw_rate), \
- .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \
-}
-
-static struct ieee80211_rate ath9k_legacy_rates[] = {
- RATE(10, 0x1b, 0),
- RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE),
- RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE),
- RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE),
- RATE(60, 0x0b, 0),
- RATE(90, 0x0f, 0),
- RATE(120, 0x0a, 0),
- RATE(180, 0x0e, 0),
- RATE(240, 0x09, 0),
- RATE(360, 0x0d, 0),
- RATE(480, 0x08, 0),
- RATE(540, 0x0c, 0),
-};
-
-static void ath9k_deinit_softc(struct ath_softc *sc);
-
-/*
- * Read and write, they both share the same lock. We do this to serialize
- * reads and writes on Atheros 802.11n PCI devices only. This is required
- * as the FIFO on these devices can only accept sanely 2 requests.
- */
-
-static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)
-{
- struct ath_hw *ah = (struct ath_hw *) hw_priv;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ath_softc *sc = (struct ath_softc *) common->priv;
-
- if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
- unsigned long flags;
- spin_lock_irqsave(&sc->sc_serial_rw, flags);
- iowrite32(val, sc->mem + reg_offset);
- spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
- } else
- iowrite32(val, sc->mem + reg_offset);
-}
-
-static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
-{
- struct ath_hw *ah = (struct ath_hw *) hw_priv;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ath_softc *sc = (struct ath_softc *) common->priv;
- u32 val;
-
- if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
- unsigned long flags;
- spin_lock_irqsave(&sc->sc_serial_rw, flags);
- val = ioread32(sc->mem + reg_offset);
- spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
- } else
- val = ioread32(sc->mem + reg_offset);
- return val;
-}
-
-static const struct ath_ops ath9k_common_ops = {
- .read = ath9k_ioread32,
- .write = ath9k_iowrite32,
-};
-
-/**************************/
-/* Initialization */
-/**************************/
-
-static void setup_ht_cap(struct ath_softc *sc,
- struct ieee80211_sta_ht_cap *ht_info)
-{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- u8 tx_streams, rx_streams;
-
- ht_info->ht_supported = true;
- ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
- IEEE80211_HT_CAP_SM_PS |
- IEEE80211_HT_CAP_SGI_40 |
- IEEE80211_HT_CAP_DSSSCCK40;
-
- ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
- ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
-
- /* set up supported mcs set */
- memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
- tx_streams = !(common->tx_chainmask & (common->tx_chainmask - 1)) ?
- 1 : 2;
- rx_streams = !(common->rx_chainmask & (common->rx_chainmask - 1)) ?
- 1 : 2;
-
- if (tx_streams != rx_streams) {
- ath_print(common, ATH_DBG_CONFIG,
- "TX streams %d, RX streams: %d\n",
- tx_streams, rx_streams);
- ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
- ht_info->mcs.tx_params |= ((tx_streams - 1) <<
- IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
- }
-
- ht_info->mcs.rx_mask[0] = 0xff;
- if (rx_streams >= 2)
- ht_info->mcs.rx_mask[1] = 0xff;
-
- ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
-}
-
-static int ath9k_reg_notifier(struct wiphy *wiphy,
- struct regulatory_request *request)
-{
- struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
- struct ath_wiphy *aphy = hw->priv;
- struct ath_softc *sc = aphy->sc;
- struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah);
-
- return ath_reg_notifier_apply(wiphy, request, reg);
-}
-
-/*
- * This function will allocate both the DMA descriptor structure, and the
- * buffers it contains. These are used to contain the descriptors used
- * by the system.
-*/
-int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
- struct list_head *head, const char *name,
- int nbuf, int ndesc)
-{
-#define DS2PHYS(_dd, _ds) \
- ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
-#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
-#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath_desc *ds;
- struct ath_buf *bf;
- int i, bsize, error;
-
- ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n",
- name, nbuf, ndesc);
-
- INIT_LIST_HEAD(head);
- /* ath_desc must be a multiple of DWORDs */
- if ((sizeof(struct ath_desc) % 4) != 0) {
- ath_print(common, ATH_DBG_FATAL,
- "ath_desc not DWORD aligned\n");
- BUG_ON((sizeof(struct ath_desc) % 4) != 0);
- error = -ENOMEM;
- goto fail;
- }
-
- dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc;
-
- /*
- * Need additional DMA memory because we can't use
- * descriptors that cross the 4K page boundary. Assume
- * one skipped descriptor per 4K page.
- */
- if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
- u32 ndesc_skipped =
- ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len);
- u32 dma_len;
-
- while (ndesc_skipped) {
- dma_len = ndesc_skipped * sizeof(struct ath_desc);
- dd->dd_desc_len += dma_len;
-
- ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len);
- };
- }
-
- /* allocate descriptors */
- dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len,
- &dd->dd_desc_paddr, GFP_KERNEL);
- if (dd->dd_desc == NULL) {
- error = -ENOMEM;
- goto fail;
- }
- ds = dd->dd_desc;
- ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
- name, ds, (u32) dd->dd_desc_len,
- ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
-
- /* allocate buffers */
- bsize = sizeof(struct ath_buf) * nbuf;
- bf = kzalloc(bsize, GFP_KERNEL);
- if (bf == NULL) {
- error = -ENOMEM;
- goto fail2;
- }
- dd->dd_bufptr = bf;
-
- for (i = 0; i < nbuf; i++, bf++, ds += ndesc) {
- bf->bf_desc = ds;
- bf->bf_daddr = DS2PHYS(dd, ds);
-
- if (!(sc->sc_ah->caps.hw_caps &
- ATH9K_HW_CAP_4KB_SPLITTRANS)) {
- /*
- * Skip descriptor addresses which can cause 4KB
- * boundary crossing (addr + length) with a 32 dword
- * descriptor fetch.
- */
- while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
- BUG_ON((caddr_t) bf->bf_desc >=
- ((caddr_t) dd->dd_desc +
- dd->dd_desc_len));
-
- ds += ndesc;
- bf->bf_desc = ds;
- bf->bf_daddr = DS2PHYS(dd, ds);
- }
- }
- list_add_tail(&bf->list, head);
- }
- return 0;
-fail2:
- dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
- dd->dd_desc_paddr);
-fail:
- memset(dd, 0, sizeof(*dd));
- return error;
-#undef ATH_DESC_4KB_BOUND_CHECK
-#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED
-#undef DS2PHYS
-}
-
-static void ath9k_init_crypto(struct ath_softc *sc)
-{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- int i = 0;
-
- /* Get the hardware key cache size. */
- common->keymax = sc->sc_ah->caps.keycache_size;
- if (common->keymax > ATH_KEYMAX) {
- ath_print(common, ATH_DBG_ANY,
- "Warning, using only %u entries in %u key cache\n",
- ATH_KEYMAX, common->keymax);
- common->keymax = ATH_KEYMAX;
- }
-
- /*
- * Reset the key cache since some parts do not
- * reset the contents on initial power up.
- */
- for (i = 0; i < common->keymax; i++)
- ath9k_hw_keyreset(sc->sc_ah, (u16) i);
-
- if (ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER,
- ATH9K_CIPHER_TKIP, NULL)) {
- /*
- * Whether we should enable h/w TKIP MIC.
- * XXX: if we don't support WME TKIP MIC, then we wouldn't
- * report WMM capable, so it's always safe to turn on
- * TKIP MIC in this case.
- */
- ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, 0, 1, NULL);
- }
-
- /*
- * Check whether the separate key cache entries
- * are required to handle both tx+rx MIC keys.
- * With split mic keys the number of stations is limited
- * to 27 otherwise 59.
- */
- if (ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER,
- ATH9K_CIPHER_TKIP, NULL)
- && ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER,
- ATH9K_CIPHER_MIC, NULL)
- && ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_TKIP_SPLIT,
- 0, NULL))
- common->splitmic = 1;
-
- /* turn on mcast key search if possible */
- if (!ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL))
- (void)ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_MCAST_KEYSRCH,
- 1, 1, NULL);
-
-}
-
-static int ath9k_init_btcoex(struct ath_softc *sc)
-{
- int r, qnum;
-
- switch (sc->sc_ah->btcoex_hw.scheme) {
- case ATH_BTCOEX_CFG_NONE:
- break;
- case ATH_BTCOEX_CFG_2WIRE:
- ath9k_hw_btcoex_init_2wire(sc->sc_ah);
- break;
- case ATH_BTCOEX_CFG_3WIRE:
- ath9k_hw_btcoex_init_3wire(sc->sc_ah);
- r = ath_init_btcoex_timer(sc);
- if (r)
- return -1;
- qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE);
- ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum);
- sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
- break;
- default:
- WARN_ON(1);
- break;
- }
-
- return 0;
-}
-
-static int ath9k_init_queues(struct ath_softc *sc)
-{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- int i = 0;
-
- for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++)
- sc->tx.hwq_map[i] = -1;
-
- sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
- if (sc->beacon.beaconq == -1) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup a beacon xmit queue\n");
- goto err;
- }
-
- sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
- if (sc->beacon.cabq == NULL) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup CAB xmit queue\n");
- goto err;
- }
-
- sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
- ath_cabq_update(sc);
-
- if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup xmit queue for BK traffic\n");
- goto err;
- }
-
- if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup xmit queue for BE traffic\n");
- goto err;
- }
- if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup xmit queue for VI traffic\n");
- goto err;
- }
- if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup xmit queue for VO traffic\n");
- goto err;
- }
-
- return 0;
-
-err:
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
- if (ATH_TXQ_SETUP(sc, i))
- ath_tx_cleanupq(sc, &sc->tx.txq[i]);
-
- return -EIO;
-}
-
-static void ath9k_init_channels_rates(struct ath_softc *sc)
-{
- if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) {
- sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable;
- sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
- sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
- ARRAY_SIZE(ath9k_2ghz_chantable);
- sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates;
- sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
- ARRAY_SIZE(ath9k_legacy_rates);
- }
-
- if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) {
- sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable;
- sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
- sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
- ARRAY_SIZE(ath9k_5ghz_chantable);
- sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
- ath9k_legacy_rates + 4;
- sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
- ARRAY_SIZE(ath9k_legacy_rates) - 4;
- }
-}
-
-static void ath9k_init_misc(struct ath_softc *sc)
-{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- int i = 0;
-
- common->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR;
- setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
-
- sc->config.txpowlimit = ATH_TXPOWER_MAX;
-
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
- sc->sc_flags |= SC_OP_TXAGGR;
- sc->sc_flags |= SC_OP_RXAGGR;
- }
-
- common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
- common->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
-
- ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_DIVERSITY, 1, true, NULL);
- sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
-
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
- memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
-
- sc->beacon.slottime = ATH9K_SLOT_TIME_9;
-
- for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
- sc->beacon.bslot[i] = NULL;
- sc->beacon.bslot_aphy[i] = NULL;
- }
-}
-
-static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
- const struct ath_bus_ops *bus_ops)
-{
- struct ath_hw *ah = NULL;
- struct ath_common *common;
- int ret = 0, i;
- int csz = 0;
-
- ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
- if (!ah)
- return -ENOMEM;
-
- ah->hw_version.devid = devid;
- ah->hw_version.subsysid = subsysid;
- sc->sc_ah = ah;
-
- common = ath9k_hw_common(ah);
- common->ops = &ath9k_common_ops;
- common->bus_ops = bus_ops;
- common->ah = ah;
- common->hw = sc->hw;
- common->priv = sc;
- common->debug_mask = ath9k_debug;
-
- spin_lock_init(&sc->wiphy_lock);
- spin_lock_init(&sc->sc_resetlock);
- spin_lock_init(&sc->sc_serial_rw);
- spin_lock_init(&sc->sc_pm_lock);
- mutex_init(&sc->mutex);
- tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
- tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
- (unsigned long)sc);
-
- /*
- * Cache line size is used to size and align various
- * structures used to communicate with the hardware.
- */
- ath_read_cachesize(common, &csz);
- common->cachelsz = csz << 2; /* convert to bytes */
-
- ret = ath9k_hw_init(ah);
- if (ret) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to initialize hardware; "
- "initialization status: %d\n", ret);
- goto err_hw;
- }
-
- ret = ath9k_init_debug(ah);
- if (ret) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to create debugfs files\n");
- goto err_debug;
- }
-
- ret = ath9k_init_queues(sc);
- if (ret)
- goto err_queues;
-
- ret = ath9k_init_btcoex(sc);
- if (ret)
- goto err_btcoex;
-
- ath9k_init_crypto(sc);
- ath9k_init_channels_rates(sc);
- ath9k_init_misc(sc);
-
- return 0;
-
-err_btcoex:
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
- if (ATH_TXQ_SETUP(sc, i))
- ath_tx_cleanupq(sc, &sc->tx.txq[i]);
-err_queues:
- ath9k_exit_debug(ah);
-err_debug:
- ath9k_hw_deinit(ah);
-err_hw:
- tasklet_kill(&sc->intr_tq);
- tasklet_kill(&sc->bcon_tasklet);
-
- kfree(ah);
- sc->sc_ah = NULL;
-
- return ret;
-}
-
-void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
-{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-
- hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
- IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
- IEEE80211_HW_SIGNAL_DBM |
- IEEE80211_HW_SUPPORTS_PS |
- IEEE80211_HW_PS_NULLFUNC_STACK |
- IEEE80211_HW_SPECTRUM_MGMT |
- IEEE80211_HW_REPORTS_TX_ACK_STATUS;
-
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
- hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
-
- if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt)
- hw->flags |= IEEE80211_HW_MFP_CAPABLE;
-
- hw->wiphy->interface_modes =
- BIT(NL80211_IFTYPE_AP) |
- BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC) |
- BIT(NL80211_IFTYPE_MESH_POINT);
-
- hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
-
- hw->queues = 4;
- hw->max_rates = 4;
- hw->channel_change_time = 5000;
- hw->max_listen_interval = 10;
- hw->max_rate_tries = 10;
- hw->sta_data_size = sizeof(struct ath_node);
- hw->vif_data_size = sizeof(struct ath_vif);
-
- hw->rate_control_algorithm = "ath9k_rate_control";
-
- if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes))
- hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
- &sc->sbands[IEEE80211_BAND_2GHZ];
- if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
- hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
- &sc->sbands[IEEE80211_BAND_5GHZ];
-
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
- if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes))
- setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
- if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
- setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
- }
-
- SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
-}
-
-int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
- const struct ath_bus_ops *bus_ops)
-{
- struct ieee80211_hw *hw = sc->hw;
- struct ath_common *common;
- struct ath_hw *ah;
- int error = 0;
- struct ath_regulatory *reg;
-
- /* Bring up device */
- error = ath9k_init_softc(devid, sc, subsysid, bus_ops);
- if (error != 0)
- goto error_init;
-
- ah = sc->sc_ah;
- common = ath9k_hw_common(ah);
- ath9k_set_hw_capab(sc, hw);
-
- /* Initialize regulatory */
- error = ath_regd_init(&common->regulatory, sc->hw->wiphy,
- ath9k_reg_notifier);
- if (error)
- goto error_regd;
-
- reg = &common->regulatory;
-
- /* Setup TX DMA */
- error = ath_tx_init(sc, ATH_TXBUF);
- if (error != 0)
- goto error_tx;
-
- /* Setup RX DMA */
- error = ath_rx_init(sc, ATH_RXBUF);
- if (error != 0)
- goto error_rx;
-
- /* Register with mac80211 */
- error = ieee80211_register_hw(hw);
- if (error)
- goto error_register;
-
- /* Handle world regulatory */
- if (!ath_is_world_regd(reg)) {
- error = regulatory_hint(hw->wiphy, reg->alpha2);
- if (error)
- goto error_world;
- }
-
- INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
- INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
- sc->wiphy_scheduler_int = msecs_to_jiffies(500);
-
- ath_init_leds(sc);
- ath_start_rfkill_poll(sc);
-
- return 0;
-
-error_world:
- ieee80211_unregister_hw(hw);
-error_register:
- ath_rx_cleanup(sc);
-error_rx:
- ath_tx_cleanup(sc);
-error_tx:
- /* Nothing */
-error_regd:
- ath9k_deinit_softc(sc);
-error_init:
- return error;
-}
-
-/*****************************/
-/* De-Initialization */
-/*****************************/
-
-static void ath9k_deinit_softc(struct ath_softc *sc)
-{
- int i = 0;
-
- if ((sc->btcoex.no_stomp_timer) &&
- sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
- ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
-
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
- if (ATH_TXQ_SETUP(sc, i))
- ath_tx_cleanupq(sc, &sc->tx.txq[i]);
-
- ath9k_exit_debug(sc->sc_ah);
- ath9k_hw_deinit(sc->sc_ah);
-
- tasklet_kill(&sc->intr_tq);
- tasklet_kill(&sc->bcon_tasklet);
-}
-
-void ath9k_deinit_device(struct ath_softc *sc)
-{
- struct ieee80211_hw *hw = sc->hw;
- int i = 0;
-
- ath9k_ps_wakeup(sc);
-
- wiphy_rfkill_stop_polling(sc->hw->wiphy);
- ath_deinit_leds(sc);
-
- for (i = 0; i < sc->num_sec_wiphy; i++) {
- struct ath_wiphy *aphy = sc->sec_wiphy[i];
- if (aphy == NULL)
- continue;
- sc->sec_wiphy[i] = NULL;
- ieee80211_unregister_hw(aphy->hw);
- ieee80211_free_hw(aphy->hw);
- }
- kfree(sc->sec_wiphy);
-
- ieee80211_unregister_hw(hw);
- ath_rx_cleanup(sc);
- ath_tx_cleanup(sc);
- ath9k_deinit_softc(sc);
-}
-
-void ath_descdma_cleanup(struct ath_softc *sc,
- struct ath_descdma *dd,
- struct list_head *head)
-{
- dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
- dd->dd_desc_paddr);
-
- INIT_LIST_HEAD(head);
- kfree(dd->dd_bufptr);
- memset(dd, 0, sizeof(*dd));
-}
-
-/************************/
-/* Module Hooks */
-/************************/
-
-static int __init ath9k_init(void)
-{
- int error;
-
- /* Register rate control algorithm */
- error = ath_rate_control_register();
- if (error != 0) {
- printk(KERN_ERR
- "ath9k: Unable to register rate control "
- "algorithm: %d\n",
- error);
- goto err_out;
- }
-
- error = ath9k_debug_create_root();
- if (error) {
- printk(KERN_ERR
- "ath9k: Unable to create debugfs root: %d\n",
- error);
- goto err_rate_unregister;
- }
-
- error = ath_pci_init();
- if (error < 0) {
- printk(KERN_ERR
- "ath9k: No PCI devices found, driver not installed.\n");
- error = -ENODEV;
- goto err_remove_root;
- }
-
- error = ath_ahb_init();
- if (error < 0) {
- error = -ENODEV;
- goto err_pci_exit;
- }
-
- return 0;
-
- err_pci_exit:
- ath_pci_exit();
-
- err_remove_root:
- ath9k_debug_remove_root();
- err_rate_unregister:
- ath_rate_control_unregister();
- err_out:
- return error;
-}
-module_init(ath9k_init);
-
-static void __exit ath9k_exit(void)
-{
- ath_ahb_exit();
- ath_pci_exit();
- ath9k_debug_remove_root();
- ath_rate_control_unregister();
- printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
-}
-module_exit(ath9k_exit);
diff --git a/trunk/drivers/net/wireless/ath/ath9k/mac.h b/trunk/drivers/net/wireless/ath/ath9k/mac.h
index 29851e6376a9..e185479e295e 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/mac.h
+++ b/trunk/drivers/net/wireless/ath/ath9k/mac.h
@@ -167,40 +167,6 @@ struct ath_rx_status {
#define ATH9K_RXKEYIX_INVALID ((u8)-1)
#define ATH9K_TXKEYIX_INVALID ((u32)-1)
-enum ath9k_phyerr {
- ATH9K_PHYERR_UNDERRUN = 0, /* Transmit underrun */
- ATH9K_PHYERR_TIMING = 1, /* Timing error */
- ATH9K_PHYERR_PARITY = 2, /* Illegal parity */
- ATH9K_PHYERR_RATE = 3, /* Illegal rate */
- ATH9K_PHYERR_LENGTH = 4, /* Illegal length */
- ATH9K_PHYERR_RADAR = 5, /* Radar detect */
- ATH9K_PHYERR_SERVICE = 6, /* Illegal service */
- ATH9K_PHYERR_TOR = 7, /* Transmit override receive */
-
- ATH9K_PHYERR_OFDM_TIMING = 17,
- ATH9K_PHYERR_OFDM_SIGNAL_PARITY = 18,
- ATH9K_PHYERR_OFDM_RATE_ILLEGAL = 19,
- ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL = 20,
- ATH9K_PHYERR_OFDM_POWER_DROP = 21,
- ATH9K_PHYERR_OFDM_SERVICE = 22,
- ATH9K_PHYERR_OFDM_RESTART = 23,
- ATH9K_PHYERR_FALSE_RADAR_EXT = 24,
-
- ATH9K_PHYERR_CCK_TIMING = 25,
- ATH9K_PHYERR_CCK_HEADER_CRC = 26,
- ATH9K_PHYERR_CCK_RATE_ILLEGAL = 27,
- ATH9K_PHYERR_CCK_SERVICE = 30,
- ATH9K_PHYERR_CCK_RESTART = 31,
- ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 32,
- ATH9K_PHYERR_CCK_POWER_DROP = 33,
-
- ATH9K_PHYERR_HT_CRC_ERROR = 34,
- ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 35,
- ATH9K_PHYERR_HT_RATE_ILLEGAL = 36,
-
- ATH9K_PHYERR_MAX = 37,
-};
-
struct ath_desc {
u32 ds_link;
u32 ds_data;
diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c
index 67ca4e5a6017..643bea35686f 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/main.c
+++ b/trunk/drivers/net/wireless/ath/ath9k/main.c
@@ -18,6 +18,118 @@
#include "ath9k.h"
#include "btcoex.h"
+static char *dev_info = "ath9k";
+
+MODULE_AUTHOR("Atheros Communications");
+MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
+MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
+MODULE_LICENSE("Dual BSD/GPL");
+
+static int modparam_nohwcrypt;
+module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
+
+static unsigned int ath9k_debug = ATH_DBG_DEFAULT;
+module_param_named(debug, ath9k_debug, uint, 0);
+MODULE_PARM_DESC(debug, "Debugging mask");
+
+/* We use the hw_value as an index into our private channel structure */
+
+#define CHAN2G(_freq, _idx) { \
+ .center_freq = (_freq), \
+ .hw_value = (_idx), \
+ .max_power = 20, \
+}
+
+#define CHAN5G(_freq, _idx) { \
+ .band = IEEE80211_BAND_5GHZ, \
+ .center_freq = (_freq), \
+ .hw_value = (_idx), \
+ .max_power = 20, \
+}
+
+/* Some 2 GHz radios are actually tunable on 2312-2732
+ * on 5 MHz steps, we support the channels which we know
+ * we have calibration data for all cards though to make
+ * this static */
+static struct ieee80211_channel ath9k_2ghz_chantable[] = {
+ CHAN2G(2412, 0), /* Channel 1 */
+ CHAN2G(2417, 1), /* Channel 2 */
+ CHAN2G(2422, 2), /* Channel 3 */
+ CHAN2G(2427, 3), /* Channel 4 */
+ CHAN2G(2432, 4), /* Channel 5 */
+ CHAN2G(2437, 5), /* Channel 6 */
+ CHAN2G(2442, 6), /* Channel 7 */
+ CHAN2G(2447, 7), /* Channel 8 */
+ CHAN2G(2452, 8), /* Channel 9 */
+ CHAN2G(2457, 9), /* Channel 10 */
+ CHAN2G(2462, 10), /* Channel 11 */
+ CHAN2G(2467, 11), /* Channel 12 */
+ CHAN2G(2472, 12), /* Channel 13 */
+ CHAN2G(2484, 13), /* Channel 14 */
+};
+
+/* Some 5 GHz radios are actually tunable on XXXX-YYYY
+ * on 5 MHz steps, we support the channels which we know
+ * we have calibration data for all cards though to make
+ * this static */
+static struct ieee80211_channel ath9k_5ghz_chantable[] = {
+ /* _We_ call this UNII 1 */
+ CHAN5G(5180, 14), /* Channel 36 */
+ CHAN5G(5200, 15), /* Channel 40 */
+ CHAN5G(5220, 16), /* Channel 44 */
+ CHAN5G(5240, 17), /* Channel 48 */
+ /* _We_ call this UNII 2 */
+ CHAN5G(5260, 18), /* Channel 52 */
+ CHAN5G(5280, 19), /* Channel 56 */
+ CHAN5G(5300, 20), /* Channel 60 */
+ CHAN5G(5320, 21), /* Channel 64 */
+ /* _We_ call this "Middle band" */
+ CHAN5G(5500, 22), /* Channel 100 */
+ CHAN5G(5520, 23), /* Channel 104 */
+ CHAN5G(5540, 24), /* Channel 108 */
+ CHAN5G(5560, 25), /* Channel 112 */
+ CHAN5G(5580, 26), /* Channel 116 */
+ CHAN5G(5600, 27), /* Channel 120 */
+ CHAN5G(5620, 28), /* Channel 124 */
+ CHAN5G(5640, 29), /* Channel 128 */
+ CHAN5G(5660, 30), /* Channel 132 */
+ CHAN5G(5680, 31), /* Channel 136 */
+ CHAN5G(5700, 32), /* Channel 140 */
+ /* _We_ call this UNII 3 */
+ CHAN5G(5745, 33), /* Channel 149 */
+ CHAN5G(5765, 34), /* Channel 153 */
+ CHAN5G(5785, 35), /* Channel 157 */
+ CHAN5G(5805, 36), /* Channel 161 */
+ CHAN5G(5825, 37), /* Channel 165 */
+};
+
+/* Atheros hardware rate code addition for short premble */
+#define SHPCHECK(__hw_rate, __flags) \
+ ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0)
+
+#define RATE(_bitrate, _hw_rate, _flags) { \
+ .bitrate = (_bitrate), \
+ .flags = (_flags), \
+ .hw_value = (_hw_rate), \
+ .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \
+}
+
+static struct ieee80211_rate ath9k_legacy_rates[] = {
+ RATE(10, 0x1b, 0),
+ RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATE(60, 0x0b, 0),
+ RATE(90, 0x0f, 0),
+ RATE(120, 0x0a, 0),
+ RATE(180, 0x0e, 0),
+ RATE(240, 0x09, 0),
+ RATE(360, 0x0d, 0),
+ RATE(480, 0x08, 0),
+ RATE(540, 0x0c, 0),
+};
+
static void ath_cache_conf_rate(struct ath_softc *sc,
struct ieee80211_conf *conf)
{
@@ -109,7 +221,7 @@ static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc,
return channel;
}
-bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
+static bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
{
unsigned long flags;
bool ret;
@@ -143,13 +255,11 @@ void ath9k_ps_restore(struct ath_softc *sc)
if (--sc->ps_usecount != 0)
goto unlock;
- if (sc->ps_idle)
- ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
- else if (sc->ps_enabled &&
- !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
- PS_WAIT_FOR_CAB |
- PS_WAIT_FOR_PSPOLL_DATA |
- PS_WAIT_FOR_TX_ACK)))
+ if (sc->ps_enabled &&
+ !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
+ SC_OP_WAIT_FOR_CAB |
+ SC_OP_WAIT_FOR_PSPOLL_DATA |
+ SC_OP_WAIT_FOR_TX_ACK)))
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
unlock:
@@ -206,7 +316,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
r = ath9k_hw_reset(ah, hchan, fastcc);
if (r) {
ath_print(common, ATH_DBG_FATAL,
- "Unable to reset channel (%u MHz), "
+ "Unable to reset channel (%u Mhz) "
"reset status %d\n",
channel->center_freq, r);
spin_unlock_bh(&sc->sc_resetlock);
@@ -239,7 +349,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
* When the task is complete, it reschedules itself depending on the
* appropriate interval that was calculated.
*/
-void ath_ani_calibrate(unsigned long data)
+static void ath_ani_calibrate(unsigned long data)
{
struct ath_softc *sc = (struct ath_softc *)data;
struct ath_hw *ah = sc->sc_ah;
@@ -253,6 +363,14 @@ void ath_ani_calibrate(unsigned long data)
short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ?
ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
+ /*
+ * don't calibrate when we're scanning.
+ * we are most likely not on our home channel.
+ */
+ spin_lock(&sc->ani_lock);
+ if (sc->sc_flags & SC_OP_SCANNING)
+ goto set_timer;
+
/* Only calibrate if awake */
if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE)
goto set_timer;
@@ -319,6 +437,7 @@ void ath_ani_calibrate(unsigned long data)
ath9k_ps_restore(sc);
set_timer:
+ spin_unlock(&sc->ani_lock);
/*
* Set timer interval based on previous results.
* The interval must be the shortest necessary to satisfy ANI,
@@ -394,7 +513,7 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
ath_tx_node_cleanup(sc, an);
}
-void ath9k_tasklet(unsigned long data)
+static void ath9k_tasklet(unsigned long data)
{
struct ath_softc *sc = (struct ath_softc *)data;
struct ath_hw *ah = sc->sc_ah;
@@ -426,7 +545,7 @@ void ath9k_tasklet(unsigned long data)
*/
ath_print(common, ATH_DBG_PS,
"TSFOOR - Sync with next Beacon\n");
- sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC;
+ sc->sc_flags |= SC_OP_WAIT_FOR_BEACON | SC_OP_BEACON_SYNC;
}
if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
@@ -527,7 +646,7 @@ irqreturn_t ath_isr(int irq, void *dev)
* receive frames */
ath9k_setpower(sc, ATH9K_PM_AWAKE);
ath9k_hw_setrxabort(sc->sc_ah, 0);
- sc->ps_flags |= PS_WAIT_FOR_BEACON;
+ sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
}
chip_reset:
@@ -809,12 +928,49 @@ static void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf
clear_bit(key->hw_key_idx + 64, common->keymap);
if (common->splitmic) {
- ath9k_hw_keyreset(ah, key->hw_key_idx + 32);
clear_bit(key->hw_key_idx + 32, common->keymap);
clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
}
}
+static void setup_ht_cap(struct ath_softc *sc,
+ struct ieee80211_sta_ht_cap *ht_info)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ u8 tx_streams, rx_streams;
+
+ ht_info->ht_supported = true;
+ ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+ IEEE80211_HT_CAP_SM_PS |
+ IEEE80211_HT_CAP_SGI_40 |
+ IEEE80211_HT_CAP_DSSSCCK40;
+
+ ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+ ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
+
+ /* set up supported mcs set */
+ memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
+ tx_streams = !(common->tx_chainmask & (common->tx_chainmask - 1)) ?
+ 1 : 2;
+ rx_streams = !(common->rx_chainmask & (common->rx_chainmask - 1)) ?
+ 1 : 2;
+
+ if (tx_streams != rx_streams) {
+ ath_print(common, ATH_DBG_CONFIG,
+ "TX streams %d, RX streams: %d\n",
+ tx_streams, rx_streams);
+ ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
+ ht_info->mcs.tx_params |= ((tx_streams - 1) <<
+ IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
+ }
+
+ ht_info->mcs.rx_mask[0] = 0xff;
+ if (rx_streams >= 2)
+ ht_info->mcs.rx_mask[1] = 0xff;
+
+ ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
+}
+
static void ath9k_bss_assoc_info(struct ath_softc *sc,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf)
@@ -836,7 +992,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
* on the receipt of the first Beacon frame (i.e.,
* after time sync with the AP).
*/
- sc->ps_flags |= PS_BEACON_SYNC;
+ sc->sc_flags |= SC_OP_BEACON_SYNC;
/* Configure the beacon */
ath_beacon_config(sc, vif);
@@ -853,6 +1009,174 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
}
}
+/********************************/
+/* LED functions */
+/********************************/
+
+static void ath_led_blink_work(struct work_struct *work)
+{
+ struct ath_softc *sc = container_of(work, struct ath_softc,
+ ath_led_blink_work.work);
+
+ if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED))
+ return;
+
+ if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
+ (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
+ ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
+ else
+ ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin,
+ (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0);
+
+ ieee80211_queue_delayed_work(sc->hw,
+ &sc->ath_led_blink_work,
+ (sc->sc_flags & SC_OP_LED_ON) ?
+ msecs_to_jiffies(sc->led_off_duration) :
+ msecs_to_jiffies(sc->led_on_duration));
+
+ sc->led_on_duration = sc->led_on_cnt ?
+ max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) :
+ ATH_LED_ON_DURATION_IDLE;
+ sc->led_off_duration = sc->led_off_cnt ?
+ max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) :
+ ATH_LED_OFF_DURATION_IDLE;
+ sc->led_on_cnt = sc->led_off_cnt = 0;
+ if (sc->sc_flags & SC_OP_LED_ON)
+ sc->sc_flags &= ~SC_OP_LED_ON;
+ else
+ sc->sc_flags |= SC_OP_LED_ON;
+}
+
+static void ath_led_brightness(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
+ struct ath_softc *sc = led->sc;
+
+ switch (brightness) {
+ case LED_OFF:
+ if (led->led_type == ATH_LED_ASSOC ||
+ led->led_type == ATH_LED_RADIO) {
+ ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin,
+ (led->led_type == ATH_LED_RADIO));
+ sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
+ if (led->led_type == ATH_LED_RADIO)
+ sc->sc_flags &= ~SC_OP_LED_ON;
+ } else {
+ sc->led_off_cnt++;
+ }
+ break;
+ case LED_FULL:
+ if (led->led_type == ATH_LED_ASSOC) {
+ sc->sc_flags |= SC_OP_LED_ASSOCIATED;
+ ieee80211_queue_delayed_work(sc->hw,
+ &sc->ath_led_blink_work, 0);
+ } else if (led->led_type == ATH_LED_RADIO) {
+ ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
+ sc->sc_flags |= SC_OP_LED_ON;
+ } else {
+ sc->led_on_cnt++;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static int ath_register_led(struct ath_softc *sc, struct ath_led *led,
+ char *trigger)
+{
+ int ret;
+
+ led->sc = sc;
+ led->led_cdev.name = led->name;
+ led->led_cdev.default_trigger = trigger;
+ led->led_cdev.brightness_set = ath_led_brightness;
+
+ ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev);
+ if (ret)
+ ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
+ "Failed to register led:%s", led->name);
+ else
+ led->registered = 1;
+ return ret;
+}
+
+static void ath_unregister_led(struct ath_led *led)
+{
+ if (led->registered) {
+ led_classdev_unregister(&led->led_cdev);
+ led->registered = 0;
+ }
+}
+
+static void ath_deinit_leds(struct ath_softc *sc)
+{
+ ath_unregister_led(&sc->assoc_led);
+ sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
+ ath_unregister_led(&sc->tx_led);
+ ath_unregister_led(&sc->rx_led);
+ ath_unregister_led(&sc->radio_led);
+ ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
+}
+
+static void ath_init_leds(struct ath_softc *sc)
+{
+ char *trigger;
+ int ret;
+
+ if (AR_SREV_9287(sc->sc_ah))
+ sc->sc_ah->led_pin = ATH_LED_PIN_9287;
+ else
+ sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
+
+ /* Configure gpio 1 for output */
+ ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin,
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+ /* LED off, active low */
+ 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);
+
+ trigger = ieee80211_get_radio_led_name(sc->hw);
+ snprintf(sc->radio_led.name, sizeof(sc->radio_led.name),
+ "ath9k-%s::radio", wiphy_name(sc->hw->wiphy));
+ ret = ath_register_led(sc, &sc->radio_led, trigger);
+ sc->radio_led.led_type = ATH_LED_RADIO;
+ if (ret)
+ goto fail;
+
+ trigger = ieee80211_get_assoc_led_name(sc->hw);
+ snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name),
+ "ath9k-%s::assoc", wiphy_name(sc->hw->wiphy));
+ ret = ath_register_led(sc, &sc->assoc_led, trigger);
+ sc->assoc_led.led_type = ATH_LED_ASSOC;
+ if (ret)
+ goto fail;
+
+ trigger = ieee80211_get_tx_led_name(sc->hw);
+ snprintf(sc->tx_led.name, sizeof(sc->tx_led.name),
+ "ath9k-%s::tx", wiphy_name(sc->hw->wiphy));
+ ret = ath_register_led(sc, &sc->tx_led, trigger);
+ sc->tx_led.led_type = ATH_LED_TX;
+ if (ret)
+ goto fail;
+
+ trigger = ieee80211_get_rx_led_name(sc->hw);
+ snprintf(sc->rx_led.name, sizeof(sc->rx_led.name),
+ "ath9k-%s::rx", wiphy_name(sc->hw->wiphy));
+ ret = ath_register_led(sc, &sc->rx_led, trigger);
+ sc->rx_led.led_type = ATH_LED_RX;
+ if (ret)
+ goto fail;
+
+ return;
+
+fail:
+ cancel_delayed_work_sync(&sc->ath_led_blink_work);
+ ath_deinit_leds(sc);
+}
+
void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
{
struct ath_hw *ah = sc->sc_ah;
@@ -870,7 +1194,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
r = ath9k_hw_reset(ah, ah->curchan, false);
if (r) {
ath_print(common, ATH_DBG_FATAL,
- "Unable to reset channel (%u MHz), "
+ "Unable to reset channel %u (%uMhz) ",
"reset status %d\n",
channel->center_freq, r);
}
@@ -925,7 +1249,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
r = ath9k_hw_reset(ah, ah->curchan, false);
if (r) {
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
- "Unable to reset channel (%u MHz), "
+ "Unable to reset channel %u (%uMhz) "
"reset status %d\n",
channel->center_freq, r);
}
@@ -937,6 +1261,711 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
}
+/*******************/
+/* Rfkill */
+/*******************/
+
+static bool ath_is_rfkill_set(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+
+ return ath9k_hw_gpio_get(ah, ah->rfkill_gpio) ==
+ ah->rfkill_polarity;
+}
+
+static void ath9k_rfkill_poll_state(struct ieee80211_hw *hw)
+{
+ struct ath_wiphy *aphy = hw->priv;
+ struct ath_softc *sc = aphy->sc;
+ bool blocked = !!ath_is_rfkill_set(sc);
+
+ wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
+}
+
+static void ath_start_rfkill_poll(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+ wiphy_rfkill_start_polling(sc->hw->wiphy);
+}
+
+static void ath9k_uninit_hw(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+
+ BUG_ON(!ah);
+
+ ath9k_exit_debug(ah);
+ ath9k_hw_detach(ah);
+ sc->sc_ah = NULL;
+}
+
+static void ath_clean_core(struct ath_softc *sc)
+{
+ struct ieee80211_hw *hw = sc->hw;
+ struct ath_hw *ah = sc->sc_ah;
+ int i = 0;
+
+ ath9k_ps_wakeup(sc);
+
+ dev_dbg(sc->dev, "Detach ATH hw\n");
+
+ ath_deinit_leds(sc);
+ wiphy_rfkill_stop_polling(sc->hw->wiphy);
+
+ for (i = 0; i < sc->num_sec_wiphy; i++) {
+ struct ath_wiphy *aphy = sc->sec_wiphy[i];
+ if (aphy == NULL)
+ continue;
+ sc->sec_wiphy[i] = NULL;
+ ieee80211_unregister_hw(aphy->hw);
+ ieee80211_free_hw(aphy->hw);
+ }
+ ieee80211_unregister_hw(hw);
+ ath_rx_cleanup(sc);
+ ath_tx_cleanup(sc);
+
+ tasklet_kill(&sc->intr_tq);
+ tasklet_kill(&sc->bcon_tasklet);
+
+ if (!(sc->sc_flags & SC_OP_INVALID))
+ ath9k_setpower(sc, ATH9K_PM_AWAKE);
+
+ /* cleanup tx queues */
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+ if (ATH_TXQ_SETUP(sc, i))
+ ath_tx_cleanupq(sc, &sc->tx.txq[i]);
+
+ if ((sc->btcoex.no_stomp_timer) &&
+ ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
+ ath_gen_timer_free(ah, sc->btcoex.no_stomp_timer);
+}
+
+void ath_detach(struct ath_softc *sc)
+{
+ ath_clean_core(sc);
+ ath9k_uninit_hw(sc);
+}
+
+void ath_cleanup(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ ath_clean_core(sc);
+ free_irq(sc->irq, sc);
+ ath_bus_cleanup(common);
+ kfree(sc->sec_wiphy);
+ ieee80211_free_hw(sc->hw);
+
+ ath9k_uninit_hw(sc);
+}
+
+static int ath9k_reg_notifier(struct wiphy *wiphy,
+ struct regulatory_request *request)
+{
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct ath_wiphy *aphy = hw->priv;
+ struct ath_softc *sc = aphy->sc;
+ struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah);
+
+ return ath_reg_notifier_apply(wiphy, request, reg);
+}
+
+/*
+ * Detects if there is any priority bt traffic
+ */
+static void ath_detect_bt_priority(struct ath_softc *sc)
+{
+ struct ath_btcoex *btcoex = &sc->btcoex;
+ struct ath_hw *ah = sc->sc_ah;
+
+ if (ath9k_hw_gpio_get(sc->sc_ah, ah->btcoex_hw.btpriority_gpio))
+ btcoex->bt_priority_cnt++;
+
+ if (time_after(jiffies, btcoex->bt_priority_time +
+ msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
+ if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
+ ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX,
+ "BT priority traffic detected");
+ sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED;
+ } else {
+ sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
+ }
+
+ btcoex->bt_priority_cnt = 0;
+ btcoex->bt_priority_time = jiffies;
+ }
+}
+
+/*
+ * Configures appropriate weight based on stomp type.
+ */
+static void ath9k_btcoex_bt_stomp(struct ath_softc *sc,
+ enum ath_stomp_type stomp_type)
+{
+ struct ath_hw *ah = sc->sc_ah;
+
+ switch (stomp_type) {
+ case ATH_BTCOEX_STOMP_ALL:
+ ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+ AR_STOMP_ALL_WLAN_WGHT);
+ break;
+ case ATH_BTCOEX_STOMP_LOW:
+ ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+ AR_STOMP_LOW_WLAN_WGHT);
+ break;
+ case ATH_BTCOEX_STOMP_NONE:
+ ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+ AR_STOMP_NONE_WLAN_WGHT);
+ break;
+ default:
+ ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
+ "Invalid Stomptype\n");
+ break;
+ }
+
+ ath9k_hw_btcoex_enable(ah);
+}
+
+static void ath9k_gen_timer_start(struct ath_hw *ah,
+ struct ath_gen_timer *timer,
+ u32 timer_next,
+ u32 timer_period)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath_softc *sc = (struct ath_softc *) common->priv;
+
+ ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period);
+
+ if ((sc->imask & ATH9K_INT_GENTIMER) == 0) {
+ ath9k_hw_set_interrupts(ah, 0);
+ sc->imask |= ATH9K_INT_GENTIMER;
+ ath9k_hw_set_interrupts(ah, sc->imask);
+ }
+}
+
+static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath_softc *sc = (struct ath_softc *) common->priv;
+ struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
+
+ ath9k_hw_gen_timer_stop(ah, timer);
+
+ /* if no timer is enabled, turn off interrupt mask */
+ if (timer_table->timer_mask.val == 0) {
+ ath9k_hw_set_interrupts(ah, 0);
+ sc->imask &= ~ATH9K_INT_GENTIMER;
+ ath9k_hw_set_interrupts(ah, sc->imask);
+ }
+}
+
+/*
+ * This is the master bt coex timer which runs for every
+ * 45ms, bt traffic will be given priority during 55% of this
+ * period while wlan gets remaining 45%
+ */
+static void ath_btcoex_period_timer(unsigned long data)
+{
+ struct ath_softc *sc = (struct ath_softc *) data;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_btcoex *btcoex = &sc->btcoex;
+
+ ath_detect_bt_priority(sc);
+
+ spin_lock_bh(&btcoex->btcoex_lock);
+
+ ath9k_btcoex_bt_stomp(sc, btcoex->bt_stomp_type);
+
+ spin_unlock_bh(&btcoex->btcoex_lock);
+
+ if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) {
+ if (btcoex->hw_timer_enabled)
+ ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
+
+ ath9k_gen_timer_start(ah,
+ btcoex->no_stomp_timer,
+ (ath9k_hw_gettsf32(ah) +
+ btcoex->btcoex_no_stomp),
+ btcoex->btcoex_no_stomp * 10);
+ btcoex->hw_timer_enabled = true;
+ }
+
+ mod_timer(&btcoex->period_timer, jiffies +
+ msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD));
+}
+
+/*
+ * Generic tsf based hw timer which configures weight
+ * registers to time slice between wlan and bt traffic
+ */
+static void ath_btcoex_no_stomp_timer(void *arg)
+{
+ struct ath_softc *sc = (struct ath_softc *)arg;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_btcoex *btcoex = &sc->btcoex;
+
+ ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
+ "no stomp timer running \n");
+
+ spin_lock_bh(&btcoex->btcoex_lock);
+
+ if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW)
+ ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE);
+ else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
+ ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW);
+
+ spin_unlock_bh(&btcoex->btcoex_lock);
+}
+
+static int ath_init_btcoex_timer(struct ath_softc *sc)
+{
+ struct ath_btcoex *btcoex = &sc->btcoex;
+
+ btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000;
+ btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
+ btcoex->btcoex_period / 100;
+
+ setup_timer(&btcoex->period_timer, ath_btcoex_period_timer,
+ (unsigned long) sc);
+
+ spin_lock_init(&btcoex->btcoex_lock);
+
+ btcoex->no_stomp_timer = ath_gen_timer_alloc(sc->sc_ah,
+ ath_btcoex_no_stomp_timer,
+ ath_btcoex_no_stomp_timer,
+ (void *) sc, AR_FIRST_NDP_TIMER);
+
+ if (!btcoex->no_stomp_timer)
+ return -ENOMEM;
+
+ return 0;
+}
+
+/*
+ * Read and write, they both share the same lock. We do this to serialize
+ * reads and writes on Atheros 802.11n PCI devices only. This is required
+ * as the FIFO on these devices can only accept sanely 2 requests. After
+ * that the device goes bananas. Serializing the reads/writes prevents this
+ * from happening.
+ */
+
+static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)
+{
+ struct ath_hw *ah = (struct ath_hw *) hw_priv;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath_softc *sc = (struct ath_softc *) common->priv;
+
+ if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
+ unsigned long flags;
+ spin_lock_irqsave(&sc->sc_serial_rw, flags);
+ iowrite32(val, sc->mem + reg_offset);
+ spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
+ } else
+ iowrite32(val, sc->mem + reg_offset);
+}
+
+static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
+{
+ struct ath_hw *ah = (struct ath_hw *) hw_priv;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath_softc *sc = (struct ath_softc *) common->priv;
+ u32 val;
+
+ if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
+ unsigned long flags;
+ spin_lock_irqsave(&sc->sc_serial_rw, flags);
+ val = ioread32(sc->mem + reg_offset);
+ spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
+ } else
+ val = ioread32(sc->mem + reg_offset);
+ return val;
+}
+
+static const struct ath_ops ath9k_common_ops = {
+ .read = ath9k_ioread32,
+ .write = ath9k_iowrite32,
+};
+
+/*
+ * Initialize and fill ath_softc, ath_sofct is the
+ * "Software Carrier" struct. Historically it has existed
+ * to allow the separation between hardware specific
+ * variables (now in ath_hw) and driver specific variables.
+ */
+static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
+ const struct ath_bus_ops *bus_ops)
+{
+ struct ath_hw *ah = NULL;
+ struct ath_common *common;
+ int r = 0, i;
+ int csz = 0;
+ int qnum;
+
+ /* XXX: hardware will not be ready until ath_open() being called */
+ sc->sc_flags |= SC_OP_INVALID;
+
+ spin_lock_init(&sc->wiphy_lock);
+ spin_lock_init(&sc->sc_resetlock);
+ spin_lock_init(&sc->sc_serial_rw);
+ spin_lock_init(&sc->ani_lock);
+ spin_lock_init(&sc->sc_pm_lock);
+ mutex_init(&sc->mutex);
+ tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
+ tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
+ (unsigned long)sc);
+
+ ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
+ if (!ah)
+ return -ENOMEM;
+
+ ah->hw_version.devid = devid;
+ ah->hw_version.subsysid = subsysid;
+ sc->sc_ah = ah;
+
+ common = ath9k_hw_common(ah);
+ common->ops = &ath9k_common_ops;
+ common->bus_ops = bus_ops;
+ common->ah = ah;
+ common->hw = sc->hw;
+ common->priv = sc;
+ common->debug_mask = ath9k_debug;
+
+ /*
+ * Cache line size is used to size and align various
+ * structures used to communicate with the hardware.
+ */
+ ath_read_cachesize(common, &csz);
+ /* XXX assert csz is non-zero */
+ common->cachelsz = csz << 2; /* convert to bytes */
+
+ r = ath9k_hw_init(ah);
+ if (r) {
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to initialize hardware; "
+ "initialization status: %d\n", r);
+ goto bad_free_hw;
+ }
+
+ if (ath9k_init_debug(ah) < 0) {
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to create debugfs files\n");
+ goto bad_free_hw;
+ }
+
+ /* Get the hardware key cache size. */
+ common->keymax = ah->caps.keycache_size;
+ if (common->keymax > ATH_KEYMAX) {
+ ath_print(common, ATH_DBG_ANY,
+ "Warning, using only %u entries in %u key cache\n",
+ ATH_KEYMAX, common->keymax);
+ common->keymax = ATH_KEYMAX;
+ }
+
+ /*
+ * Reset the key cache since some parts do not
+ * reset the contents on initial power up.
+ */
+ for (i = 0; i < common->keymax; i++)
+ ath9k_hw_keyreset(ah, (u16) i);
+
+ /* default to MONITOR mode */
+ sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR;
+
+ /*
+ * Allocate hardware transmit queues: one queue for
+ * beacon frames and one data queue for each QoS
+ * priority. Note that the hal handles reseting
+ * these queues at the needed time.
+ */
+ sc->beacon.beaconq = ath9k_hw_beaconq_setup(ah);
+ if (sc->beacon.beaconq == -1) {
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to setup a beacon xmit queue\n");
+ r = -EIO;
+ goto bad2;
+ }
+ sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
+ if (sc->beacon.cabq == NULL) {
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to setup CAB xmit queue\n");
+ r = -EIO;
+ goto bad2;
+ }
+
+ sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
+ ath_cabq_update(sc);
+
+ for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++)
+ sc->tx.hwq_map[i] = -1;
+
+ /* Setup data queues */
+ /* NB: ensure BK queue is the lowest priority h/w queue */
+ if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) {
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to setup xmit queue for BK traffic\n");
+ r = -EIO;
+ goto bad2;
+ }
+
+ if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) {
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to setup xmit queue for BE traffic\n");
+ r = -EIO;
+ goto bad2;
+ }
+ if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) {
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to setup xmit queue for VI traffic\n");
+ r = -EIO;
+ goto bad2;
+ }
+ if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) {
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to setup xmit queue for VO traffic\n");
+ r = -EIO;
+ goto bad2;
+ }
+
+ /* Initializes the noise floor to a reasonable default value.
+ * Later on this will be updated during ANI processing. */
+
+ common->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR;
+ setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
+
+ if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+ ATH9K_CIPHER_TKIP, NULL)) {
+ /*
+ * Whether we should enable h/w TKIP MIC.
+ * XXX: if we don't support WME TKIP MIC, then we wouldn't
+ * report WMM capable, so it's always safe to turn on
+ * TKIP MIC in this case.
+ */
+ ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC,
+ 0, 1, NULL);
+ }
+
+ /*
+ * Check whether the separate key cache entries
+ * are required to handle both tx+rx MIC keys.
+ * With split mic keys the number of stations is limited
+ * to 27 otherwise 59.
+ */
+ if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+ ATH9K_CIPHER_TKIP, NULL)
+ && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+ ATH9K_CIPHER_MIC, NULL)
+ && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT,
+ 0, NULL))
+ common->splitmic = 1;
+
+ /* turn on mcast key search if possible */
+ if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL))
+ (void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1,
+ 1, NULL);
+
+ sc->config.txpowlimit = ATH_TXPOWER_MAX;
+
+ /* 11n Capabilities */
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
+ sc->sc_flags |= SC_OP_TXAGGR;
+ sc->sc_flags |= SC_OP_RXAGGR;
+ }
+
+ common->tx_chainmask = ah->caps.tx_chainmask;
+ common->rx_chainmask = ah->caps.rx_chainmask;
+
+ ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL);
+ sc->rx.defant = ath9k_hw_getdefantenna(ah);
+
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
+ memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
+
+ sc->beacon.slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */
+
+ /* initialize beacon slots */
+ for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
+ sc->beacon.bslot[i] = NULL;
+ sc->beacon.bslot_aphy[i] = NULL;
+ }
+
+ /* setup channels and rates */
+
+ if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) {
+ sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable;
+ sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
+ sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
+ ARRAY_SIZE(ath9k_2ghz_chantable);
+ sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates;
+ sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
+ ARRAY_SIZE(ath9k_legacy_rates);
+ }
+
+ if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) {
+ sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable;
+ sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
+ sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
+ ARRAY_SIZE(ath9k_5ghz_chantable);
+ sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
+ ath9k_legacy_rates + 4;
+ sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
+ ARRAY_SIZE(ath9k_legacy_rates) - 4;
+ }
+
+ switch (ah->btcoex_hw.scheme) {
+ case ATH_BTCOEX_CFG_NONE:
+ break;
+ case ATH_BTCOEX_CFG_2WIRE:
+ ath9k_hw_btcoex_init_2wire(ah);
+ break;
+ case ATH_BTCOEX_CFG_3WIRE:
+ ath9k_hw_btcoex_init_3wire(ah);
+ r = ath_init_btcoex_timer(sc);
+ if (r)
+ goto bad2;
+ qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE);
+ ath9k_hw_init_btcoex_hw(ah, qnum);
+ sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
+ break;
+ default:
+ WARN_ON(1);
+ break;
+ }
+
+ return 0;
+bad2:
+ /* cleanup tx queues */
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+ if (ATH_TXQ_SETUP(sc, i))
+ ath_tx_cleanupq(sc, &sc->tx.txq[i]);
+
+bad_free_hw:
+ ath9k_uninit_hw(sc);
+ return r;
+}
+
+void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
+{
+ hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ IEEE80211_HW_SIGNAL_DBM |
+ IEEE80211_HW_AMPDU_AGGREGATION |
+ IEEE80211_HW_SUPPORTS_PS |
+ IEEE80211_HW_PS_NULLFUNC_STACK |
+ IEEE80211_HW_SPECTRUM_MGMT;
+
+ if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt)
+ hw->flags |= IEEE80211_HW_MFP_CAPABLE;
+
+ hw->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_MESH_POINT);
+
+ hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
+ hw->queues = 4;
+ hw->max_rates = 4;
+ hw->channel_change_time = 5000;
+ hw->max_listen_interval = 10;
+ /* Hardware supports 10 but we use 4 */
+ hw->max_rate_tries = 4;
+ hw->sta_data_size = sizeof(struct ath_node);
+ hw->vif_data_size = sizeof(struct ath_vif);
+
+ hw->rate_control_algorithm = "ath9k_rate_control";
+
+ if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes))
+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+ &sc->sbands[IEEE80211_BAND_2GHZ];
+ if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
+ hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+ &sc->sbands[IEEE80211_BAND_5GHZ];
+}
+
+/* Device driver core initialization */
+int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
+ const struct ath_bus_ops *bus_ops)
+{
+ struct ieee80211_hw *hw = sc->hw;
+ struct ath_common *common;
+ struct ath_hw *ah;
+ int error = 0, i;
+ struct ath_regulatory *reg;
+
+ dev_dbg(sc->dev, "Attach ATH hw\n");
+
+ error = ath_init_softc(devid, sc, subsysid, bus_ops);
+ if (error != 0)
+ return error;
+
+ ah = sc->sc_ah;
+ common = ath9k_hw_common(ah);
+
+ /* get mac address from hardware and set in mac80211 */
+
+ SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
+
+ ath_set_hw_capab(sc, hw);
+
+ error = ath_regd_init(&common->regulatory, sc->hw->wiphy,
+ ath9k_reg_notifier);
+ if (error)
+ return error;
+
+ reg = &common->regulatory;
+
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
+ if (test_bit(ATH9K_MODE_11G, ah->caps.wireless_modes))
+ setup_ht_cap(sc,
+ &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
+ if (test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes))
+ setup_ht_cap(sc,
+ &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
+ }
+
+ /* initialize tx/rx engine */
+ error = ath_tx_init(sc, ATH_TXBUF);
+ if (error != 0)
+ goto error_attach;
+
+ error = ath_rx_init(sc, ATH_RXBUF);
+ if (error != 0)
+ goto error_attach;
+
+ INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
+ INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
+ sc->wiphy_scheduler_int = msecs_to_jiffies(500);
+
+ error = ieee80211_register_hw(hw);
+
+ if (!ath_is_world_regd(reg)) {
+ error = regulatory_hint(hw->wiphy, reg->alpha2);
+ if (error)
+ goto error_attach;
+ }
+
+ /* Initialize LED control */
+ ath_init_leds(sc);
+
+ ath_start_rfkill_poll(sc);
+
+ return 0;
+
+error_attach:
+ /* cleanup tx queues */
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+ if (ATH_TXQ_SETUP(sc, i))
+ ath_tx_cleanupq(sc, &sc->tx.txq[i]);
+
+ ath9k_uninit_hw(sc);
+
+ return error;
+}
+
int ath_reset(struct ath_softc *sc, bool retry_tx)
{
struct ath_hw *ah = sc->sc_ah;
@@ -947,8 +1976,6 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
/* Stop ANI */
del_timer_sync(&common->ani.timer);
- ieee80211_stop_queues(hw);
-
ath9k_hw_set_interrupts(ah, 0);
ath_drain_all_txq(sc, retry_tx);
ath_stoprecv(sc);
@@ -990,14 +2017,131 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
}
}
- ieee80211_wake_queues(hw);
-
/* Start ANI */
ath_start_ani(common);
return r;
}
+/*
+ * This function will allocate both the DMA descriptor structure, and the
+ * buffers it contains. These are used to contain the descriptors used
+ * by the system.
+*/
+int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
+ struct list_head *head, const char *name,
+ int nbuf, int ndesc)
+{
+#define DS2PHYS(_dd, _ds) \
+ ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
+#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
+#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_desc *ds;
+ struct ath_buf *bf;
+ int i, bsize, error;
+
+ ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n",
+ name, nbuf, ndesc);
+
+ INIT_LIST_HEAD(head);
+ /* ath_desc must be a multiple of DWORDs */
+ if ((sizeof(struct ath_desc) % 4) != 0) {
+ ath_print(common, ATH_DBG_FATAL,
+ "ath_desc not DWORD aligned\n");
+ BUG_ON((sizeof(struct ath_desc) % 4) != 0);
+ error = -ENOMEM;
+ goto fail;
+ }
+
+ dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc;
+
+ /*
+ * Need additional DMA memory because we can't use
+ * descriptors that cross the 4K page boundary. Assume
+ * one skipped descriptor per 4K page.
+ */
+ if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
+ u32 ndesc_skipped =
+ ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len);
+ u32 dma_len;
+
+ while (ndesc_skipped) {
+ dma_len = ndesc_skipped * sizeof(struct ath_desc);
+ dd->dd_desc_len += dma_len;
+
+ ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len);
+ };
+ }
+
+ /* allocate descriptors */
+ dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len,
+ &dd->dd_desc_paddr, GFP_KERNEL);
+ if (dd->dd_desc == NULL) {
+ error = -ENOMEM;
+ goto fail;
+ }
+ ds = dd->dd_desc;
+ ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
+ name, ds, (u32) dd->dd_desc_len,
+ ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
+
+ /* allocate buffers */
+ bsize = sizeof(struct ath_buf) * nbuf;
+ bf = kzalloc(bsize, GFP_KERNEL);
+ if (bf == NULL) {
+ error = -ENOMEM;
+ goto fail2;
+ }
+ dd->dd_bufptr = bf;
+
+ for (i = 0; i < nbuf; i++, bf++, ds += ndesc) {
+ bf->bf_desc = ds;
+ bf->bf_daddr = DS2PHYS(dd, ds);
+
+ if (!(sc->sc_ah->caps.hw_caps &
+ ATH9K_HW_CAP_4KB_SPLITTRANS)) {
+ /*
+ * Skip descriptor addresses which can cause 4KB
+ * boundary crossing (addr + length) with a 32 dword
+ * descriptor fetch.
+ */
+ while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
+ BUG_ON((caddr_t) bf->bf_desc >=
+ ((caddr_t) dd->dd_desc +
+ dd->dd_desc_len));
+
+ ds += ndesc;
+ bf->bf_desc = ds;
+ bf->bf_daddr = DS2PHYS(dd, ds);
+ }
+ }
+ list_add_tail(&bf->list, head);
+ }
+ return 0;
+fail2:
+ dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
+ dd->dd_desc_paddr);
+fail:
+ memset(dd, 0, sizeof(*dd));
+ return error;
+#undef ATH_DESC_4KB_BOUND_CHECK
+#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED
+#undef DS2PHYS
+}
+
+void ath_descdma_cleanup(struct ath_softc *sc,
+ struct ath_descdma *dd,
+ struct list_head *head)
+{
+ dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
+ dd->dd_desc_paddr);
+
+ INIT_LIST_HEAD(head);
+ kfree(dd->dd_bufptr);
+ memset(dd, 0, sizeof(*dd));
+}
+
int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
{
int qnum;
@@ -1076,6 +2220,28 @@ void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
/* mac80211 callbacks */
/**********************/
+/*
+ * (Re)start btcoex timers
+ */
+static void ath9k_btcoex_timer_resume(struct ath_softc *sc)
+{
+ struct ath_btcoex *btcoex = &sc->btcoex;
+ struct ath_hw *ah = sc->sc_ah;
+
+ ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
+ "Starting btcoex timers");
+
+ /* make sure duty cycle timer is also stopped when resuming */
+ if (btcoex->hw_timer_enabled)
+ ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
+
+ btcoex->bt_priority_cnt = 0;
+ btcoex->bt_priority_time = jiffies;
+ sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
+
+ mod_timer(&btcoex->period_timer, jiffies);
+}
+
static int ath9k_start(struct ieee80211_hw *hw)
{
struct ath_wiphy *aphy = hw->priv;
@@ -1245,11 +2411,11 @@ static int ath9k_tx(struct ieee80211_hw *hw,
if (ieee80211_is_pspoll(hdr->frame_control)) {
ath_print(common, ATH_DBG_PS,
"Sending PS-Poll to pick a buffered frame\n");
- sc->ps_flags |= PS_WAIT_FOR_PSPOLL_DATA;
+ sc->sc_flags |= SC_OP_WAIT_FOR_PSPOLL_DATA;
} else {
ath_print(common, ATH_DBG_PS,
"Wake up to complete TX\n");
- sc->ps_flags |= PS_WAIT_FOR_TX_ACK;
+ sc->sc_flags |= SC_OP_WAIT_FOR_TX_ACK;
}
/*
* The actual restore operation will happen only after
@@ -1302,6 +2468,22 @@ static int ath9k_tx(struct ieee80211_hw *hw,
return 0;
}
+/*
+ * Pause btcoex timer and bt duty cycle timer
+ */
+static void ath9k_btcoex_timer_pause(struct ath_softc *sc)
+{
+ struct ath_btcoex *btcoex = &sc->btcoex;
+ struct ath_hw *ah = sc->sc_ah;
+
+ del_timer_sync(&btcoex->period_timer);
+
+ if (btcoex->hw_timer_enabled)
+ ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
+
+ btcoex->hw_timer_enabled = false;
+}
+
static void ath9k_stop(struct ieee80211_hw *hw)
{
struct ath_wiphy *aphy = hw->priv;
@@ -1368,12 +2550,12 @@ static void ath9k_stop(struct ieee80211_hw *hw)
}
static int ath9k_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath_vif *avp = (void *)vif->drv_priv;
+ struct ath_vif *avp = (void *)conf->vif->drv_priv;
enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED;
int ret = 0;
@@ -1385,7 +2567,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
goto out;
}
- switch (vif->type) {
+ switch (conf->type) {
case NL80211_IFTYPE_STATION:
ic_opmode = NL80211_IFTYPE_STATION;
break;
@@ -1396,11 +2578,11 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
ret = -ENOBUFS;
goto out;
}
- ic_opmode = vif->type;
+ ic_opmode = conf->type;
break;
default:
ath_print(common, ATH_DBG_FATAL,
- "Interface type %d not yet supported\n", vif->type);
+ "Interface type %d not yet supported\n", conf->type);
ret = -EOPNOTSUPP;
goto out;
}
@@ -1432,18 +2614,18 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
* Enable MIB interrupts when there are hardware phy counters.
* Note we only do this (at the moment) for station mode.
*/
- if ((vif->type == NL80211_IFTYPE_STATION) ||
- (vif->type == NL80211_IFTYPE_ADHOC) ||
- (vif->type == NL80211_IFTYPE_MESH_POINT)) {
+ if ((conf->type == NL80211_IFTYPE_STATION) ||
+ (conf->type == NL80211_IFTYPE_ADHOC) ||
+ (conf->type == NL80211_IFTYPE_MESH_POINT)) {
sc->imask |= ATH9K_INT_MIB;
sc->imask |= ATH9K_INT_TSFOOR;
}
ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
- if (vif->type == NL80211_IFTYPE_AP ||
- vif->type == NL80211_IFTYPE_ADHOC ||
- vif->type == NL80211_IFTYPE_MONITOR)
+ if (conf->type == NL80211_IFTYPE_AP ||
+ conf->type == NL80211_IFTYPE_ADHOC ||
+ conf->type == NL80211_IFTYPE_MONITOR)
ath_start_ani(common);
out:
@@ -1452,12 +2634,12 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
}
static void ath9k_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath_vif *avp = (void *)vif->drv_priv;
+ struct ath_vif *avp = (void *)conf->vif->drv_priv;
int i;
ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n");
@@ -1480,7 +2662,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
sc->sc_flags &= ~SC_OP_BEACONS;
for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
- if (sc->beacon.bslot[i] == vif) {
+ if (sc->beacon.bslot[i] == conf->vif) {
printk(KERN_DEBUG "%s: vif had allocated beacon "
"slot\n", __func__);
sc->beacon.bslot[i] = NULL;
@@ -1493,19 +2675,6 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&sc->mutex);
}
-void ath9k_enable_ps(struct ath_softc *sc)
-{
- sc->ps_enabled = true;
- if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
- if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) {
- sc->imask |= ATH9K_INT_TIM_TIMER;
- ath9k_hw_set_interrupts(sc->sc_ah,
- sc->imask);
- }
- }
- ath9k_hw_setrxabort(sc->sc_ah, 1);
-}
-
static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
{
struct ath_wiphy *aphy = hw->priv;
@@ -1544,7 +2713,6 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
spin_unlock_bh(&sc->wiphy_lock);
if (enable_radio) {
- sc->ps_idle = false;
ath_radio_enable(sc, hw);
ath_print(common, ATH_DBG_CONFIG,
"not-idle: enabling radio\n");
@@ -1559,27 +2727,36 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
*/
if (changed & IEEE80211_CONF_CHANGE_PS) {
if (conf->flags & IEEE80211_CONF_PS) {
- sc->ps_flags |= PS_ENABLED;
+ sc->sc_flags |= SC_OP_PS_ENABLED;
+ if (!(ah->caps.hw_caps &
+ ATH9K_HW_CAP_AUTOSLEEP)) {
+ if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) {
+ sc->imask |= ATH9K_INT_TIM_TIMER;
+ ath9k_hw_set_interrupts(sc->sc_ah,
+ sc->imask);
+ }
+ }
/*
* At this point we know hardware has received an ACK
* of a previously sent null data frame.
*/
- if ((sc->ps_flags & PS_NULLFUNC_COMPLETED)) {
- sc->ps_flags &= ~PS_NULLFUNC_COMPLETED;
- ath9k_enable_ps(sc);
+ if ((sc->sc_flags & SC_OP_NULLFUNC_COMPLETED)) {
+ sc->sc_flags &= ~SC_OP_NULLFUNC_COMPLETED;
+ sc->ps_enabled = true;
+ ath9k_hw_setrxabort(sc->sc_ah, 1);
}
} else {
sc->ps_enabled = false;
- sc->ps_flags &= ~(PS_ENABLED |
- PS_NULLFUNC_COMPLETED);
+ sc->sc_flags &= ~(SC_OP_PS_ENABLED |
+ SC_OP_NULLFUNC_COMPLETED);
ath9k_setpower(sc, ATH9K_PM_AWAKE);
if (!(ah->caps.hw_caps &
ATH9K_HW_CAP_AUTOSLEEP)) {
ath9k_hw_setrxabort(sc->sc_ah, 0);
- sc->ps_flags &= ~(PS_WAIT_FOR_BEACON |
- PS_WAIT_FOR_CAB |
- PS_WAIT_FOR_PSPOLL_DATA |
- PS_WAIT_FOR_TX_ACK);
+ sc->sc_flags &= ~(SC_OP_WAIT_FOR_BEACON |
+ SC_OP_WAIT_FOR_CAB |
+ SC_OP_WAIT_FOR_PSPOLL_DATA |
+ SC_OP_WAIT_FOR_TX_ACK);
if (sc->imask & ATH9K_INT_TIM_TIMER) {
sc->imask &= ~ATH9K_INT_TIM_TIMER;
ath9k_hw_set_interrupts(sc->sc_ah,
@@ -1589,14 +2766,6 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
}
}
- if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
- if (conf->flags & IEEE80211_CONF_MONITOR) {
- ath_print(common, ATH_DBG_CONFIG,
- "HW opmode set to Monitor mode\n");
- sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR;
- }
- }
-
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
struct ieee80211_channel *curchan = hw->conf.channel;
int pos = curchan->hw_value;
@@ -1632,10 +2801,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
}
skip_chan_change:
- if (changed & IEEE80211_CONF_CHANGE_POWER) {
+ if (changed & IEEE80211_CONF_CHANGE_POWER)
sc->config.txpowlimit = 2 * conf->power_level;
- ath_update_txpow(sc);
- }
spin_lock_bh(&sc->wiphy_lock);
disable_radio = ath9k_all_wiphys_idle(sc);
@@ -1643,7 +2810,6 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
if (disable_radio) {
ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n");
- sc->ps_idle = true;
ath_radio_disable(sc, hw);
}
@@ -1684,28 +2850,24 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
"Set HW RX filter: 0x%x\n", rfilt);
}
-static int ath9k_sta_add(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+static void ath9k_sta_notify(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ enum sta_notify_cmd cmd,
+ struct ieee80211_sta *sta)
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
- ath_node_attach(sc, sta);
-
- return 0;
-}
-
-static int ath9k_sta_remove(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
-{
- struct ath_wiphy *aphy = hw->priv;
- struct ath_softc *sc = aphy->sc;
-
- ath_node_detach(sc, sta);
-
- return 0;
+ switch (cmd) {
+ case STA_NOTIFY_ADD:
+ ath_node_attach(sc, sta);
+ break;
+ case STA_NOTIFY_REMOVE:
+ ath_node_detach(sc, sta);
+ break;
+ default:
+ break;
+ }
}
static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
@@ -1804,7 +2966,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ath_vif *avp = (void *)vif->drv_priv;
- int slottime;
int error;
mutex_lock(&sc->mutex);
@@ -1840,25 +3001,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
ath_beacon_config(sc, vif);
}
- if (changed & BSS_CHANGED_ERP_SLOT) {
- if (bss_conf->use_short_slot)
- slottime = 9;
- else
- slottime = 20;
- if (vif->type == NL80211_IFTYPE_AP) {
- /*
- * Defer update, so that connected stations can adjust
- * their settings at the same time.
- * See beacon.c for more details
- */
- sc->beacon.slottime = slottime;
- sc->beacon.updateslot = UPDATE;
- } else {
- ah->slottime = slottime;
- ath9k_hw_init_global_settings(ah);
- }
- }
-
/* Disable transmission of beacons */
if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon)
ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
@@ -1991,7 +3133,6 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
mutex_lock(&sc->mutex);
if (ath9k_wiphy_scanning(sc)) {
@@ -2007,9 +3148,10 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
aphy->state = ATH_WIPHY_SCAN;
ath9k_wiphy_pause_all_forced(sc, aphy);
+
+ spin_lock_bh(&sc->ani_lock);
sc->sc_flags |= SC_OP_SCANNING;
- del_timer_sync(&common->ani.timer);
- cancel_delayed_work_sync(&sc->tx_complete_work);
+ spin_unlock_bh(&sc->ani_lock);
mutex_unlock(&sc->mutex);
}
@@ -2017,30 +3159,17 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
mutex_lock(&sc->mutex);
+ spin_lock_bh(&sc->ani_lock);
aphy->state = ATH_WIPHY_ACTIVE;
sc->sc_flags &= ~SC_OP_SCANNING;
sc->sc_flags |= SC_OP_FULL_RESET;
- ath_start_ani(common);
- ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+ spin_unlock_bh(&sc->ani_lock);
ath_beacon_config(sc, NULL);
mutex_unlock(&sc->mutex);
}
-static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
-{
- struct ath_wiphy *aphy = hw->priv;
- struct ath_softc *sc = aphy->sc;
- struct ath_hw *ah = sc->sc_ah;
-
- mutex_lock(&sc->mutex);
- ah->coverage_class = coverage_class;
- ath9k_hw_init_global_settings(ah);
- mutex_unlock(&sc->mutex);
-}
-
struct ieee80211_ops ath9k_ops = {
.tx = ath9k_tx,
.start = ath9k_start,
@@ -2049,8 +3178,7 @@ struct ieee80211_ops ath9k_ops = {
.remove_interface = ath9k_remove_interface,
.config = ath9k_config,
.configure_filter = ath9k_configure_filter,
- .sta_add = ath9k_sta_add,
- .sta_remove = ath9k_sta_remove,
+ .sta_notify = ath9k_sta_notify,
.conf_tx = ath9k_conf_tx,
.bss_info_changed = ath9k_bss_info_changed,
.set_key = ath9k_set_key,
@@ -2061,5 +3189,64 @@ struct ieee80211_ops ath9k_ops = {
.sw_scan_start = ath9k_sw_scan_start,
.sw_scan_complete = ath9k_sw_scan_complete,
.rfkill_poll = ath9k_rfkill_poll_state,
- .set_coverage_class = ath9k_set_coverage_class,
};
+
+static int __init ath9k_init(void)
+{
+ int error;
+
+ /* Register rate control algorithm */
+ error = ath_rate_control_register();
+ if (error != 0) {
+ printk(KERN_ERR
+ "ath9k: Unable to register rate control "
+ "algorithm: %d\n",
+ error);
+ goto err_out;
+ }
+
+ error = ath9k_debug_create_root();
+ if (error) {
+ printk(KERN_ERR
+ "ath9k: Unable to create debugfs root: %d\n",
+ error);
+ goto err_rate_unregister;
+ }
+
+ error = ath_pci_init();
+ if (error < 0) {
+ printk(KERN_ERR
+ "ath9k: No PCI devices found, driver not installed.\n");
+ error = -ENODEV;
+ goto err_remove_root;
+ }
+
+ error = ath_ahb_init();
+ if (error < 0) {
+ error = -ENODEV;
+ goto err_pci_exit;
+ }
+
+ return 0;
+
+ err_pci_exit:
+ ath_pci_exit();
+
+ err_remove_root:
+ ath9k_debug_remove_root();
+ err_rate_unregister:
+ ath_rate_control_unregister();
+ err_out:
+ return error;
+}
+module_init(ath9k_init);
+
+static void __exit ath9k_exit(void)
+{
+ ath_ahb_exit();
+ ath_pci_exit();
+ ath9k_debug_remove_root();
+ ath_rate_control_unregister();
+ printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
+}
+module_exit(ath9k_exit);
diff --git a/trunk/drivers/net/wireless/ath/ath9k/pci.c b/trunk/drivers/net/wireless/ath/ath9k/pci.c
index f318b3b1abe9..f7af5ea54753 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/pci.c
+++ b/trunk/drivers/net/wireless/ath/ath9k/pci.c
@@ -25,7 +25,6 @@ static struct pci_device_id ath_pci_id_table[] __devinitdata = {
{ PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
{ PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
- { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */
{ PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */
{ 0 }
@@ -50,6 +49,16 @@ static void ath_pci_read_cachesize(struct ath_common *common, int *csz)
*csz = DEFAULT_CACHELINE >> 2; /* Use the default size */
}
+static void ath_pci_cleanup(struct ath_common *common)
+{
+ struct ath_softc *sc = (struct ath_softc *) common->priv;
+ struct pci_dev *pdev = to_pci_dev(sc->dev);
+
+ pci_iounmap(pdev, sc->mem);
+ pci_disable_device(pdev);
+ pci_release_region(pdev, 0);
+}
+
static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
{
struct ath_hw *ah = (struct ath_hw *) common->ah;
@@ -89,6 +98,7 @@ static void ath_pci_bt_coex_prep(struct ath_common *common)
static const struct ath_bus_ops ath_pci_bus_ops = {
.read_cachesize = ath_pci_read_cachesize,
+ .cleanup = ath_pci_cleanup,
.eeprom_read = ath_pci_eeprom_read,
.bt_coex_prep = ath_pci_bt_coex_prep,
};
@@ -103,22 +113,25 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
u16 subsysid;
u32 val;
int ret = 0;
+ struct ath_hw *ah;
char hw_name[64];
if (pci_enable_device(pdev))
return -EIO;
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+
if (ret) {
printk(KERN_ERR "ath9k: 32-bit DMA not available\n");
- goto err_dma;
+ goto bad;
}
ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+
if (ret) {
printk(KERN_ERR "ath9k: 32-bit DMA consistent "
"DMA enable failed\n");
- goto err_dma;
+ goto bad;
}
/*
@@ -158,22 +171,22 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret) {
dev_err(&pdev->dev, "PCI memory region reserve error\n");
ret = -ENODEV;
- goto err_region;
+ goto bad;
}
mem = pci_iomap(pdev, 0, 0);
if (!mem) {
printk(KERN_ERR "PCI memory map error\n") ;
ret = -EIO;
- goto err_iomap;
+ goto bad1;
}
hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) +
sizeof(struct ath_softc), &ath9k_ops);
if (!hw) {
- dev_err(&pdev->dev, "No memory for ieee80211_hw\n");
+ dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
ret = -ENOMEM;
- goto err_alloc_hw;
+ goto bad2;
}
SET_IEEE80211_DEV(hw, &pdev->dev);
@@ -188,25 +201,25 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sc->dev = &pdev->dev;
sc->mem = mem;
- /* Will be cleared in ath9k_start() */
- sc->sc_flags |= SC_OP_INVALID;
+ pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid);
+ ret = ath_init_device(id->device, sc, subsysid, &ath_pci_bus_ops);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to initialize device\n");
+ goto bad3;
+ }
+
+ /* setup interrupt service routine */
ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc);
if (ret) {
dev_err(&pdev->dev, "request_irq failed\n");
- goto err_irq;
+ goto bad4;
}
sc->irq = pdev->irq;
- pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid);
- ret = ath9k_init_device(id->device, sc, subsysid, &ath_pci_bus_ops);
- if (ret) {
- dev_err(&pdev->dev, "Failed to initialize device\n");
- goto err_init;
- }
-
- ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name));
+ ah = sc->sc_ah;
+ ath9k_hw_name(ah, hw_name, sizeof(hw_name));
printk(KERN_INFO
"%s: %s mem=0x%lx, irq=%d\n",
wiphy_name(hw->wiphy),
@@ -214,18 +227,15 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
(unsigned long)mem, pdev->irq);
return 0;
-
-err_init:
- free_irq(sc->irq, sc);
-err_irq:
+bad4:
+ ath_detach(sc);
+bad3:
ieee80211_free_hw(hw);
-err_alloc_hw:
+bad2:
pci_iounmap(pdev, mem);
-err_iomap:
+bad1:
pci_release_region(pdev, 0);
-err_region:
- /* Nothing */
-err_dma:
+bad:
pci_disable_device(pdev);
return ret;
}
@@ -235,15 +245,8 @@ static void ath_pci_remove(struct pci_dev *pdev)
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
- void __iomem *mem = sc->mem;
-
- ath9k_deinit_device(sc);
- free_irq(sc->irq, sc);
- ieee80211_free_hw(sc->hw);
- pci_iounmap(pdev, mem);
- pci_disable_device(pdev);
- pci_release_region(pdev, 0);
+ ath_cleanup(sc);
}
#ifdef CONFIG_PM
diff --git a/trunk/drivers/net/wireless/ath/ath9k/rc.c b/trunk/drivers/net/wireless/ath/ath9k/rc.c
index 2880507f9d3f..c915954d4d5b 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/rc.c
+++ b/trunk/drivers/net/wireless/ath/ath9k/rc.c
@@ -668,7 +668,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
struct ieee80211_tx_rate *rates = tx_info->control.rates;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
__le16 fc = hdr->frame_control;
- u8 try_per_rate, i = 0, rix;
+ u8 try_per_rate, i = 0, rix, nrix;
int is_probe = 0;
if (rate_control_send_low(sta, priv_sta, txrc))
@@ -678,47 +678,48 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
* For Multi Rate Retry we use a different number of
* retry attempt counts. This ends up looking like this:
*
- * MRR[0] = 4
- * MRR[1] = 4
- * MRR[2] = 4
- * MRR[3] = 8
+ * MRR[0] = 2
+ * MRR[1] = 2
+ * MRR[2] = 2
+ * MRR[3] = 4
*
*/
- try_per_rate = 4;
+ try_per_rate = sc->hw->max_rate_tries;
rate_table = sc->cur_rate_table;
rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe);
+ nrix = rix;
if (is_probe) {
/* set one try for probe rates. For the
* probes don't enable rts */
ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
- 1, rix, 0);
+ 1, nrix, 0);
/* Get the next tried/allowed rate. No RTS for the next series
* after the probe rate
*/
- ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
+ ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix);
ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
- try_per_rate, rix, 0);
+ try_per_rate, nrix, 0);
tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
} else {
/* Set the choosen rate. No RTS for first series entry. */
ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
- try_per_rate, rix, 0);
+ try_per_rate, nrix, 0);
}
/* Fill in the other rates for multirate retry */
for ( ; i < 4; i++) {
/* Use twice the number of tries for the last MRR segment. */
if (i + 1 == 4)
- try_per_rate = 8;
+ try_per_rate = 4;
- ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
+ ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix);
/* All other rates in the series have RTS enabled */
ath_rc_rate_set_series(rate_table, &rates[i], txrc,
- try_per_rate, rix, 1);
+ try_per_rate, nrix, 1);
}
/*
diff --git a/trunk/drivers/net/wireless/ath/ath9k/rc.h b/trunk/drivers/net/wireless/ath/ath9k/rc.h
index 4f6d6fd442f4..9eb96f506998 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/rc.h
+++ b/trunk/drivers/net/wireless/ath/ath9k/rc.h
@@ -57,10 +57,6 @@ enum {
|| (_phy == WLAN_RC_PHY_HT_40_DS) \
|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \
|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
-#define WLAN_RC_PHY_20(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS) \
- || (_phy == WLAN_RC_PHY_HT_20_DS) \
- || (_phy == WLAN_RC_PHY_HT_20_SS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_20_DS_HGI))
#define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \
|| (_phy == WLAN_RC_PHY_HT_40_DS) \
|| (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \
diff --git a/trunk/drivers/net/wireless/ath/ath9k/recv.c b/trunk/drivers/net/wireless/ath/ath9k/recv.c
index 1ca42e5148c8..477365e5ae69 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/recv.c
+++ b/trunk/drivers/net/wireless/ath/ath9k/recv.c
@@ -364,10 +364,10 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0)
return; /* not from our current AP */
- sc->ps_flags &= ~PS_WAIT_FOR_BEACON;
+ sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON;
- if (sc->ps_flags & PS_BEACON_SYNC) {
- sc->ps_flags &= ~PS_BEACON_SYNC;
+ if (sc->sc_flags & SC_OP_BEACON_SYNC) {
+ sc->sc_flags &= ~SC_OP_BEACON_SYNC;
ath_print(common, ATH_DBG_PS,
"Reconfigure Beacon timers based on "
"timestamp from the AP\n");
@@ -384,17 +384,17 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
*/
ath_print(common, ATH_DBG_PS, "Received DTIM beacon indicating "
"buffered broadcast/multicast frame(s)\n");
- sc->ps_flags |= PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON;
+ sc->sc_flags |= SC_OP_WAIT_FOR_CAB | SC_OP_WAIT_FOR_BEACON;
return;
}
- if (sc->ps_flags & PS_WAIT_FOR_CAB) {
+ if (sc->sc_flags & SC_OP_WAIT_FOR_CAB) {
/*
* This can happen if a broadcast frame is dropped or the AP
* fails to send a frame indicating that all CAB frames have
* been delivered.
*/
- sc->ps_flags &= ~PS_WAIT_FOR_CAB;
+ sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB;
ath_print(common, ATH_DBG_PS,
"PS wait for CAB frames timed out\n");
}
@@ -408,10 +408,10 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
hdr = (struct ieee80211_hdr *)skb->data;
/* Process Beacon and CAB receive in PS state */
- if ((sc->ps_flags & PS_WAIT_FOR_BEACON) &&
+ if ((sc->sc_flags & SC_OP_WAIT_FOR_BEACON) &&
ieee80211_is_beacon(hdr->frame_control))
ath_rx_ps_beacon(sc, skb);
- else if ((sc->ps_flags & PS_WAIT_FOR_CAB) &&
+ else if ((sc->sc_flags & SC_OP_WAIT_FOR_CAB) &&
(ieee80211_is_data(hdr->frame_control) ||
ieee80211_is_action(hdr->frame_control)) &&
is_multicast_ether_addr(hdr->addr1) &&
@@ -420,20 +420,20 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
* No more broadcast/multicast frames to be received at this
* point.
*/
- sc->ps_flags &= ~PS_WAIT_FOR_CAB;
+ sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB;
ath_print(common, ATH_DBG_PS,
"All PS CAB frames received, back to sleep\n");
- } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) &&
+ } else if ((sc->sc_flags & SC_OP_WAIT_FOR_PSPOLL_DATA) &&
!is_multicast_ether_addr(hdr->addr1) &&
!ieee80211_has_morefrags(hdr->frame_control)) {
- sc->ps_flags &= ~PS_WAIT_FOR_PSPOLL_DATA;
+ sc->sc_flags &= ~SC_OP_WAIT_FOR_PSPOLL_DATA;
ath_print(common, ATH_DBG_PS,
"Going back to sleep after having received "
- "PS-Poll data (0x%lx)\n",
- sc->ps_flags & (PS_WAIT_FOR_BEACON |
- PS_WAIT_FOR_CAB |
- PS_WAIT_FOR_PSPOLL_DATA |
- PS_WAIT_FOR_TX_ACK));
+ "PS-Poll data (0x%x)\n",
+ sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
+ SC_OP_WAIT_FOR_CAB |
+ SC_OP_WAIT_FOR_PSPOLL_DATA |
+ SC_OP_WAIT_FOR_TX_ACK));
}
}
@@ -571,8 +571,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
hw = ath_get_virt_hw(sc, hdr);
rx_stats = &ds->ds_rxstat;
- ath_debug_stat_rx(sc, bf);
-
/*
* If we're asked to flush receive queue, directly
* chain it back at the queue without processing it.
@@ -633,9 +631,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
sc->rx.rxotherant = 0;
}
- if (unlikely(sc->ps_flags & (PS_WAIT_FOR_BEACON |
- PS_WAIT_FOR_CAB |
- PS_WAIT_FOR_PSPOLL_DATA)))
+ if (unlikely(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
+ SC_OP_WAIT_FOR_CAB |
+ SC_OP_WAIT_FOR_PSPOLL_DATA)))
ath_rx_ps(sc, skb);
ath_rx_send_to_mac80211(hw, sc, skb, rxs);
diff --git a/trunk/drivers/net/wireless/ath/ath9k/reg.h b/trunk/drivers/net/wireless/ath/ath9k/reg.h
index 72cfa8ebd9ae..8e653fb937a1 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/reg.h
+++ b/trunk/drivers/net/wireless/ath/ath9k/reg.h
@@ -1547,9 +1547,9 @@ enum {
#define AR_BT_COEX_WEIGHT 0x8174
#define AR_BT_COEX_WGHT 0xff55
-#define AR_STOMP_ALL_WLAN_WGHT 0xfcfc
-#define AR_STOMP_LOW_WLAN_WGHT 0xa8a8
-#define AR_STOMP_NONE_WLAN_WGHT 0x0000
+#define AR_STOMP_ALL_WLAN_WGHT 0xffcc
+#define AR_STOMP_LOW_WLAN_WGHT 0xaaa8
+#define AR_STOMP_NONE_WLAN_WGHT 0xaa00
#define AR_BTCOEX_BT_WGHT 0x0000ffff
#define AR_BTCOEX_BT_WGHT_S 0
#define AR_BTCOEX_WL_WGHT 0xffff0000
diff --git a/trunk/drivers/net/wireless/ath/ath9k/virtual.c b/trunk/drivers/net/wireless/ath/ath9k/virtual.c
index a43fbf84dab9..cd26caaf44e7 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/virtual.c
+++ b/trunk/drivers/net/wireless/ath/ath9k/virtual.c
@@ -152,7 +152,7 @@ int ath9k_wiphy_add(struct ath_softc *sc)
SET_IEEE80211_PERM_ADDR(hw, addr);
- ath9k_set_hw_capab(sc, hw);
+ ath_set_hw_capab(sc, hw);
error = ieee80211_register_hw(hw);
diff --git a/trunk/drivers/net/wireless/ath/ath9k/xmit.c b/trunk/drivers/net/wireless/ath/ath9k/xmit.c
index 47294f90bbe5..29bf33692f71 100644
--- a/trunk/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/trunk/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1498,6 +1498,26 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
ctsrate |= rate->hw_value_short;
+ /*
+ * ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive.
+ * Check the first rate in the series to decide whether RTS/CTS
+ * or CTS-to-self has to be used.
+ */
+ if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
+ flags = ATH9K_TXDESC_CTSENA;
+ else if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
+ flags = ATH9K_TXDESC_RTSENA;
+
+ /* FIXME: Handle aggregation protection */
+ if (sc->config.ath_aggr_prot &&
+ (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) {
+ flags = ATH9K_TXDESC_RTSENA;
+ }
+
+ /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
+ if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit))
+ flags &= ~(ATH9K_TXDESC_RTSENA);
+
for (i = 0; i < 4; i++) {
bool is_40, is_sgi, is_sp;
int phy;
@@ -1509,15 +1529,8 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
series[i].Tries = rates[i].count;
series[i].ChSel = common->tx_chainmask;
- if ((sc->config.ath_aggr_prot && bf_isaggr(bf)) ||
- (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)) {
+ if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)
series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
- flags |= ATH9K_TXDESC_RTSENA;
- } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
- series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
- flags |= ATH9K_TXDESC_CTSENA;
- }
-
if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
series[i].RateFlags |= ATH9K_RATESERIES_2040;
if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
@@ -1555,14 +1568,6 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
phy, rate->bitrate * 100, bf->bf_frmlen, rix, is_sp);
}
- /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
- if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit))
- flags &= ~ATH9K_TXDESC_RTSENA;
-
- /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
- if (flags & ATH9K_TXDESC_RTSENA)
- flags &= ~ATH9K_TXDESC_CTSENA;
-
/* set dur_update_en for l-sig computation except for PS-Poll frames */
ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc,
bf->bf_lastbf->bf_desc,
@@ -1643,7 +1648,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
/* tag if this is a nullfunc frame to enable PS when AP acks it */
if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc)) {
bf->bf_isnullfunc = true;
- sc->ps_flags &= ~PS_NULLFUNC_COMPLETED;
+ sc->sc_flags &= ~SC_OP_NULLFUNC_COMPLETED;
} else
bf->bf_isnullfunc = false;
@@ -1853,15 +1858,15 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
skb_pull(skb, padsize);
}
- if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) {
- sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK;
+ if (sc->sc_flags & SC_OP_WAIT_FOR_TX_ACK) {
+ sc->sc_flags &= ~SC_OP_WAIT_FOR_TX_ACK;
ath_print(common, ATH_DBG_PS,
"Going back to sleep after having "
- "received TX status (0x%lx)\n",
- sc->ps_flags & (PS_WAIT_FOR_BEACON |
- PS_WAIT_FOR_CAB |
- PS_WAIT_FOR_PSPOLL_DATA |
- PS_WAIT_FOR_TX_ACK));
+ "received TX status (0x%x)\n",
+ sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
+ SC_OP_WAIT_FOR_CAB |
+ SC_OP_WAIT_FOR_PSPOLL_DATA |
+ SC_OP_WAIT_FOR_TX_ACK));
}
if (unlikely(tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_INTERNAL))
@@ -2048,10 +2053,11 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
*/
if (bf->bf_isnullfunc &&
(ds->ds_txstat.ts_status & ATH9K_TX_ACKED)) {
- if ((sc->ps_flags & PS_ENABLED))
- ath9k_enable_ps(sc);
- else
- sc->ps_flags |= PS_NULLFUNC_COMPLETED;
+ if ((sc->sc_flags & SC_OP_PS_ENABLED)) {
+ sc->ps_enabled = true;
+ ath9k_hw_setrxabort(sc->sc_ah, 1);
+ } else
+ sc->sc_flags |= SC_OP_NULLFUNC_COMPLETED;
}
/*
diff --git a/trunk/drivers/net/wireless/ath/debug.h b/trunk/drivers/net/wireless/ath/debug.h
index 8263633c003c..d6b685a06c5e 100644
--- a/trunk/drivers/net/wireless/ath/debug.h
+++ b/trunk/drivers/net/wireless/ath/debug.h
@@ -65,11 +65,11 @@ enum ATH_DEBUG {
#define ATH_DBG_DEFAULT (ATH_DBG_FATAL)
#ifdef CONFIG_ATH_DEBUG
-void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
- __attribute__ ((format (printf, 3, 4)));
+void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...);
#else
-static inline void __attribute__ ((format (printf, 3, 4)))
-ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
+static inline void ath_print(struct ath_common *common,
+ int dbg_mask,
+ const char *fmt, ...)
{
}
#endif /* CONFIG_ATH_DEBUG */
diff --git a/trunk/drivers/net/wireless/ath/regd.c b/trunk/drivers/net/wireless/ath/regd.c
index 04abd1f556b7..039ac490465c 100644
--- a/trunk/drivers/net/wireless/ath/regd.c
+++ b/trunk/drivers/net/wireless/ath/regd.c
@@ -110,9 +110,8 @@ static const struct ieee80211_regdomain ath_world_regdom_67_68_6A = {
static inline bool is_wwr_sku(u16 regd)
{
- return ((regd & COUNTRY_ERD_FLAG) != COUNTRY_ERD_FLAG) &&
- (((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) ||
- (regd == WORLD));
+ return ((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) ||
+ (regd == WORLD);
}
static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
diff --git a/trunk/drivers/net/wireless/b43/Kconfig b/trunk/drivers/net/wireless/b43/Kconfig
index 073be566d05e..64c12e1bced3 100644
--- a/trunk/drivers/net/wireless/b43/Kconfig
+++ b/trunk/drivers/net/wireless/b43/Kconfig
@@ -3,7 +3,6 @@ config B43
depends on SSB_POSSIBLE && MAC80211 && HAS_DMA
select SSB
select FW_LOADER
- select SSB_BLOCKIO
---help---
b43 is a driver for the Broadcom 43xx series wireless devices.
@@ -79,6 +78,14 @@ config B43_SDIO
If unsure, say N.
+# Data transfers to the device via PIO
+# This is only needed on PCMCIA and SDIO devices. All others can do DMA properly.
+config B43_PIO
+ bool
+ depends on B43 && (B43_SDIO || B43_PCMCIA || B43_FORCE_PIO)
+ select SSB_BLOCKIO
+ default y
+
config B43_NPHY
bool "Pre IEEE 802.11n support (BROKEN)"
depends on B43 && EXPERIMENTAL && BROKEN
@@ -130,4 +137,12 @@ config B43_DEBUG
for production use.
Only say Y, if you are debugging a problem in the b43 driver sourcecode.
+config B43_FORCE_PIO
+ bool "Force usage of PIO instead of DMA"
+ depends on B43 && B43_DEBUG
+ ---help---
+ This will disable DMA and always enable PIO instead.
+ Say N!
+ This is only for debugging the PIO engine code. You do
+ _NOT_ want to enable this.
diff --git a/trunk/drivers/net/wireless/b43/Makefile b/trunk/drivers/net/wireless/b43/Makefile
index 5e83b6f0a3a0..84772a2542dc 100644
--- a/trunk/drivers/net/wireless/b43/Makefile
+++ b/trunk/drivers/net/wireless/b43/Makefile
@@ -12,7 +12,7 @@ b43-y += xmit.o
b43-y += lo.o
b43-y += wa.o
b43-y += dma.o
-b43-y += pio.o
+b43-$(CONFIG_B43_PIO) += pio.o
b43-y += rfkill.o
b43-$(CONFIG_B43_LEDS) += leds.o
b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
diff --git a/trunk/drivers/net/wireless/b43/b43.h b/trunk/drivers/net/wireless/b43/b43.h
index 6a6ab0f630e5..c484cc253892 100644
--- a/trunk/drivers/net/wireless/b43/b43.h
+++ b/trunk/drivers/net/wireless/b43/b43.h
@@ -254,14 +254,6 @@ enum {
#define B43_SHM_SH_MAXBFRAMES 0x0080 /* Maximum number of frames in a burst */
#define B43_SHM_SH_SPUWKUP 0x0094 /* pre-wakeup for synth PU in us */
#define B43_SHM_SH_PRETBTT 0x0096 /* pre-TBTT in us */
-/* SHM_SHARED tx iq workarounds */
-#define B43_SHM_SH_NPHY_TXIQW0 0x0700
-#define B43_SHM_SH_NPHY_TXIQW1 0x0702
-#define B43_SHM_SH_NPHY_TXIQW2 0x0704
-#define B43_SHM_SH_NPHY_TXIQW3 0x0706
-/* SHM_SHARED tx pwr ctrl */
-#define B43_SHM_SH_NPHY_TXPWR_INDX0 0x0708
-#define B43_SHM_SH_NPHY_TXPWR_INDX1 0x070E
/* SHM_SCRATCH offsets */
#define B43_SHM_SC_MINCONT 0x0003 /* Minimum contention window */
@@ -830,9 +822,11 @@ struct b43_wl {
/* The device LEDs. */
struct b43_leds leds;
+#ifdef CONFIG_B43_PIO
/* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */
u8 pio_scratchspace[110] __attribute__((__aligned__(8)));
u8 pio_tailspace[4] __attribute__((__aligned__(8)));
+#endif /* CONFIG_B43_PIO */
};
static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw)
@@ -883,9 +877,20 @@ static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value)
static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
{
+#ifdef CONFIG_B43_PIO
return dev->__using_pio_transfers;
+#else
+ return 0;
+#endif
}
+#ifdef CONFIG_B43_FORCE_PIO
+# define B43_FORCE_PIO 1
+#else
+# define B43_FORCE_PIO 0
+#endif
+
+
/* Message printing */
void b43info(struct b43_wl *wl, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));
diff --git a/trunk/drivers/net/wireless/b43/dma.c b/trunk/drivers/net/wireless/b43/dma.c
index be7abf8916ad..88d1fd02d40a 100644
--- a/trunk/drivers/net/wireless/b43/dma.c
+++ b/trunk/drivers/net/wireless/b43/dma.c
@@ -1369,6 +1369,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
b43err(dev->wl, "DMA tx mapping failure\n");
goto out;
}
+ ring->nr_tx_packets++;
if ((free_slots(ring) < TX_SLOTS_PER_FRAME) ||
should_inject_overflow(ring)) {
/* This TX ring is full. */
@@ -1499,6 +1500,22 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
}
}
+void b43_dma_get_tx_stats(struct b43_wldev *dev,
+ struct ieee80211_tx_queue_stats *stats)
+{
+ const int nr_queues = dev->wl->hw->queues;
+ struct b43_dmaring *ring;
+ int i;
+
+ for (i = 0; i < nr_queues; i++) {
+ ring = select_ring_by_priority(dev, i);
+
+ stats[i].len = ring->used_slots / TX_SLOTS_PER_FRAME;
+ stats[i].limit = ring->nr_slots / TX_SLOTS_PER_FRAME;
+ stats[i].count = ring->nr_tx_packets;
+ }
+}
+
static void dma_rx(struct b43_dmaring *ring, int *slot)
{
const struct b43_dma_ops *ops = ring->ops;
@@ -1636,6 +1653,7 @@ void b43_dma_tx_resume(struct b43_wldev *dev)
b43_power_saving_ctl_bits(dev, 0);
}
+#ifdef CONFIG_B43_PIO
static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type,
u16 mmio_base, bool enable)
{
@@ -1669,3 +1687,4 @@ void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
mmio_base = b43_dmacontroller_base(type, engine_index);
direct_fifo_rx(dev, type, mmio_base, enable);
}
+#endif /* CONFIG_B43_PIO */
diff --git a/trunk/drivers/net/wireless/b43/dma.h b/trunk/drivers/net/wireless/b43/dma.h
index dc91944d6022..f7ab37c4cdbc 100644
--- a/trunk/drivers/net/wireless/b43/dma.h
+++ b/trunk/drivers/net/wireless/b43/dma.h
@@ -228,6 +228,8 @@ struct b43_dmaring {
int used_slots;
/* Currently used slot in the ring. */
int current_slot;
+ /* Total number of packets sent. Statistics only. */
+ unsigned int nr_tx_packets;
/* Frameoffset in octets. */
u32 frameoffset;
/* Descriptor buffer size. */
@@ -276,6 +278,9 @@ void b43_dma_free(struct b43_wldev *dev);
void b43_dma_tx_suspend(struct b43_wldev *dev);
void b43_dma_tx_resume(struct b43_wldev *dev);
+void b43_dma_get_tx_stats(struct b43_wldev *dev,
+ struct ieee80211_tx_queue_stats *stats);
+
int b43_dma_tx(struct b43_wldev *dev,
struct sk_buff *skb);
void b43_dma_handle_txstatus(struct b43_wldev *dev,
diff --git a/trunk/drivers/net/wireless/b43/main.c b/trunk/drivers/net/wireless/b43/main.c
index 8f7a8c0ec27d..fcbf0e27d9f3 100644
--- a/trunk/drivers/net/wireless/b43/main.c
+++ b/trunk/drivers/net/wireless/b43/main.c
@@ -67,12 +67,7 @@ MODULE_AUTHOR("Gábor Stefanik");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(B43_SUPPORTED_FIRMWARE_ID);
-MODULE_FIRMWARE("b43/ucode11.fw");
-MODULE_FIRMWARE("b43/ucode13.fw");
-MODULE_FIRMWARE("b43/ucode14.fw");
-MODULE_FIRMWARE("b43/ucode15.fw");
-MODULE_FIRMWARE("b43/ucode5.fw");
-MODULE_FIRMWARE("b43/ucode9.fw");
+
static int modparam_bad_frames_preempt;
module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
@@ -107,9 +102,6 @@ int b43_modparam_verbose = B43_VERBOSITY_DEFAULT;
module_param_named(verbose, b43_modparam_verbose, int, 0644);
MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug");
-static int modparam_pio;
-module_param_named(pio, modparam_pio, int, 0444);
-MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode");
static const struct ssb_device_id b43_ssb_tbl[] = {
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
@@ -118,7 +110,6 @@ static const struct ssb_device_id b43_ssb_tbl[] = {
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 9),
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10),
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 11),
- SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 12),
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13),
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 15),
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16),
@@ -851,10 +842,8 @@ static void rx_tkip_phase1_write(struct b43_wldev *dev, u8 index, u32 iv32,
}
static void b43_op_update_tkip_key(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_key_conf *keyconf,
- struct ieee80211_sta *sta,
- u32 iv32, u16 *phase1key)
+ 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;
@@ -863,19 +852,19 @@ static void b43_op_update_tkip_key(struct ieee80211_hw *hw,
if (B43_WARN_ON(!modparam_hwtkip))
return;
- /* This is only called from the RX path through mac80211, where
- * our mutex is already locked. */
- B43_WARN_ON(!mutex_is_locked(&wl->mutex));
+ mutex_lock(&wl->mutex);
+
dev = wl->current_dev;
- B43_WARN_ON(!dev || b43_status(dev) < B43_STAT_INITIALIZED);
+ 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);
- /* only pairwise TKIP keys are supported right now */
- if (WARN_ON(!sta))
- return;
- keymac_write(dev, index, sta->addr);
+ keymac_write(dev, index, addr);
+
+out_unlock:
+ mutex_unlock(&wl->mutex);
}
static void do_key_write(struct b43_wldev *dev,
@@ -1804,8 +1793,8 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
dma_reason[4], dma_reason[5]);
b43err(dev->wl, "This device does not support DMA "
"on your system. Please use PIO instead.\n");
- b43err(dev->wl, "Unload the b43 module and reload "
- "with 'pio=1'\n");
+ b43err(dev->wl, "CONFIG_B43_FORCE_PIO must be set in "
+ "your kernel configuration.\n");
return;
}
if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) {
@@ -3356,6 +3345,27 @@ static int b43_op_conf_tx(struct ieee80211_hw *hw, u16 _queue,
return err;
}
+static int b43_op_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats)
+{
+ struct b43_wl *wl = hw_to_b43_wl(hw);
+ struct b43_wldev *dev;
+ int err = -ENODEV;
+
+ mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+ if (dev && b43_status(dev) >= B43_STAT_STARTED) {
+ if (b43_using_pio_transfers(dev))
+ b43_pio_get_tx_stats(dev, stats);
+ else
+ b43_dma_get_tx_stats(dev, stats);
+ err = 0;
+ }
+ mutex_unlock(&wl->mutex);
+
+ return err;
+}
+
static int b43_op_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats)
{
@@ -3559,12 +3569,6 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
dev = wl->current_dev;
phy = &dev->phy;
- if (conf_is_ht(conf))
- phy->is_40mhz =
- (conf_is_ht40_minus(conf) || conf_is_ht40_plus(conf));
- else
- phy->is_40mhz = false;
-
b43_mac_suspend(dev);
if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
@@ -3966,7 +3970,6 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
}
/* We are ready to run. */
- ieee80211_wake_queues(dev->wl->hw);
b43_set_status(dev, B43_STAT_STARTED);
/* Start data flow (TX/RX). */
@@ -4357,7 +4360,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) ||
(dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) ||
- modparam_pio) {
+ B43_FORCE_PIO) {
dev->__using_pio_transfers = 1;
err = b43_pio_init(dev);
} else {
@@ -4376,6 +4379,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
ieee80211_wake_queues(dev->wl->hw);
+ ieee80211_wake_queues(dev->wl->hw);
+
b43_set_status(dev, B43_STAT_INITIALIZED);
out:
@@ -4390,7 +4395,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
}
static int b43_op_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev;
@@ -4398,24 +4403,24 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,
/* TODO: allow WDS/AP devices to coexist */
- if (vif->type != NL80211_IFTYPE_AP &&
- vif->type != NL80211_IFTYPE_MESH_POINT &&
- vif->type != NL80211_IFTYPE_STATION &&
- vif->type != NL80211_IFTYPE_WDS &&
- vif->type != NL80211_IFTYPE_ADHOC)
+ if (conf->type != NL80211_IFTYPE_AP &&
+ conf->type != NL80211_IFTYPE_MESH_POINT &&
+ conf->type != NL80211_IFTYPE_STATION &&
+ conf->type != NL80211_IFTYPE_WDS &&
+ conf->type != NL80211_IFTYPE_ADHOC)
return -EOPNOTSUPP;
mutex_lock(&wl->mutex);
if (wl->operating)
goto out_mutex_unlock;
- b43dbg(wl, "Adding Interface type %d\n", vif->type);
+ b43dbg(wl, "Adding Interface type %d\n", conf->type);
dev = wl->current_dev;
wl->operating = 1;
- wl->vif = vif;
- wl->if_type = vif->type;
- memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
+ wl->vif = conf->vif;
+ wl->if_type = conf->type;
+ memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
b43_adjust_opmode(dev);
b43_set_pretbtt(dev);
@@ -4430,17 +4435,17 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,
}
static void b43_op_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
- b43dbg(wl, "Removing Interface type %d\n", vif->type);
+ b43dbg(wl, "Removing Interface type %d\n", conf->type);
mutex_lock(&wl->mutex);
B43_WARN_ON(!wl->operating);
- B43_WARN_ON(wl->vif != vif);
+ B43_WARN_ON(wl->vif != conf->vif);
wl->vif = NULL;
wl->operating = 0;
@@ -4581,6 +4586,7 @@ static const struct ieee80211_ops b43_hw_ops = {
.set_key = b43_op_set_key,
.update_tkip_key = b43_op_update_tkip_key,
.get_stats = b43_op_get_stats,
+ .get_tx_stats = b43_op_get_tx_stats,
.get_tsf = b43_op_get_tsf,
.set_tsf = b43_op_set_tsf,
.start = b43_op_start,
diff --git a/trunk/drivers/net/wireless/b43/phy_common.c b/trunk/drivers/net/wireless/b43/phy_common.c
index 8f7d7eff2d80..75b26e175e8f 100644
--- a/trunk/drivers/net/wireless/b43/phy_common.c
+++ b/trunk/drivers/net/wireless/b43/phy_common.c
@@ -421,48 +421,3 @@ void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on)
{
b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4);
}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/Cordic */
-struct b43_c32 b43_cordic(int theta)
-{
- u32 arctg[] = { 2949120, 1740967, 919879, 466945, 234379, 117304,
- 58666, 29335, 14668, 7334, 3667, 1833, 917, 458,
- 229, 115, 57, 29, };
- u8 i;
- s32 tmp;
- s8 signx = 1;
- u32 angle = 0;
- struct b43_c32 ret = { .i = 39797, .q = 0, };
-
- while (theta > (180 << 16))
- theta -= (360 << 16);
- while (theta < -(180 << 16))
- theta += (360 << 16);
-
- if (theta > (90 << 16)) {
- theta -= (180 << 16);
- signx = -1;
- } else if (theta < -(90 << 16)) {
- theta += (180 << 16);
- signx = -1;
- }
-
- for (i = 0; i <= 17; i++) {
- if (theta > angle) {
- tmp = ret.i - (ret.q >> i);
- ret.q += ret.i >> i;
- ret.i = tmp;
- angle += arctg[i];
- } else {
- tmp = ret.i + (ret.q >> i);
- ret.q -= ret.i >> i;
- ret.i = tmp;
- angle -= arctg[i];
- }
- }
-
- ret.i *= signx;
- ret.q *= signx;
-
- return ret;
-}
diff --git a/trunk/drivers/net/wireless/b43/phy_common.h b/trunk/drivers/net/wireless/b43/phy_common.h
index bd480b481bfc..9edd4e8e0c85 100644
--- a/trunk/drivers/net/wireless/b43/phy_common.h
+++ b/trunk/drivers/net/wireless/b43/phy_common.h
@@ -5,12 +5,6 @@
struct b43_wldev;
-/* Complex number using 2 32-bit signed integers */
-struct b43_c32 { s32 i, q; };
-
-#define CORDIC_CONVERT(value) (((value) >= 0) ? \
- ((((value) >> 15) + 1) >> 1) : \
- -((((-(value)) >> 15) + 1) >> 1))
/* PHY register routing bits */
#define B43_PHYROUTE 0x0C00 /* PHY register routing bits mask */
@@ -218,9 +212,6 @@ struct b43_phy {
bool supports_2ghz;
bool supports_5ghz;
- /* HT info */
- bool is_40mhz;
-
/* GMODE bit enabled? */
bool gmode;
@@ -427,6 +418,5 @@ int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset);
*/
void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on);
-struct b43_c32 b43_cordic(int theta);
#endif /* LINUX_B43_PHY_COMMON_H_ */
diff --git a/trunk/drivers/net/wireless/b43/phy_lp.c b/trunk/drivers/net/wireless/b43/phy_lp.c
index 185219e0a552..3e046ec1ff86 100644
--- a/trunk/drivers/net/wireless/b43/phy_lp.c
+++ b/trunk/drivers/net/wireless/b43/phy_lp.c
@@ -80,7 +80,6 @@ static void b43_lpphy_op_free(struct b43_wldev *dev)
dev->phy.lp = NULL;
}
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/LP/ReadBandSrom */
static void lpphy_read_band_sprom(struct b43_wldev *dev)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
@@ -102,12 +101,6 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev)
maxpwr = bus->sprom.maxpwr_bg;
lpphy->max_tx_pwr_med_band = maxpwr;
cckpo = bus->sprom.cck2gpo;
- /*
- * We don't read SPROM's opo as specs say. On rev8 SPROMs
- * opo == ofdm2gpo and we don't know any SSB with LP-PHY
- * and SPROM rev below 8.
- */
- B43_WARN_ON(bus->sprom.revision < 8);
ofdmpo = bus->sprom.ofdm2gpo;
if (cckpo) {
for (i = 0; i < 4; i++) {
@@ -1710,6 +1703,19 @@ static const struct lpphy_rx_iq_comp lpphy_rev2plus_iq_comp = {
.c0 = 0,
};
+static u8 lpphy_nbits(s32 val)
+{
+ u32 tmp = abs(val);
+ u8 nbits = 0;
+
+ while (tmp != 0) {
+ nbits++;
+ tmp >>= 1;
+ }
+
+ return nbits;
+}
+
static int lpphy_calc_rx_iq_comp(struct b43_wldev *dev, u16 samples)
{
struct lpphy_iq_est iq_est;
@@ -1736,8 +1742,8 @@ static int lpphy_calc_rx_iq_comp(struct b43_wldev *dev, u16 samples)
goto out;
}
- prod_msb = fls(abs(prod));
- q_msb = fls(abs(qpwr));
+ prod_msb = lpphy_nbits(prod);
+ q_msb = lpphy_nbits(qpwr);
tmp1 = prod_msb - 20;
if (tmp1 >= 0) {
@@ -1767,6 +1773,47 @@ static int lpphy_calc_rx_iq_comp(struct b43_wldev *dev, u16 samples)
return ret;
}
+/* Complex number using 2 32-bit signed integers */
+typedef struct {s32 i, q;} lpphy_c32;
+
+static lpphy_c32 lpphy_cordic(int theta)
+{
+ u32 arctg[] = { 2949120, 1740967, 919879, 466945, 234379, 117304,
+ 58666, 29335, 14668, 7334, 3667, 1833, 917, 458,
+ 229, 115, 57, 29, };
+ int i, tmp, signx = 1, angle = 0;
+ lpphy_c32 ret = { .i = 39797, .q = 0, };
+
+ theta = clamp_t(int, theta, -180, 180);
+
+ if (theta > 90) {
+ theta -= 180;
+ signx = -1;
+ } else if (theta < -90) {
+ theta += 180;
+ signx = -1;
+ }
+
+ for (i = 0; i <= 17; i++) {
+ if (theta > angle) {
+ tmp = ret.i - (ret.q >> i);
+ ret.q += ret.i >> i;
+ ret.i = tmp;
+ angle += arctg[i];
+ } else {
+ tmp = ret.i + (ret.q >> i);
+ ret.q -= ret.i >> i;
+ ret.i = tmp;
+ angle -= arctg[i];
+ }
+ }
+
+ ret.i *= signx;
+ ret.q *= signx;
+
+ return ret;
+}
+
static void lpphy_run_samples(struct b43_wldev *dev, u16 samples, u16 loops,
u16 wait)
{
@@ -1784,9 +1831,8 @@ static void lpphy_start_tx_tone(struct b43_wldev *dev, s32 freq, u16 max)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
u16 buf[64];
- int i, samples = 0, angle = 0;
- int rotation = (((36 * freq) / 20) << 16) / 100;
- struct b43_c32 sample;
+ int i, samples = 0, angle = 0, rotation = (9 * freq) / 500;
+ lpphy_c32 sample;
lpphy->tx_tone_freq = freq;
@@ -1802,10 +1848,10 @@ static void lpphy_start_tx_tone(struct b43_wldev *dev, s32 freq, u16 max)
}
for (i = 0; i < samples; i++) {
- sample = b43_cordic(angle);
+ sample = lpphy_cordic(angle);
angle += rotation;
- buf[i] = CORDIC_CONVERT((sample.i * max) & 0xFF) << 8;
- buf[i] |= CORDIC_CONVERT((sample.q * max) & 0xFF);
+ buf[i] = ((sample.i * max) & 0xFF) << 8;
+ buf[i] |= (sample.q * max) & 0xFF;
}
b43_lptab_write_bulk(dev, B43_LPTAB16(5, 0), samples, buf);
diff --git a/trunk/drivers/net/wireless/b43/phy_n.c b/trunk/drivers/net/wireless/b43/phy_n.c
index 795bb1e3345d..992318a78077 100644
--- a/trunk/drivers/net/wireless/b43/phy_n.c
+++ b/trunk/drivers/net/wireless/b43/phy_n.c
@@ -28,50 +28,7 @@
#include "b43.h"
#include "phy_n.h"
#include "tables_nphy.h"
-#include "main.h"
-struct nphy_txgains {
- u16 txgm[2];
- u16 pga[2];
- u16 pad[2];
- u16 ipa[2];
-};
-
-struct nphy_iqcal_params {
- u16 txgm;
- u16 pga;
- u16 pad;
- u16 ipa;
- u16 cal_gain;
- u16 ncorr[5];
-};
-
-struct nphy_iq_est {
- s32 iq0_prod;
- u32 i0_pwr;
- u32 q0_pwr;
- s32 iq1_prod;
- u32 i1_pwr;
- u32 q1_pwr;
-};
-
-enum b43_nphy_rf_sequence {
- B43_RFSEQ_RX2TX,
- B43_RFSEQ_TX2RX,
- B43_RFSEQ_RESET2RX,
- B43_RFSEQ_UPDATE_GAINH,
- B43_RFSEQ_UPDATE_GAINL,
- B43_RFSEQ_UPDATE_GAINU,
-};
-
-static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
- u8 *events, u8 *delays, u8 length);
-static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
- enum b43_nphy_rf_sequence seq);
-static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
- u16 value, u8 core, bool off);
-static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
- u16 value, u8 core);
void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
{//TODO
@@ -240,2915 +197,295 @@ void b43_nphy_radio_turn_off(struct b43_wldev *dev)
~B43_NPHY_RFCTL_CMD_EN);
}
-/*
- * Upload the N-PHY tables.
- * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
- */
+#define ntab_upload(dev, offset, data) do { \
+ unsigned int i; \
+ for (i = 0; i < (offset##_SIZE); i++) \
+ b43_ntab_write(dev, (offset) + i, (data)[i]); \
+ } while (0)
+
+/* Upload the N-PHY tables. */
static void b43_nphy_tables_init(struct b43_wldev *dev)
{
- if (dev->phy.rev < 3)
- b43_nphy_rev0_1_2_tables_init(dev);
- else
- b43_nphy_rev3plus_tables_init(dev);
+ /* Static tables */
+ ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct);
+ ntab_upload(dev, B43_NTAB_FRAMELT, b43_ntab_framelookup);
+ ntab_upload(dev, B43_NTAB_TMAP, b43_ntab_tmap);
+ ntab_upload(dev, B43_NTAB_TDTRN, b43_ntab_tdtrn);
+ ntab_upload(dev, B43_NTAB_INTLEVEL, b43_ntab_intlevel);
+ ntab_upload(dev, B43_NTAB_PILOT, b43_ntab_pilot);
+ ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt);
+ ntab_upload(dev, B43_NTAB_TDI20A0, b43_ntab_tdi20a0);
+ ntab_upload(dev, B43_NTAB_TDI20A1, b43_ntab_tdi20a1);
+ ntab_upload(dev, B43_NTAB_TDI40A0, b43_ntab_tdi40a0);
+ ntab_upload(dev, B43_NTAB_TDI40A1, b43_ntab_tdi40a1);
+ ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi);
+ ntab_upload(dev, B43_NTAB_CHANEST, b43_ntab_channelest);
+ ntab_upload(dev, B43_NTAB_MCS, b43_ntab_mcs);
+
+ /* Volatile tables */
+ ntab_upload(dev, B43_NTAB_NOISEVAR10, b43_ntab_noisevar10);
+ ntab_upload(dev, B43_NTAB_NOISEVAR11, b43_ntab_noisevar11);
+ ntab_upload(dev, B43_NTAB_C0_ESTPLT, b43_ntab_estimatepowerlt0);
+ ntab_upload(dev, B43_NTAB_C1_ESTPLT, b43_ntab_estimatepowerlt1);
+ ntab_upload(dev, B43_NTAB_C0_ADJPLT, b43_ntab_adjustpower0);
+ ntab_upload(dev, B43_NTAB_C1_ADJPLT, b43_ntab_adjustpower1);
+ ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0);
+ ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1);
+ ntab_upload(dev, B43_NTAB_C0_IQLT, b43_ntab_iqlt0);
+ ntab_upload(dev, B43_NTAB_C1_IQLT, b43_ntab_iqlt1);
+ ntab_upload(dev, B43_NTAB_C0_LOFEEDTH, b43_ntab_loftlt0);
+ ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1);
}
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */
-static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
+static void b43_nphy_workarounds(struct b43_wldev *dev)
{
- struct b43_phy_n *nphy = dev->phy.n;
- enum ieee80211_band band;
- u16 tmp;
+ struct b43_phy *phy = &dev->phy;
+ unsigned int i;
- if (!enable) {
- nphy->rfctrl_intc1_save = b43_phy_read(dev,
- B43_NPHY_RFCTL_INTC1);
- nphy->rfctrl_intc2_save = b43_phy_read(dev,
- B43_NPHY_RFCTL_INTC2);
- band = b43_current_band(dev->wl);
- if (dev->phy.rev >= 3) {
- if (band == IEEE80211_BAND_5GHZ)
- tmp = 0x600;
- else
- tmp = 0x480;
- } else {
- if (band == IEEE80211_BAND_5GHZ)
- tmp = 0x180;
- else
- tmp = 0x120;
- }
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
- } else {
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC1,
- nphy->rfctrl_intc1_save);
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC2,
- nphy->rfctrl_intc2_save);
- }
-}
+ b43_phy_set(dev, B43_NPHY_IQFLIP,
+ B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
+ if (1 /* FIXME band is 2.4GHz */) {
+ b43_phy_set(dev, B43_NPHY_CLASSCTL,
+ B43_NPHY_CLASSCTL_CCKEN);
+ } else {
+ b43_phy_mask(dev, B43_NPHY_CLASSCTL,
+ ~B43_NPHY_CLASSCTL_CCKEN);
+ }
+ b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
+ b43_phy_write(dev, B43_NPHY_TXFRAMEDELAY, 8);
+
+ /* Fixup some tables */
+ b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0xA);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0xA);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x800);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x800);
+
+ b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
+ b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
+ b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
+ b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
+
+ //TODO set RF sequence
+
+ /* Set narrowband clip threshold */
+ b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 66);
+ b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 66);
+
+ /* Set wideband clip 2 threshold */
+ b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
+ ~B43_NPHY_C1_CLIPWBTHRES_CLIP2,
+ 21 << B43_NPHY_C1_CLIPWBTHRES_CLIP2_SHIFT);
+ b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
+ ~B43_NPHY_C2_CLIPWBTHRES_CLIP2,
+ 21 << B43_NPHY_C2_CLIPWBTHRES_CLIP2_SHIFT);
+
+ /* Set Clip 2 detect */
+ b43_phy_set(dev, B43_NPHY_C1_CGAINI,
+ B43_NPHY_C1_CGAINI_CL2DETECT);
+ b43_phy_set(dev, B43_NPHY_C2_CGAINI,
+ B43_NPHY_C2_CGAINI_CL2DETECT);
+
+ if (0 /*FIXME*/) {
+ /* Set dwell lengths */
+ b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 43);
+ b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 43);
+ b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 9);
+ b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 9);
+
+ /* Set gain backoff */
+ b43_phy_maskset(dev, B43_NPHY_C1_CGAINI,
+ ~B43_NPHY_C1_CGAINI_GAINBKOFF,
+ 1 << B43_NPHY_C1_CGAINI_GAINBKOFF_SHIFT);
+ b43_phy_maskset(dev, B43_NPHY_C2_CGAINI,
+ ~B43_NPHY_C2_CGAINI_GAINBKOFF,
+ 1 << B43_NPHY_C2_CGAINI_GAINBKOFF_SHIFT);
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */
-static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
-{
- struct b43_phy_n *nphy = dev->phy.n;
- u16 tmp;
- enum ieee80211_band band = b43_current_band(dev->wl);
- bool ipa = (nphy->ipa2g_on && band == IEEE80211_BAND_2GHZ) ||
- (nphy->ipa5g_on && band == IEEE80211_BAND_5GHZ);
-
- if (dev->phy.rev >= 3) {
- if (ipa) {
- tmp = 4;
- b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
- (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
- }
+ /* Set HPVGA2 index */
+ b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN,
+ ~B43_NPHY_C1_INITGAIN_HPVGA2,
+ 6 << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT);
+ b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN,
+ ~B43_NPHY_C2_INITGAIN_HPVGA2,
+ 6 << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT);
- tmp = 1;
- b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2,
- (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
+ //FIXME verify that the specs really mean to use autoinc here.
+ for (i = 0; i < 3; i++)
+ b43_ntab_write(dev, B43_NTAB16(7, 0x106) + i, 0x673);
}
-}
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
-static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force)
-{
- u32 tmslow;
+ /* Set minimum gain value */
+ b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN,
+ ~B43_NPHY_C1_MINGAIN,
+ 23 << B43_NPHY_C1_MINGAIN_SHIFT);
+ b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN,
+ ~B43_NPHY_C2_MINGAIN,
+ 23 << B43_NPHY_C2_MINGAIN_SHIFT);
- if (dev->phy.type != B43_PHYTYPE_N)
- return;
+ if (phy->rev < 2) {
+ b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
+ ~B43_NPHY_SCRAM_SIGCTL_SCM);
+ }
- tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
- if (force)
- tmslow |= SSB_TMSLOW_FGC;
- else
- tmslow &= ~SSB_TMSLOW_FGC;
- ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
+ /* Set phase track alpha and beta */
+ b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
+ b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
+ b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
}
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
static void b43_nphy_reset_cca(struct b43_wldev *dev)
{
u16 bbcfg;
- b43_nphy_bmac_clock_fgc(dev, 1);
+ ssb_write32(dev->dev, SSB_TMSLOW,
+ ssb_read32(dev->dev, SSB_TMSLOW) | SSB_TMSLOW_FGC);
bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
- b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA);
- udelay(1);
- b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
- b43_nphy_bmac_clock_fgc(dev, 0);
- b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */
-static void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble)
-{
- u16 mimocfg = b43_phy_read(dev, B43_NPHY_MIMOCFG);
-
- mimocfg |= B43_NPHY_MIMOCFG_AUTO;
- if (preamble == 1)
- mimocfg |= B43_NPHY_MIMOCFG_GFMIX;
- else
- mimocfg &= ~B43_NPHY_MIMOCFG_GFMIX;
-
- b43_phy_write(dev, B43_NPHY_MIMOCFG, mimocfg);
+ b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTCCA);
+ b43_phy_write(dev, B43_NPHY_BBCFG,
+ bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
+ ssb_write32(dev->dev, SSB_TMSLOW,
+ ssb_read32(dev->dev, SSB_TMSLOW) & ~SSB_TMSLOW_FGC);
}
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */
-static void b43_nphy_update_txrx_chain(struct b43_wldev *dev)
-{
- struct b43_phy_n *nphy = dev->phy.n;
-
- bool override = false;
- u16 chain = 0x33;
-
- if (nphy->txrx_chain == 0) {
- chain = 0x11;
- override = true;
- } else if (nphy->txrx_chain == 1) {
- chain = 0x22;
- override = true;
- }
-
- b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
- ~(B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN),
- chain);
-
- if (override)
- b43_phy_set(dev, B43_NPHY_RFSEQMODE,
- B43_NPHY_RFSEQMODE_CAOVER);
- else
- b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
- ~B43_NPHY_RFSEQMODE_CAOVER);
-}
+enum b43_nphy_rf_sequence {
+ B43_RFSEQ_RX2TX,
+ B43_RFSEQ_TX2RX,
+ B43_RFSEQ_RESET2RX,
+ B43_RFSEQ_UPDATE_GAINH,
+ B43_RFSEQ_UPDATE_GAINL,
+ B43_RFSEQ_UPDATE_GAINU,
+};
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */
-static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est,
- u16 samps, u8 time, bool wait)
+static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
+ enum b43_nphy_rf_sequence seq)
{
+ static const u16 trigger[] = {
+ [B43_RFSEQ_RX2TX] = B43_NPHY_RFSEQTR_RX2TX,
+ [B43_RFSEQ_TX2RX] = B43_NPHY_RFSEQTR_TX2RX,
+ [B43_RFSEQ_RESET2RX] = B43_NPHY_RFSEQTR_RST2RX,
+ [B43_RFSEQ_UPDATE_GAINH] = B43_NPHY_RFSEQTR_UPGH,
+ [B43_RFSEQ_UPDATE_GAINL] = B43_NPHY_RFSEQTR_UPGL,
+ [B43_RFSEQ_UPDATE_GAINU] = B43_NPHY_RFSEQTR_UPGU,
+ };
int i;
- u16 tmp;
-
- b43_phy_write(dev, B43_NPHY_IQEST_SAMCNT, samps);
- b43_phy_maskset(dev, B43_NPHY_IQEST_WT, ~B43_NPHY_IQEST_WT_VAL, time);
- if (wait)
- b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_MODE);
- else
- b43_phy_mask(dev, B43_NPHY_IQEST_CMD, ~B43_NPHY_IQEST_CMD_MODE);
-
- b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_START);
-
- for (i = 1000; i; i--) {
- tmp = b43_phy_read(dev, B43_NPHY_IQEST_CMD);
- if (!(tmp & B43_NPHY_IQEST_CMD_START)) {
- est->i0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI0) << 16) |
- b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO0);
- est->q0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI0) << 16) |
- b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO0);
- est->iq0_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI0) << 16) |
- b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO0);
-
- est->i1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI1) << 16) |
- b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO1);
- est->q1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI1) << 16) |
- b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO1);
- est->iq1_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI1) << 16) |
- b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO1);
- return;
- }
- udelay(10);
- }
- memset(est, 0, sizeof(*est));
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */
-static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write,
- struct b43_phy_n_iq_comp *pcomp)
-{
- if (write) {
- b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPA0, pcomp->a0);
- b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPB0, pcomp->b0);
- b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPA1, pcomp->a1);
- b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPB1, pcomp->b1);
- } else {
- pcomp->a0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPA0);
- pcomp->b0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPB0);
- pcomp->a1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPA1);
- pcomp->b1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPB1);
- }
-}
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */
-static void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core)
-{
- u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
+ B43_WARN_ON(seq >= ARRAY_SIZE(trigger));
- b43_phy_write(dev, B43_NPHY_RFSEQCA, regs[0]);
- if (core == 0) {
- b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[1]);
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
- } else {
- b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
+ b43_phy_set(dev, B43_NPHY_RFSEQMODE,
+ B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER);
+ b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]);
+ for (i = 0; i < 200; i++) {
+ if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq]))
+ goto ok;
+ msleep(1);
}
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[3]);
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[4]);
- b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, regs[5]);
- b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, regs[6]);
- b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, regs[7]);
- b43_phy_write(dev, B43_NPHY_RFCTL_OVER, regs[8]);
- b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
- b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
+ b43err(dev->wl, "RF sequence status timeout\n");
+ok:
+ b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
+ ~(B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER));
}
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */
-static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
+static void b43_nphy_bphy_init(struct b43_wldev *dev)
{
- u8 rxval, txval;
- u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
-
- regs[0] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
- if (core == 0) {
- regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
- regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
- } else {
- regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
- regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
- }
- regs[3] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
- regs[4] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
- regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
- regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
- regs[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S1);
- regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
- regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
- regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
-
- b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
- b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
-
- b43_phy_maskset(dev, B43_NPHY_RFSEQCA, (u16)~B43_NPHY_RFSEQCA_RXDIS,
- ((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
- b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
- ((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT));
- b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,
- (core << B43_NPHY_RFSEQCA_RXEN_SHIFT));
- b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXDIS,
- (core << B43_NPHY_RFSEQCA_TXDIS_SHIFT));
-
- if (core == 0) {
- b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x0007);
- b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0007);
- } else {
- b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x0007);
- b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007);
- }
-
- b43_nphy_rf_control_intc_override(dev, 2, 0, 3);
- b43_nphy_rf_control_override(dev, 8, 0, 3, false);
- b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
+ unsigned int i;
+ u16 val;
- if (core == 0) {
- rxval = 1;
- txval = 8;
- } else {
- rxval = 4;
- txval = 2;
+ val = 0x1E1F;
+ for (i = 0; i < 14; i++) {
+ b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
+ val -= 0x202;
}
- b43_nphy_rf_control_intc_override(dev, 1, rxval, (core + 1));
- b43_nphy_rf_control_intc_override(dev, 1, txval, (2 - core));
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */
-static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
-{
- int i;
- s32 iq;
- u32 ii;
- u32 qq;
- int iq_nbits, qq_nbits;
- int arsh, brsh;
- u16 tmp, a, b;
-
- struct nphy_iq_est est;
- struct b43_phy_n_iq_comp old;
- struct b43_phy_n_iq_comp new = { };
- bool error = false;
-
- if (mask == 0)
- return;
-
- b43_nphy_rx_iq_coeffs(dev, false, &old);
- b43_nphy_rx_iq_coeffs(dev, true, &new);
- b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false);
- new = old;
-
- for (i = 0; i < 2; i++) {
- if (i == 0 && (mask & 1)) {
- iq = est.iq0_prod;
- ii = est.i0_pwr;
- qq = est.q0_pwr;
- } else if (i == 1 && (mask & 2)) {
- iq = est.iq1_prod;
- ii = est.i1_pwr;
- qq = est.q1_pwr;
- } else {
- B43_WARN_ON(1);
- continue;
- }
-
- if (ii + qq < 2) {
- error = true;
- break;
- }
-
- iq_nbits = fls(abs(iq));
- qq_nbits = fls(qq);
-
- arsh = iq_nbits - 20;
- if (arsh >= 0) {
- a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
- tmp = ii >> arsh;
- } else {
- a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
- tmp = ii << -arsh;
- }
- if (tmp == 0) {
- error = true;
- break;
- }
- a /= tmp;
-
- brsh = qq_nbits - 11;
- if (brsh >= 0) {
- b = (qq << (31 - qq_nbits));
- tmp = ii >> brsh;
- } else {
- b = (qq << (31 - qq_nbits));
- tmp = ii << -brsh;
- }
- if (tmp == 0) {
- error = true;
- break;
- }
- b = int_sqrt(b / tmp - a * a) - (1 << 10);
-
- if (i == 0 && (mask & 0x1)) {
- if (dev->phy.rev >= 3) {
- new.a0 = a & 0x3FF;
- new.b0 = b & 0x3FF;
- } else {
- new.a0 = b & 0x3FF;
- new.b0 = a & 0x3FF;
- }
- } else if (i == 1 && (mask & 0x2)) {
- if (dev->phy.rev >= 3) {
- new.a1 = a & 0x3FF;
- new.b1 = b & 0x3FF;
- } else {
- new.a1 = b & 0x3FF;
- new.b1 = a & 0x3FF;
- }
- }
+ val = 0x3E3F;
+ for (i = 0; i < 16; i++) {
+ b43_phy_write(dev, B43_PHY_N_BMODE(0x97 + i), val);
+ val -= 0x202;
}
-
- if (error)
- new = old;
-
- b43_nphy_rx_iq_coeffs(dev, true, &new);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */
-static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)
-{
- u16 array[4];
- int i;
-
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C50);
- for (i = 0; i < 4; i++)
- array[i] = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
-
- b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]);
- b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]);
- b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW2, array[2]);
- b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
-static void b43_nphy_write_clip_detection(struct b43_wldev *dev, u16 *clip_st)
-{
- b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]);
- b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
-static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
-{
- clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES);
- clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES);
+ b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
}
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
-static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
+/* RSSI Calibration */
+static void b43_nphy_rssi_cal(struct b43_wldev *dev, u8 type)
{
- u16 tmp;
-
- if (dev->dev->id.revision == 16)
- b43_mac_suspend(dev);
-
- tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
- tmp &= (B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN |
- B43_NPHY_CLASSCTL_WAITEDEN);
- tmp &= ~mask;
- tmp |= (val & mask);
- b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);
-
- if (dev->dev->id.revision == 16)
- b43_mac_enable(dev);
-
- return tmp;
+ //TODO
}
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */
-static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable)
+int b43_phy_initn(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
- struct b43_phy_n *nphy = phy->n;
-
- if (enable) {
- u16 clip[] = { 0xFFFF, 0xFFFF };
- if (nphy->deaf_count++ == 0) {
- nphy->classifier_state = b43_nphy_classifier(dev, 0, 0);
- b43_nphy_classifier(dev, 0x7, 0);
- b43_nphy_read_clip_detection(dev, nphy->clip_state);
- b43_nphy_write_clip_detection(dev, clip);
- }
- b43_nphy_reset_cca(dev);
- } else {
- if (--nphy->deaf_count == 0) {
- b43_nphy_classifier(dev, 0x7, nphy->classifier_state);
- b43_nphy_write_clip_detection(dev, nphy->clip_state);
- }
- }
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */
-static void b43_nphy_stop_playback(struct b43_wldev *dev)
-{
- struct b43_phy_n *nphy = dev->phy.n;
u16 tmp;
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, 1);
-
- tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT);
- if (tmp & 0x1)
- b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP);
- else if (tmp & 0x2)
- b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, (u16)~0x8000);
-
- b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004);
-
- if (nphy->bb_mult_save & 0x80000000) {
- tmp = nphy->bb_mult_save & 0xFFFF;
- b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
- nphy->bb_mult_save = 0;
- }
-
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, 0);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */
-static void b43_nphy_spur_workaround(struct b43_wldev *dev)
-{
- struct b43_phy_n *nphy = dev->phy.n;
-
- unsigned int channel;
- int tone[2] = { 57, 58 };
- u32 noise[2] = { 0x3FF, 0x3FF };
-
- B43_WARN_ON(dev->phy.rev < 3);
-
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, 1);
-
- /* FIXME: channel = radio_chanspec */
-
- if (nphy->gband_spurwar_en) {
- /* TODO: N PHY Adjust Analog Pfbw (7) */
- if (channel == 11 && dev->phy.is_40mhz)
- ; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/
- else
- ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
- /* TODO: N PHY Adjust CRS Min Power (0x1E) */
- }
-
- if (nphy->aband_spurwar_en) {
- if (channel == 54) {
- tone[0] = 0x20;
- noise[0] = 0x25F;
- } else if (channel == 38 || channel == 102 || channel == 118) {
- if (0 /* FIXME */) {
- tone[0] = 0x20;
- noise[0] = 0x21F;
- } else {
- tone[0] = 0;
- noise[0] = 0;
- }
- } else if (channel == 134) {
- tone[0] = 0x20;
- noise[0] = 0x21F;
- } else if (channel == 151) {
- tone[0] = 0x10;
- noise[0] = 0x23F;
- } else if (channel == 153 || channel == 161) {
- tone[0] = 0x30;
- noise[0] = 0x23F;
- } else {
- tone[0] = 0;
- noise[0] = 0;
- }
-
- if (!tone[0] && !noise[0])
- ; /* TODO: N PHY Adjust Min Noise Var(1, tone, noise)*/
- else
- ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
- }
-
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, 0);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
-static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev)
-{
- struct b43_phy_n *nphy = dev->phy.n;
- u8 i, j;
- u8 code;
-
- /* TODO: for PHY >= 3
- s8 *lna1_gain, *lna2_gain;
- u8 *gain_db, *gain_bits;
- u16 *rfseq_init;
- u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 };
- u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 };
- */
-
- u8 rfseq_events[3] = { 6, 8, 7 };
- u8 rfseq_delays[3] = { 10, 30, 1 };
-
- if (dev->phy.rev >= 3) {
- /* TODO */
- } else {
- /* Set Clip 2 detect */
- b43_phy_set(dev, B43_NPHY_C1_CGAINI,
- B43_NPHY_C1_CGAINI_CL2DETECT);
- b43_phy_set(dev, B43_NPHY_C2_CGAINI,
- B43_NPHY_C2_CGAINI_CL2DETECT);
-
- /* Set narrowband clip threshold */
- b43_phy_set(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84);
- b43_phy_set(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84);
-
- if (!dev->phy.is_40mhz) {
- /* Set dwell lengths */
- b43_phy_set(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B);
- b43_phy_set(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B);
- b43_phy_set(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009);
- b43_phy_set(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009);
- }
-
- /* Set wideband clip 2 threshold */
- b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
- ~B43_NPHY_C1_CLIPWBTHRES_CLIP2,
- 21);
- b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
- ~B43_NPHY_C2_CLIPWBTHRES_CLIP2,
- 21);
-
- if (!dev->phy.is_40mhz) {
- b43_phy_maskset(dev, B43_NPHY_C1_CGAINI,
- ~B43_NPHY_C1_CGAINI_GAINBKOFF, 0x1);
- b43_phy_maskset(dev, B43_NPHY_C2_CGAINI,
- ~B43_NPHY_C2_CGAINI_GAINBKOFF, 0x1);
- b43_phy_maskset(dev, B43_NPHY_C1_CCK_CGAINI,
- ~B43_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1);
- b43_phy_maskset(dev, B43_NPHY_C2_CCK_CGAINI,
- ~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1);
- }
-
- b43_phy_set(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
-
- if (nphy->gain_boost) {
- if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ &&
- dev->phy.is_40mhz)
- code = 4;
- else
- code = 5;
- } else {
- code = dev->phy.is_40mhz ? 6 : 7;
- }
-
- /* Set HPVGA2 index */
- b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN,
- ~B43_NPHY_C1_INITGAIN_HPVGA2,
- code << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT);
- b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN,
- ~B43_NPHY_C2_INITGAIN_HPVGA2,
- code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT);
-
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
- (code << 8 | 0x7C));
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
- (code << 8 | 0x7C));
-
- /* TODO: b43_nphy_adjust_lna_gain_table(dev); */
-
- if (nphy->elna_gain_config) {
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
-
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0C08);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
-
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
- (code << 8 | 0x74));
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
- (code << 8 | 0x74));
- }
-
- if (dev->phy.rev == 2) {
- for (i = 0; i < 4; i++) {
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
- (0x0400 * i) + 0x0020);
- for (j = 0; j < 21; j++)
- b43_phy_write(dev,
- B43_NPHY_TABLE_DATALO, 3 * j);
- }
-
- b43_nphy_set_rf_sequence(dev, 5,
- rfseq_events, rfseq_delays, 3);
- b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1,
- (u16)~B43_NPHY_OVER_DGAIN_CCKDGECV,
- 0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT);
-
- if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
- b43_phy_maskset(dev, B43_PHY_N(0xC5D),
- 0xFF80, 4);
- }
- }
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
-static void b43_nphy_workarounds(struct b43_wldev *dev)
-{
- struct ssb_bus *bus = dev->dev->bus;
- struct b43_phy *phy = &dev->phy;
- struct b43_phy_n *nphy = phy->n;
-
- u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 };
- u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 };
-
- u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
- u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
-
- if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
- b43_nphy_classifier(dev, 1, 0);
- else
- b43_nphy_classifier(dev, 1, 1);
-
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, 1);
-
- b43_phy_set(dev, B43_NPHY_IQFLIP,
- B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
-
- if (dev->phy.rev >= 3) {
- /* TODO */
- } else {
- if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
- nphy->band5g_pwrgain) {
- b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
- b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8);
- } else {
- b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
- b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
- }
-
- /* TODO: convert to b43_ntab_write? */
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2000);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A);
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2010);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A);
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2002);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA);
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2012);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA);
-
- if (dev->phy.rev < 2) {
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2008);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000);
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2018);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000);
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2007);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB);
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2017);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB);
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2006);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800);
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2016);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800);
- }
-
- b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
- b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
- b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
- b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
-
- if (bus->sprom.boardflags2_lo & 0x100 &&
- bus->boardinfo.type == 0x8B) {
- delays1[0] = 0x1;
- delays1[5] = 0x14;
- }
- b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
- b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
-
- b43_nphy_gain_crtl_workarounds(dev);
+ //TODO: Spectral management
+ b43_nphy_tables_init(dev);
- if (dev->phy.rev < 2) {
- if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
- ; /*TODO: b43_mhf(dev, 2, 0x0010, 0x0010, 3);*/
- } else if (dev->phy.rev == 2) {
- b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
- b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
- }
+ /* Clear all overrides */
+ b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
+ b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0);
+ b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0);
+ b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0);
+ b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0);
+ b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
+ ~(B43_NPHY_RFSEQMODE_CAOVER |
+ B43_NPHY_RFSEQMODE_TROVER));
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0);
- if (dev->phy.rev < 2)
- b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
- ~B43_NPHY_SCRAM_SIGCTL_SCM);
-
- /* Set phase track alpha and beta */
- b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
- b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
- b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
- b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
- b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
- b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
-
- b43_phy_mask(dev, B43_NPHY_PIL_DW1,
- (u16)~B43_NPHY_PIL_DW_64QAM);
- b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
- b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
- b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
-
- if (dev->phy.rev == 2)
- b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
- B43_NPHY_FINERX2_CGC_DECGC);
- }
+ tmp = (phy->rev < 2) ? 64 : 59;
+ b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
+ ~B43_NPHY_BPHY_CTL3_SCALE,
+ tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT);
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, 0);
-}
+ b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
+ b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */
-static int b43_nphy_load_samples(struct b43_wldev *dev,
- struct b43_c32 *samples, u16 len) {
- struct b43_phy_n *nphy = dev->phy.n;
- u16 i;
- u32 *data;
+ b43_phy_write(dev, B43_NPHY_TXREALFD, 184);
+ b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 200);
+ b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 80);
+ b43_phy_write(dev, B43_NPHY_C2_BCLIPBKOFF, 511);
- data = kzalloc(len * sizeof(u32), GFP_KERNEL);
- if (!data) {
- b43err(dev->wl, "allocation for samples loading failed\n");
- return -ENOMEM;
- }
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, 1);
+ //TODO MIMO-Config
+ //TODO Update TX/RX chain
- for (i = 0; i < len; i++) {
- data[i] = (samples[i].i & 0x3FF << 10);
- data[i] |= samples[i].q & 0x3FF;
+ if (phy->rev < 2) {
+ b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8);
+ b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4);
}
- b43_ntab_write_bulk(dev, B43_NTAB32(17, 0), len, data);
-
- kfree(data);
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, 0);
- return 0;
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */
-static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max,
- bool test)
-{
- int i;
- u16 bw, len, rot, angle;
- struct b43_c32 *samples;
-
+ b43_nphy_workarounds(dev);
+ b43_nphy_reset_cca(dev);
- bw = (dev->phy.is_40mhz) ? 40 : 20;
- len = bw << 3;
-
- if (test) {
- if (b43_phy_read(dev, B43_NPHY_BBCFG) & B43_NPHY_BBCFG_RSTRX)
- bw = 82;
- else
- bw = 80;
-
- if (dev->phy.is_40mhz)
- bw <<= 1;
-
- len = bw << 1;
- }
-
- samples = kzalloc(len * sizeof(struct b43_c32), GFP_KERNEL);
- if (!samples) {
- b43err(dev->wl, "allocation for samples generation failed\n");
- return 0;
- }
- rot = (((freq * 36) / bw) << 16) / 100;
- angle = 0;
-
- for (i = 0; i < len; i++) {
- samples[i] = b43_cordic(angle);
- angle += rot;
- samples[i].q = CORDIC_CONVERT(samples[i].q * max);
- samples[i].i = CORDIC_CONVERT(samples[i].i * max);
- }
-
- i = b43_nphy_load_samples(dev, samples, len);
- kfree(samples);
- return (i < 0) ? 0 : len;
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */
-static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
- u16 wait, bool iqmode, bool dac_test)
-{
- struct b43_phy_n *nphy = dev->phy.n;
- int i;
- u16 seq_mode;
- u32 tmp;
-
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, true);
-
- if ((nphy->bb_mult_save & 0x80000000) == 0) {
- tmp = b43_ntab_read(dev, B43_NTAB16(15, 87));
- nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000;
- }
-
- if (!dev->phy.is_40mhz)
- tmp = 0x6464;
- else
- tmp = 0x4747;
- b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
-
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, false);
-
- b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1));
-
- if (loops != 0xFFFF)
- b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, (loops - 1));
- else
- b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, loops);
-
- b43_phy_write(dev, B43_NPHY_SAMP_WAITCNT, wait);
-
- seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
-
- b43_phy_set(dev, B43_NPHY_RFSEQMODE, B43_NPHY_RFSEQMODE_CAOVER);
- if (iqmode) {
- b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
- b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000);
- } else {
- if (dac_test)
- b43_phy_write(dev, B43_NPHY_SAMP_CMD, 5);
- else
- b43_phy_write(dev, B43_NPHY_SAMP_CMD, 1);
- }
- for (i = 0; i < 100; i++) {
- if (b43_phy_read(dev, B43_NPHY_RFSEQST) & 1) {
- i = 0;
- break;
- }
- udelay(10);
- }
- if (i)
- b43err(dev->wl, "run samples timeout\n");
-
- b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
-}
-
-/*
- * Transmits a known value for LO calibration
- * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone
- */
-static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val,
- bool iqmode, bool dac_test)
-{
- u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test);
- if (samp == 0)
- return -1;
- b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test);
- return 0;
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */
-static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev)
-{
- struct b43_phy_n *nphy = dev->phy.n;
- int i, j;
- u32 tmp;
- u32 cur_real, cur_imag, real_part, imag_part;
-
- u16 buffer[7];
-
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, true);
-
- b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
-
- for (i = 0; i < 2; i++) {
- tmp = ((buffer[i * 2] & 0x3FF) << 10) |
- (buffer[i * 2 + 1] & 0x3FF);
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
- (((i + 26) << 10) | 320));
- for (j = 0; j < 128; j++) {
- b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
- ((tmp >> 16) & 0xFFFF));
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
- (tmp & 0xFFFF));
- }
- }
-
- for (i = 0; i < 2; i++) {
- tmp = buffer[5 + i];
- real_part = (tmp >> 8) & 0xFF;
- imag_part = (tmp & 0xFF);
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
- (((i + 26) << 10) | 448));
-
- if (dev->phy.rev >= 3) {
- cur_real = real_part;
- cur_imag = imag_part;
- tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF);
- }
-
- for (j = 0; j < 128; j++) {
- if (dev->phy.rev < 3) {
- cur_real = (real_part * loscale[j] + 128) >> 8;
- cur_imag = (imag_part * loscale[j] + 128) >> 8;
- tmp = ((cur_real & 0xFF) << 8) |
- (cur_imag & 0xFF);
- }
- b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
- ((tmp >> 16) & 0xFFFF));
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
- (tmp & 0xFFFF));
- }
- }
-
- if (dev->phy.rev >= 3) {
- b43_shm_write16(dev, B43_SHM_SHARED,
- B43_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF);
- b43_shm_write16(dev, B43_SHM_SHARED,
- B43_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF);
- }
-
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, false);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */
-static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
- u8 *events, u8 *delays, u8 length)
-{
- struct b43_phy_n *nphy = dev->phy.n;
- u8 i;
- u8 end = (dev->phy.rev >= 3) ? 0x1F : 0x0F;
- u16 offset1 = cmd << 4;
- u16 offset2 = offset1 + 0x80;
-
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, true);
-
- b43_ntab_write_bulk(dev, B43_NTAB8(7, offset1), length, events);
- b43_ntab_write_bulk(dev, B43_NTAB8(7, offset2), length, delays);
-
- for (i = length; i < 16; i++) {
- b43_ntab_write(dev, B43_NTAB8(7, offset1 + i), end);
- b43_ntab_write(dev, B43_NTAB8(7, offset2 + i), 1);
- }
-
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, false);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */
-static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
- enum b43_nphy_rf_sequence seq)
-{
- static const u16 trigger[] = {
- [B43_RFSEQ_RX2TX] = B43_NPHY_RFSEQTR_RX2TX,
- [B43_RFSEQ_TX2RX] = B43_NPHY_RFSEQTR_TX2RX,
- [B43_RFSEQ_RESET2RX] = B43_NPHY_RFSEQTR_RST2RX,
- [B43_RFSEQ_UPDATE_GAINH] = B43_NPHY_RFSEQTR_UPGH,
- [B43_RFSEQ_UPDATE_GAINL] = B43_NPHY_RFSEQTR_UPGL,
- [B43_RFSEQ_UPDATE_GAINU] = B43_NPHY_RFSEQTR_UPGU,
- };
- int i;
- u16 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
-
- B43_WARN_ON(seq >= ARRAY_SIZE(trigger));
-
- b43_phy_set(dev, B43_NPHY_RFSEQMODE,
- B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER);
- b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]);
- for (i = 0; i < 200; i++) {
- if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq]))
- goto ok;
- msleep(1);
- }
- b43err(dev->wl, "RF sequence status timeout\n");
-ok:
- b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
-static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
- u16 value, u8 core, bool off)
-{
- int i;
- u8 index = fls(field);
- u8 addr, en_addr, val_addr;
- /* we expect only one bit set */
- B43_WARN_ON(field & (~(1 << (index - 1))));
-
- if (dev->phy.rev >= 3) {
- const struct nphy_rf_control_override_rev3 *rf_ctrl;
- for (i = 0; i < 2; i++) {
- if (index == 0 || index == 16) {
- b43err(dev->wl,
- "Unsupported RF Ctrl Override call\n");
- return;
- }
-
- rf_ctrl = &tbl_rf_control_override_rev3[index - 1];
- en_addr = B43_PHY_N((i == 0) ?
- rf_ctrl->en_addr0 : rf_ctrl->en_addr1);
- val_addr = B43_PHY_N((i == 0) ?
- rf_ctrl->val_addr0 : rf_ctrl->val_addr1);
-
- if (off) {
- b43_phy_mask(dev, en_addr, ~(field));
- b43_phy_mask(dev, val_addr,
- ~(rf_ctrl->val_mask));
- } else {
- if (core == 0 || ((1 << core) & i) != 0) {
- b43_phy_set(dev, en_addr, field);
- b43_phy_maskset(dev, val_addr,
- ~(rf_ctrl->val_mask),
- (value << rf_ctrl->val_shift));
- }
- }
- }
- } else {
- const struct nphy_rf_control_override_rev2 *rf_ctrl;
- if (off) {
- b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~(field));
- value = 0;
- } else {
- b43_phy_set(dev, B43_NPHY_RFCTL_OVER, field);
- }
-
- for (i = 0; i < 2; i++) {
- if (index <= 1 || index == 16) {
- b43err(dev->wl,
- "Unsupported RF Ctrl Override call\n");
- return;
- }
-
- if (index == 2 || index == 10 ||
- (index >= 13 && index <= 15)) {
- core = 1;
- }
-
- rf_ctrl = &tbl_rf_control_override_rev2[index - 2];
- addr = B43_PHY_N((i == 0) ?
- rf_ctrl->addr0 : rf_ctrl->addr1);
-
- if ((core & (1 << i)) != 0)
- b43_phy_maskset(dev, addr, ~(rf_ctrl->bmask),
- (value << rf_ctrl->shift));
-
- b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1);
- b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
- B43_NPHY_RFCTL_CMD_START);
- udelay(1);
- b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 0xFFFE);
- }
- }
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */
-static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
- u16 value, u8 core)
-{
- u8 i, j;
- u16 reg, tmp, val;
-
- B43_WARN_ON(dev->phy.rev < 3);
- B43_WARN_ON(field > 4);
-
- for (i = 0; i < 2; i++) {
- if ((core == 1 && i == 1) || (core == 2 && !i))
- continue;
-
- reg = (i == 0) ?
- B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2;
- b43_phy_mask(dev, reg, 0xFBFF);
-
- switch (field) {
- case 0:
- b43_phy_write(dev, reg, 0);
- b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
- break;
- case 1:
- if (!i) {
- b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC1,
- 0xFC3F, (value << 6));
- b43_phy_maskset(dev, B43_NPHY_TXF_40CO_B1S1,
- 0xFFFE, 1);
- b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
- B43_NPHY_RFCTL_CMD_START);
- for (j = 0; j < 100; j++) {
- if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_START) {
- j = 0;
- break;
- }
- udelay(10);
- }
- if (j)
- b43err(dev->wl,
- "intc override timeout\n");
- b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1,
- 0xFFFE);
- } else {
- b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC2,
- 0xFC3F, (value << 6));
- b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
- 0xFFFE, 1);
- b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
- B43_NPHY_RFCTL_CMD_RXTX);
- for (j = 0; j < 100; j++) {
- if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_RXTX) {
- j = 0;
- break;
- }
- udelay(10);
- }
- if (j)
- b43err(dev->wl,
- "intc override timeout\n");
- b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
- 0xFFFE);
- }
- break;
- case 2:
- if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
- tmp = 0x0020;
- val = value << 5;
- } else {
- tmp = 0x0010;
- val = value << 4;
- }
- b43_phy_maskset(dev, reg, ~tmp, val);
- break;
- case 3:
- if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
- tmp = 0x0001;
- val = value;
- } else {
- tmp = 0x0004;
- val = value << 2;
- }
- b43_phy_maskset(dev, reg, ~tmp, val);
- break;
- case 4:
- if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
- tmp = 0x0002;
- val = value << 1;
- } else {
- tmp = 0x0008;
- val = value << 3;
- }
- b43_phy_maskset(dev, reg, ~tmp, val);
- break;
- }
- }
-}
-
-static void b43_nphy_bphy_init(struct b43_wldev *dev)
-{
- unsigned int i;
- u16 val;
-
- val = 0x1E1F;
- for (i = 0; i < 14; i++) {
- b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
- val -= 0x202;
- }
- val = 0x3E3F;
- for (i = 0; i < 16; i++) {
- b43_phy_write(dev, B43_PHY_N_BMODE(0x97 + i), val);
- val -= 0x202;
- }
- b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
-static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
- s8 offset, u8 core, u8 rail, u8 type)
-{
- u16 tmp;
- bool core1or5 = (core == 1) || (core == 5);
- bool core2or5 = (core == 2) || (core == 5);
-
- offset = clamp_val(offset, -32, 31);
- tmp = ((scale & 0x3F) << 8) | (offset & 0x3F);
-
- if (core1or5 && (rail == 0) && (type == 2))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
- if (core1or5 && (rail == 1) && (type == 2))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
- if (core2or5 && (rail == 0) && (type == 2))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
- if (core2or5 && (rail == 1) && (type == 2))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
- if (core1or5 && (rail == 0) && (type == 0))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
- if (core1or5 && (rail == 1) && (type == 0))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
- if (core2or5 && (rail == 0) && (type == 0))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
- if (core2or5 && (rail == 1) && (type == 0))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
- if (core1or5 && (rail == 0) && (type == 1))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
- if (core1or5 && (rail == 1) && (type == 1))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
- if (core2or5 && (rail == 0) && (type == 1))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
- if (core2or5 && (rail == 1) && (type == 1))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
- if (core1or5 && (rail == 0) && (type == 6))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
- if (core1or5 && (rail == 1) && (type == 6))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
- if (core2or5 && (rail == 0) && (type == 6))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
- if (core2or5 && (rail == 1) && (type == 6))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
- if (core1or5 && (rail == 0) && (type == 3))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
- if (core1or5 && (rail == 1) && (type == 3))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
- if (core2or5 && (rail == 0) && (type == 3))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
- if (core2or5 && (rail == 1) && (type == 3))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
- if (core1or5 && (type == 4))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
- if (core2or5 && (type == 4))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
- if (core1or5 && (type == 5))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
- if (core2or5 && (type == 5))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
-}
-
-static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
-{
- u16 val;
-
- if (type < 3)
- val = 0;
- else if (type == 6)
- val = 1;
- else if (type == 3)
- val = 2;
- else
- val = 3;
-
- val = (val << 12) | (val << 14);
- b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val);
- b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val);
-
- if (type < 3) {
- b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF,
- (type + 1) << 4);
- b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF,
- (type + 1) << 4);
- }
-
- /* TODO use some definitions */
- if (code == 0) {
- b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, 0);
- if (type < 3) {
- b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFEC7, 0);
- b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xEFDC, 0);
- b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFFFE, 0);
- udelay(20);
- b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xFFFE, 0);
- }
- } else {
- b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF,
- 0x3000);
- if (type < 3) {
- b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
- 0xFEC7, 0x0180);
- b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
- 0xEFDC, (code << 1 | 0x1021));
- b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFFFE, 0x1);
- udelay(20);
- b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xFFFE, 0);
- }
- }
-}
-
-static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
-{
- struct b43_phy_n *nphy = dev->phy.n;
- u8 i;
- u16 reg, val;
-
- if (code == 0) {
- b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, 0xFDFF);
- b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, 0xFDFF);
- b43_phy_mask(dev, B43_NPHY_AFECTL_C1, 0xFCFF);
- b43_phy_mask(dev, B43_NPHY_AFECTL_C2, 0xFCFF);
- b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S0, 0xFFDF);
- b43_phy_mask(dev, B43_NPHY_TXF_40CO_B32S1, 0xFFDF);
- b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3);
- b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3);
- } else {
- for (i = 0; i < 2; i++) {
- if ((code == 1 && i == 1) || (code == 2 && !i))
- continue;
-
- reg = (i == 0) ?
- B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER;
- b43_phy_maskset(dev, reg, 0xFDFF, 0x0200);
-
- if (type < 3) {
- reg = (i == 0) ?
- B43_NPHY_AFECTL_C1 :
- B43_NPHY_AFECTL_C2;
- b43_phy_maskset(dev, reg, 0xFCFF, 0);
-
- reg = (i == 0) ?
- B43_NPHY_RFCTL_LUT_TRSW_UP1 :
- B43_NPHY_RFCTL_LUT_TRSW_UP2;
- b43_phy_maskset(dev, reg, 0xFFC3, 0);
-
- if (type == 0)
- val = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 4 : 8;
- else if (type == 1)
- val = 16;
- else
- val = 32;
- b43_phy_set(dev, reg, val);
-
- reg = (i == 0) ?
- B43_NPHY_TXF_40CO_B1S0 :
- B43_NPHY_TXF_40CO_B32S1;
- b43_phy_set(dev, reg, 0x0020);
- } else {
- if (type == 6)
- val = 0x0100;
- else if (type == 3)
- val = 0x0200;
- else
- val = 0x0300;
-
- reg = (i == 0) ?
- B43_NPHY_AFECTL_C1 :
- B43_NPHY_AFECTL_C2;
-
- b43_phy_maskset(dev, reg, 0xFCFF, val);
- b43_phy_maskset(dev, reg, 0xF3FF, val << 2);
-
- if (type != 3 && type != 6) {
- enum ieee80211_band band =
- b43_current_band(dev->wl);
-
- if ((nphy->ipa2g_on &&
- band == IEEE80211_BAND_2GHZ) ||
- (nphy->ipa5g_on &&
- band == IEEE80211_BAND_5GHZ))
- val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
- else
- val = 0x11;
- reg = (i == 0) ? 0x2000 : 0x3000;
- reg |= B2055_PADDRV;
- b43_radio_write16(dev, reg, val);
-
- reg = (i == 0) ?
- B43_NPHY_AFECTL_OVER1 :
- B43_NPHY_AFECTL_OVER;
- b43_phy_set(dev, reg, 0x0200);
- }
- }
- }
- }
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
-static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
-{
- if (dev->phy.rev >= 3)
- b43_nphy_rev3_rssi_select(dev, code, type);
- else
- b43_nphy_rev2_rssi_select(dev, code, type);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
-static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf)
-{
- int i;
- for (i = 0; i < 2; i++) {
- if (type == 2) {
- if (i == 0) {
- b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM,
- 0xFC, buf[0]);
- b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
- 0xFC, buf[1]);
- } else {
- b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM,
- 0xFC, buf[2 * i]);
- b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
- 0xFC, buf[2 * i + 1]);
- }
- } else {
- if (i == 0)
- b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
- 0xF3, buf[0] << 2);
- else
- b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
- 0xF3, buf[2 * i + 1] << 2);
- }
- }
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
-static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
- u8 nsamp)
-{
- int i;
- int out;
- u16 save_regs_phy[9];
- u16 s[2];
-
- if (dev->phy.rev >= 3) {
- save_regs_phy[0] = b43_phy_read(dev,
- B43_NPHY_RFCTL_LUT_TRSW_UP1);
- save_regs_phy[1] = b43_phy_read(dev,
- B43_NPHY_RFCTL_LUT_TRSW_UP2);
- save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
- save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
- save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
- save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
- save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0);
- save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1);
- }
-
- b43_nphy_rssi_select(dev, 5, type);
-
- if (dev->phy.rev < 2) {
- save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL);
- b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5);
- }
-
- for (i = 0; i < 4; i++)
- buf[i] = 0;
-
- for (i = 0; i < nsamp; i++) {
- if (dev->phy.rev < 2) {
- s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT);
- s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT);
- } else {
- s[0] = b43_phy_read(dev, B43_NPHY_RSSI1);
- s[1] = b43_phy_read(dev, B43_NPHY_RSSI2);
- }
-
- buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2;
- buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2;
- buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2;
- buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2;
- }
- out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 |
- (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF);
-
- if (dev->phy.rev < 2)
- b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]);
-
- if (dev->phy.rev >= 3) {
- b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1,
- save_regs_phy[0]);
- b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2,
- save_regs_phy[1]);
- b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[2]);
- b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[3]);
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]);
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]);
- b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]);
- b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]);
- }
-
- return out;
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
-static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
-{
- int i, j;
- u8 state[4];
- u8 code, val;
- u16 class, override;
- u8 regs_save_radio[2];
- u16 regs_save_phy[2];
- s8 offset[4];
-
- u16 clip_state[2];
- u16 clip_off[2] = { 0xFFFF, 0xFFFF };
- s32 results_min[4] = { };
- u8 vcm_final[4] = { };
- s32 results[4][4] = { };
- s32 miniq[4][2] = { };
-
- if (type == 2) {
- code = 0;
- val = 6;
- } else if (type < 2) {
- code = 25;
- val = 4;
- } else {
- B43_WARN_ON(1);
- return;
- }
-
- class = b43_nphy_classifier(dev, 0, 0);
- b43_nphy_classifier(dev, 7, 4);
- b43_nphy_read_clip_detection(dev, clip_state);
- b43_nphy_write_clip_detection(dev, clip_off);
-
- if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
- override = 0x140;
- else
- override = 0x110;
-
- regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
- regs_save_radio[0] = b43_radio_read16(dev, B2055_C1_PD_RXTX);
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override);
- b43_radio_write16(dev, B2055_C1_PD_RXTX, val);
-
- regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
- regs_save_radio[1] = b43_radio_read16(dev, B2055_C2_PD_RXTX);
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override);
- b43_radio_write16(dev, B2055_C2_PD_RXTX, val);
-
- state[0] = b43_radio_read16(dev, B2055_C1_PD_RSSIMISC) & 0x07;
- state[1] = b43_radio_read16(dev, B2055_C2_PD_RSSIMISC) & 0x07;
- b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8);
- b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8);
- state[2] = b43_radio_read16(dev, B2055_C1_SP_RSSI) & 0x07;
- state[3] = b43_radio_read16(dev, B2055_C2_SP_RSSI) & 0x07;
-
- b43_nphy_rssi_select(dev, 5, type);
- b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 0, type);
- b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 1, type);
-
- for (i = 0; i < 4; i++) {
- u8 tmp[4];
- for (j = 0; j < 4; j++)
- tmp[j] = i;
- if (type != 1)
- b43_nphy_set_rssi_2055_vcm(dev, type, tmp);
- b43_nphy_poll_rssi(dev, type, results[i], 8);
- if (type < 2)
- for (j = 0; j < 2; j++)
- miniq[i][j] = min(results[i][2 * j],
- results[i][2 * j + 1]);
- }
-
- for (i = 0; i < 4; i++) {
- s32 mind = 40;
- u8 minvcm = 0;
- s32 minpoll = 249;
- s32 curr;
- for (j = 0; j < 4; j++) {
- if (type == 2)
- curr = abs(results[j][i]);
- else
- curr = abs(miniq[j][i / 2] - code * 8);
-
- if (curr < mind) {
- mind = curr;
- minvcm = j;
- }
-
- if (results[j][i] < minpoll)
- minpoll = results[j][i];
- }
- results_min[i] = minpoll;
- vcm_final[i] = minvcm;
- }
-
- if (type != 1)
- b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final);
-
- for (i = 0; i < 4; i++) {
- offset[i] = (code * 8) - results[vcm_final[i]][i];
-
- if (offset[i] < 0)
- offset[i] = -((abs(offset[i]) + 4) / 8);
- else
- offset[i] = (offset[i] + 4) / 8;
-
- if (results_min[i] == 248)
- offset[i] = code - 32;
-
- if (i % 2 == 0)
- b43_nphy_scale_offset_rssi(dev, 0, offset[i], 1, 0,
- type);
- else
- b43_nphy_scale_offset_rssi(dev, 0, offset[i], 2, 1,
- type);
- }
-
- b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]);
- b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[1]);
-
- switch (state[2]) {
- case 1:
- b43_nphy_rssi_select(dev, 1, 2);
- break;
- case 4:
- b43_nphy_rssi_select(dev, 1, 0);
- break;
- case 2:
- b43_nphy_rssi_select(dev, 1, 1);
- break;
- default:
- b43_nphy_rssi_select(dev, 1, 1);
- break;
- }
-
- switch (state[3]) {
- case 1:
- b43_nphy_rssi_select(dev, 2, 2);
- break;
- case 4:
- b43_nphy_rssi_select(dev, 2, 0);
- break;
- default:
- b43_nphy_rssi_select(dev, 2, 1);
- break;
- }
-
- b43_nphy_rssi_select(dev, 0, type);
-
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]);
- b43_radio_write16(dev, B2055_C1_PD_RXTX, regs_save_radio[0]);
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]);
- b43_radio_write16(dev, B2055_C2_PD_RXTX, regs_save_radio[1]);
-
- b43_nphy_classifier(dev, 7, class);
- b43_nphy_write_clip_detection(dev, clip_state);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
-static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
-{
- /* TODO */
-}
-
-/*
- * RSSI Calibration
- * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal
- */
-static void b43_nphy_rssi_cal(struct b43_wldev *dev)
-{
- if (dev->phy.rev >= 3) {
- b43_nphy_rev3_rssi_cal(dev);
- } else {
- b43_nphy_rev2_rssi_cal(dev, 2);
- b43_nphy_rev2_rssi_cal(dev, 0);
- b43_nphy_rev2_rssi_cal(dev, 1);
- }
-}
-
-/*
- * Restore RSSI Calibration
- * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal
- */
-static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
-{
- struct b43_phy_n *nphy = dev->phy.n;
-
- u16 *rssical_radio_regs = NULL;
- u16 *rssical_phy_regs = NULL;
-
- if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
- if (!nphy->rssical_chanspec_2G)
- return;
- rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
- rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
- } else {
- if (!nphy->rssical_chanspec_5G)
- return;
- rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
- rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
- }
-
- /* TODO use some definitions */
- b43_radio_maskset(dev, 0x602B, 0xE3, rssical_radio_regs[0]);
- b43_radio_maskset(dev, 0x702B, 0xE3, rssical_radio_regs[1]);
-
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]);
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]);
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]);
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]);
-
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]);
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]);
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]);
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]);
-
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]);
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]);
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]);
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */
-static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
-{
- if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
- if (dev->phy.rev >= 6) {
- /* TODO If the chip is 47162
- return txpwrctrl_tx_gain_ipa_rev5 */
- return txpwrctrl_tx_gain_ipa_rev6;
- } else if (dev->phy.rev >= 5) {
- return txpwrctrl_tx_gain_ipa_rev5;
- } else {
- return txpwrctrl_tx_gain_ipa;
- }
- } else {
- return txpwrctrl_tx_gain_ipa_5g;
- }
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */
-static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
-{
- struct b43_phy_n *nphy = dev->phy.n;
- u16 *save = nphy->tx_rx_cal_radio_saveregs;
- u16 tmp;
- u8 offset, i;
-
- if (dev->phy.rev >= 3) {
- for (i = 0; i < 2; i++) {
- tmp = (i == 0) ? 0x2000 : 0x3000;
- offset = i * 11;
-
- save[offset + 0] = b43_radio_read16(dev, B2055_CAL_RVARCTL);
- save[offset + 1] = b43_radio_read16(dev, B2055_CAL_LPOCTL);
- save[offset + 2] = b43_radio_read16(dev, B2055_CAL_TS);
- save[offset + 3] = b43_radio_read16(dev, B2055_CAL_RCCALRTS);
- save[offset + 4] = b43_radio_read16(dev, B2055_CAL_RCALRTS);
- save[offset + 5] = b43_radio_read16(dev, B2055_PADDRV);
- save[offset + 6] = b43_radio_read16(dev, B2055_XOCTL1);
- save[offset + 7] = b43_radio_read16(dev, B2055_XOCTL2);
- save[offset + 8] = b43_radio_read16(dev, B2055_XOREGUL);
- save[offset + 9] = b43_radio_read16(dev, B2055_XOMISC);
- save[offset + 10] = b43_radio_read16(dev, B2055_PLL_LFC1);
-
- if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
- b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x0A);
- b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
- b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
- b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
- b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
- if (nphy->ipa5g_on) {
- b43_radio_write16(dev, tmp | B2055_PADDRV, 4);
- b43_radio_write16(dev, tmp | B2055_XOCTL1, 1);
- } else {
- b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
- b43_radio_write16(dev, tmp | B2055_XOCTL1, 0x2F);
- }
- b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
- } else {
- b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x06);
- b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
- b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
- b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
- b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
- b43_radio_write16(dev, tmp | B2055_XOCTL1, 0);
- if (nphy->ipa2g_on) {
- b43_radio_write16(dev, tmp | B2055_PADDRV, 6);
- b43_radio_write16(dev, tmp | B2055_XOCTL2,
- (dev->phy.rev < 5) ? 0x11 : 0x01);
- } else {
- b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
- b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
- }
- }
- b43_radio_write16(dev, tmp | B2055_XOREGUL, 0);
- b43_radio_write16(dev, tmp | B2055_XOMISC, 0);
- b43_radio_write16(dev, tmp | B2055_PLL_LFC1, 0);
- }
- } else {
- save[0] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL1);
- b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL1, 0x29);
-
- save[1] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL2);
- b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL2, 0x54);
-
- save[2] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL1);
- b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL1, 0x29);
-
- save[3] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL2);
- b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL2, 0x54);
-
- save[3] = b43_radio_read16(dev, B2055_C1_PWRDET_RXTX);
- save[4] = b43_radio_read16(dev, B2055_C2_PWRDET_RXTX);
-
- if (!(b43_phy_read(dev, B43_NPHY_BANDCTL) &
- B43_NPHY_BANDCTL_5GHZ)) {
- b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x04);
- b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x04);
- } else {
- b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x20);
- b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x20);
- }
-
- if (dev->phy.rev < 2) {
- b43_radio_set(dev, B2055_C1_TX_BB_MXGM, 0x20);
- b43_radio_set(dev, B2055_C2_TX_BB_MXGM, 0x20);
- } else {
- b43_radio_mask(dev, B2055_C1_TX_BB_MXGM, ~0x20);
- b43_radio_mask(dev, B2055_C2_TX_BB_MXGM, ~0x20);
- }
- }
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */
-static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core,
- struct nphy_txgains target,
- struct nphy_iqcal_params *params)
-{
- int i, j, indx;
- u16 gain;
-
- if (dev->phy.rev >= 3) {
- params->txgm = target.txgm[core];
- params->pga = target.pga[core];
- params->pad = target.pad[core];
- params->ipa = target.ipa[core];
- params->cal_gain = (params->txgm << 12) | (params->pga << 8) |
- (params->pad << 4) | (params->ipa);
- for (j = 0; j < 5; j++)
- params->ncorr[j] = 0x79;
- } else {
- gain = (target.pad[core]) | (target.pga[core] << 4) |
- (target.txgm[core] << 8);
-
- indx = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ?
- 1 : 0;
- for (i = 0; i < 9; i++)
- if (tbl_iqcal_gainparams[indx][i][0] == gain)
- break;
- i = min(i, 8);
-
- params->txgm = tbl_iqcal_gainparams[indx][i][1];
- params->pga = tbl_iqcal_gainparams[indx][i][2];
- params->pad = tbl_iqcal_gainparams[indx][i][3];
- params->cal_gain = (params->txgm << 7) | (params->pga << 4) |
- (params->pad << 2);
- for (j = 0; j < 4; j++)
- params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j];
- }
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */
-static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core)
-{
- struct b43_phy_n *nphy = dev->phy.n;
- int i;
- u16 scale, entry;
-
- u16 tmp = nphy->txcal_bbmult;
- if (core == 0)
- tmp >>= 8;
- tmp &= 0xff;
-
- for (i = 0; i < 18; i++) {
- scale = (ladder_lo[i].percent * tmp) / 100;
- entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env;
- b43_ntab_write(dev, B43_NTAB16(15, i), entry);
-
- scale = (ladder_iq[i].percent * tmp) / 100;
- entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env;
- b43_ntab_write(dev, B43_NTAB16(15, i + 32), entry);
- }
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */
-static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev)
-{
- int i;
- for (i = 0; i < 15; i++)
- b43_phy_write(dev, B43_PHY_N(0x2C5 + i),
- tbl_tx_filter_coef_rev4[2][i]);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */
-static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev)
-{
- int i, j;
- /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */
- u16 offset[] = { 0x186, 0x195, 0x2C5 };
-
- for (i = 0; i < 3; i++)
- for (j = 0; j < 15; j++)
- b43_phy_write(dev, B43_PHY_N(offset[i] + j),
- tbl_tx_filter_coef_rev4[i][j]);
-
- if (dev->phy.is_40mhz) {
- for (j = 0; j < 15; j++)
- b43_phy_write(dev, B43_PHY_N(offset[0] + j),
- tbl_tx_filter_coef_rev4[3][j]);
- } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
- for (j = 0; j < 15; j++)
- b43_phy_write(dev, B43_PHY_N(offset[0] + j),
- tbl_tx_filter_coef_rev4[5][j]);
- }
-
- if (dev->phy.channel == 14)
- for (j = 0; j < 15; j++)
- b43_phy_write(dev, B43_PHY_N(offset[0] + j),
- tbl_tx_filter_coef_rev4[6][j]);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */
-static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
-{
- struct b43_phy_n *nphy = dev->phy.n;
-
- u16 curr_gain[2];
- struct nphy_txgains target;
- const u32 *table = NULL;
-
- if (nphy->txpwrctrl == 0) {
- int i;
-
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, true);
- b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, curr_gain);
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, false);
-
- for (i = 0; i < 2; ++i) {
- if (dev->phy.rev >= 3) {
- target.ipa[i] = curr_gain[i] & 0x000F;
- target.pad[i] = (curr_gain[i] & 0x00F0) >> 4;
- target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
- target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;
- } else {
- target.ipa[i] = curr_gain[i] & 0x0003;
- target.pad[i] = (curr_gain[i] & 0x000C) >> 2;
- target.pga[i] = (curr_gain[i] & 0x0070) >> 4;
- target.txgm[i] = (curr_gain[i] & 0x0380) >> 7;
- }
- }
- } else {
- int i;
- u16 index[2];
- index[0] = (b43_phy_read(dev, B43_NPHY_C1_TXPCTL_STAT) &
- B43_NPHY_TXPCTL_STAT_BIDX) >>
- B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;
- index[1] = (b43_phy_read(dev, B43_NPHY_C2_TXPCTL_STAT) &
- B43_NPHY_TXPCTL_STAT_BIDX) >>
- B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;
-
- for (i = 0; i < 2; ++i) {
- if (dev->phy.rev >= 3) {
- enum ieee80211_band band =
- b43_current_band(dev->wl);
-
- if ((nphy->ipa2g_on &&
- band == IEEE80211_BAND_2GHZ) ||
- (nphy->ipa5g_on &&
- band == IEEE80211_BAND_5GHZ)) {
- table = b43_nphy_get_ipa_gain_table(dev);
- } else {
- if (band == IEEE80211_BAND_5GHZ) {
- if (dev->phy.rev == 3)
- table = b43_ntab_tx_gain_rev3_5ghz;
- else if (dev->phy.rev == 4)
- table = b43_ntab_tx_gain_rev4_5ghz;
- else
- table = b43_ntab_tx_gain_rev5plus_5ghz;
- } else {
- table = b43_ntab_tx_gain_rev3plus_2ghz;
- }
- }
-
- target.ipa[i] = (table[index[i]] >> 16) & 0xF;
- target.pad[i] = (table[index[i]] >> 20) & 0xF;
- target.pga[i] = (table[index[i]] >> 24) & 0xF;
- target.txgm[i] = (table[index[i]] >> 28) & 0xF;
- } else {
- table = b43_ntab_tx_gain_rev0_1_2;
-
- target.ipa[i] = (table[index[i]] >> 16) & 0x3;
- target.pad[i] = (table[index[i]] >> 18) & 0x3;
- target.pga[i] = (table[index[i]] >> 20) & 0x7;
- target.txgm[i] = (table[index[i]] >> 23) & 0x7;
- }
- }
- }
-
- return target;
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */
-static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev)
-{
- u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
-
- if (dev->phy.rev >= 3) {
- b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[0]);
- b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[3]);
- b43_phy_write(dev, B43_NPHY_BBCFG, regs[4]);
- b43_ntab_write(dev, B43_NTAB16(8, 3), regs[5]);
- b43_ntab_write(dev, B43_NTAB16(8, 19), regs[6]);
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[7]);
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[8]);
- b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
- b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
- b43_nphy_reset_cca(dev);
- } else {
- b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, regs[0]);
- b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, regs[1]);
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
- b43_ntab_write(dev, B43_NTAB16(8, 2), regs[3]);
- b43_ntab_write(dev, B43_NTAB16(8, 18), regs[4]);
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[5]);
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[6]);
- }
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */
-static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
-{
- u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
- u16 tmp;
-
- regs[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
- regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
- if (dev->phy.rev >= 3) {
- b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0xF0FF, 0x0A00);
- b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0xF0FF, 0x0A00);
-
- tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
- regs[2] = tmp;
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, tmp | 0x0600);
-
- tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
- regs[3] = tmp;
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x0600);
-
- regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG);
- b43_phy_mask(dev, B43_NPHY_BBCFG, (u16)~B43_NPHY_BBCFG_RSTRX);
-
- tmp = b43_ntab_read(dev, B43_NTAB16(8, 3));
- regs[5] = tmp;
- b43_ntab_write(dev, B43_NTAB16(8, 3), 0);
-
- tmp = b43_ntab_read(dev, B43_NTAB16(8, 19));
- regs[6] = tmp;
- b43_ntab_write(dev, B43_NTAB16(8, 19), 0);
- regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
- regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
-
- b43_nphy_rf_control_intc_override(dev, 2, 1, 3);
- b43_nphy_rf_control_intc_override(dev, 1, 2, 1);
- b43_nphy_rf_control_intc_override(dev, 1, 8, 2);
-
- regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
- regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
- b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
- b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
- } else {
- b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000);
- b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000);
- tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
- regs[2] = tmp;
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x3000);
- tmp = b43_ntab_read(dev, B43_NTAB16(8, 2));
- regs[3] = tmp;
- tmp |= 0x2000;
- b43_ntab_write(dev, B43_NTAB16(8, 2), tmp);
- tmp = b43_ntab_read(dev, B43_NTAB16(8, 18));
- regs[4] = tmp;
- tmp |= 0x2000;
- b43_ntab_write(dev, B43_NTAB16(8, 18), tmp);
- regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
- regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
- if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
- tmp = 0x0180;
- else
- tmp = 0x0120;
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
- }
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */
-static void b43_nphy_save_cal(struct b43_wldev *dev)
-{
- struct b43_phy_n *nphy = dev->phy.n;
-
- struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
- u16 *txcal_radio_regs = NULL;
- u8 *iqcal_chanspec;
- u16 *table = NULL;
-
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, 1);
-
- if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
- rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
- txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
- iqcal_chanspec = &nphy->iqcal_chanspec_2G;
- table = nphy->cal_cache.txcal_coeffs_2G;
- } else {
- rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
- txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
- iqcal_chanspec = &nphy->iqcal_chanspec_5G;
- table = nphy->cal_cache.txcal_coeffs_5G;
- }
-
- b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs);
- /* TODO use some definitions */
- if (dev->phy.rev >= 3) {
- txcal_radio_regs[0] = b43_radio_read(dev, 0x2021);
- txcal_radio_regs[1] = b43_radio_read(dev, 0x2022);
- txcal_radio_regs[2] = b43_radio_read(dev, 0x3021);
- txcal_radio_regs[3] = b43_radio_read(dev, 0x3022);
- txcal_radio_regs[4] = b43_radio_read(dev, 0x2023);
- txcal_radio_regs[5] = b43_radio_read(dev, 0x2024);
- txcal_radio_regs[6] = b43_radio_read(dev, 0x3023);
- txcal_radio_regs[7] = b43_radio_read(dev, 0x3024);
- } else {
- txcal_radio_regs[0] = b43_radio_read(dev, 0x8B);
- txcal_radio_regs[1] = b43_radio_read(dev, 0xBA);
- txcal_radio_regs[2] = b43_radio_read(dev, 0x8D);
- txcal_radio_regs[3] = b43_radio_read(dev, 0xBC);
- }
- *iqcal_chanspec = nphy->radio_chanspec;
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 8, table);
-
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, 0);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */
-static void b43_nphy_restore_cal(struct b43_wldev *dev)
-{
- struct b43_phy_n *nphy = dev->phy.n;
-
- u16 coef[4];
- u16 *loft = NULL;
- u16 *table = NULL;
-
- int i;
- u16 *txcal_radio_regs = NULL;
- struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
-
- if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
- if (nphy->iqcal_chanspec_2G == 0)
- return;
- table = nphy->cal_cache.txcal_coeffs_2G;
- loft = &nphy->cal_cache.txcal_coeffs_2G[5];
- } else {
- if (nphy->iqcal_chanspec_5G == 0)
- return;
- table = nphy->cal_cache.txcal_coeffs_5G;
- loft = &nphy->cal_cache.txcal_coeffs_5G[5];
- }
-
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, table);
-
- for (i = 0; i < 4; i++) {
- if (dev->phy.rev >= 3)
- table[i] = coef[i];
- else
- coef[i] = 0;
- }
-
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, coef);
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, loft);
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, loft);
-
- if (dev->phy.rev < 2)
- b43_nphy_tx_iq_workaround(dev);
-
- if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
- txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
- rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
- } else {
- txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
- rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
- }
-
- /* TODO use some definitions */
- if (dev->phy.rev >= 3) {
- b43_radio_write(dev, 0x2021, txcal_radio_regs[0]);
- b43_radio_write(dev, 0x2022, txcal_radio_regs[1]);
- b43_radio_write(dev, 0x3021, txcal_radio_regs[2]);
- b43_radio_write(dev, 0x3022, txcal_radio_regs[3]);
- b43_radio_write(dev, 0x2023, txcal_radio_regs[4]);
- b43_radio_write(dev, 0x2024, txcal_radio_regs[5]);
- b43_radio_write(dev, 0x3023, txcal_radio_regs[6]);
- b43_radio_write(dev, 0x3024, txcal_radio_regs[7]);
- } else {
- b43_radio_write(dev, 0x8B, txcal_radio_regs[0]);
- b43_radio_write(dev, 0xBA, txcal_radio_regs[1]);
- b43_radio_write(dev, 0x8D, txcal_radio_regs[2]);
- b43_radio_write(dev, 0xBC, txcal_radio_regs[3]);
- }
- b43_nphy_rx_iq_coeffs(dev, true, rxcal_coeffs);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */
-static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
- struct nphy_txgains target,
- bool full, bool mphase)
-{
- struct b43_phy_n *nphy = dev->phy.n;
- int i;
- int error = 0;
- int freq;
- bool avoid = false;
- u8 length;
- u16 tmp, core, type, count, max, numb, last, cmd;
- const u16 *table;
- bool phy6or5x;
-
- u16 buffer[11];
- u16 diq_start = 0;
- u16 save[2];
- u16 gain[2];
- struct nphy_iqcal_params params[2];
- bool updated[2] = { };
-
- b43_nphy_stay_in_carrier_search(dev, true);
-
- if (dev->phy.rev >= 4) {
- avoid = nphy->hang_avoid;
- nphy->hang_avoid = 0;
- }
-
- b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
-
- for (i = 0; i < 2; i++) {
- b43_nphy_iq_cal_gain_params(dev, i, target, ¶ms[i]);
- gain[i] = params[i].cal_gain;
- }
-
- b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain);
-
- b43_nphy_tx_cal_radio_setup(dev);
- b43_nphy_tx_cal_phy_setup(dev);
-
- phy6or5x = dev->phy.rev >= 6 ||
- (dev->phy.rev == 5 && nphy->ipa2g_on &&
- b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ);
- if (phy6or5x) {
- if (dev->phy.is_40mhz) {
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
- tbl_tx_iqlo_cal_loft_ladder_40);
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
- tbl_tx_iqlo_cal_iqimb_ladder_40);
- } else {
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
- tbl_tx_iqlo_cal_loft_ladder_20);
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
- tbl_tx_iqlo_cal_iqimb_ladder_20);
- }
- }
-
- b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9);
-
- if (!dev->phy.is_40mhz)
- freq = 2500;
- else
- freq = 5000;
-
- if (nphy->mphase_cal_phase_id > 2)
- b43_nphy_run_samples(dev, (dev->phy.is_40mhz ? 40 : 20) * 8,
- 0xFFFF, 0, true, false);
- else
- error = b43_nphy_tx_tone(dev, freq, 250, true, false);
-
- if (error == 0) {
- if (nphy->mphase_cal_phase_id > 2) {
- table = nphy->mphase_txcal_bestcoeffs;
- length = 11;
- if (dev->phy.rev < 3)
- length -= 2;
- } else {
- if (!full && nphy->txiqlocal_coeffsvalid) {
- table = nphy->txiqlocal_bestc;
- length = 11;
- if (dev->phy.rev < 3)
- length -= 2;
- } else {
- full = true;
- if (dev->phy.rev >= 3) {
- table = tbl_tx_iqlo_cal_startcoefs_nphyrev3;
- length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3;
- } else {
- table = tbl_tx_iqlo_cal_startcoefs;
- length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS;
- }
- }
- }
-
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, table);
-
- if (full) {
- if (dev->phy.rev >= 3)
- max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3;
- else
- max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL;
- } else {
- if (dev->phy.rev >= 3)
- max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3;
- else
- max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL;
- }
-
- if (mphase) {
- count = nphy->mphase_txcal_cmdidx;
- numb = min(max,
- (u16)(count + nphy->mphase_txcal_numcmds));
- } else {
- count = 0;
- numb = max;
- }
-
- for (; count < numb; count++) {
- if (full) {
- if (dev->phy.rev >= 3)
- cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count];
- else
- cmd = tbl_tx_iqlo_cal_cmds_fullcal[count];
- } else {
- if (dev->phy.rev >= 3)
- cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count];
- else
- cmd = tbl_tx_iqlo_cal_cmds_recal[count];
- }
-
- core = (cmd & 0x3000) >> 12;
- type = (cmd & 0x0F00) >> 8;
-
- if (phy6or5x && updated[core] == 0) {
- b43_nphy_update_tx_cal_ladder(dev, core);
- updated[core] = 1;
- }
-
- tmp = (params[core].ncorr[type] << 8) | 0x66;
- b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDNNUM, tmp);
-
- if (type == 1 || type == 3 || type == 4) {
- buffer[0] = b43_ntab_read(dev,
- B43_NTAB16(15, 69 + core));
- diq_start = buffer[0];
- buffer[0] = 0;
- b43_ntab_write(dev, B43_NTAB16(15, 69 + core),
- 0);
- }
-
- b43_phy_write(dev, B43_NPHY_IQLOCAL_CMD, cmd);
- for (i = 0; i < 2000; i++) {
- tmp = b43_phy_read(dev, B43_NPHY_IQLOCAL_CMD);
- if (tmp & 0xC000)
- break;
- udelay(10);
- }
-
- b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
- buffer);
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length,
- buffer);
-
- if (type == 1 || type == 3 || type == 4)
- buffer[0] = diq_start;
- }
-
- if (mphase)
- nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb;
-
- last = (dev->phy.rev < 3) ? 6 : 7;
-
- if (!mphase || nphy->mphase_cal_phase_id == last) {
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 96), 4, buffer);
- b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 4, buffer);
- if (dev->phy.rev < 3) {
- buffer[0] = 0;
- buffer[1] = 0;
- buffer[2] = 0;
- buffer[3] = 0;
- }
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
- buffer);
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 101), 2,
- buffer);
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
- buffer);
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,
- buffer);
- length = 11;
- if (dev->phy.rev < 3)
- length -= 2;
- b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
- nphy->txiqlocal_bestc);
- nphy->txiqlocal_coeffsvalid = true;
- /* TODO: Set nphy->txiqlocal_chanspec to
- the current channel */
- } else {
- length = 11;
- if (dev->phy.rev < 3)
- length -= 2;
- b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
- nphy->mphase_txcal_bestcoeffs);
- }
-
- b43_nphy_stop_playback(dev);
- b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0);
- }
-
- b43_nphy_tx_cal_phy_cleanup(dev);
- b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
-
- if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last))
- b43_nphy_tx_iq_workaround(dev);
-
- if (dev->phy.rev >= 4)
- nphy->hang_avoid = avoid;
-
- b43_nphy_stay_in_carrier_search(dev, false);
-
- return error;
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */
-static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev)
-{
- struct b43_phy_n *nphy = dev->phy.n;
- u8 i;
- u16 buffer[7];
- bool equal = true;
-
- if (!nphy->txiqlocal_coeffsvalid || 1 /* FIXME */)
- return;
-
- b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
- for (i = 0; i < 4; i++) {
- if (buffer[i] != nphy->txiqlocal_bestc[i]) {
- equal = false;
- break;
- }
- }
-
- if (!equal) {
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4,
- nphy->txiqlocal_bestc);
- for (i = 0; i < 4; i++)
- buffer[i] = 0;
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
- buffer);
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
- &nphy->txiqlocal_bestc[5]);
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,
- &nphy->txiqlocal_bestc[5]);
- }
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */
-static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
- struct nphy_txgains target, u8 type, bool debug)
-{
- struct b43_phy_n *nphy = dev->phy.n;
- int i, j, index;
- u8 rfctl[2];
- u8 afectl_core;
- u16 tmp[6];
- u16 cur_hpf1, cur_hpf2, cur_lna;
- u32 real, imag;
- enum ieee80211_band band;
-
- u8 use;
- u16 cur_hpf;
- u16 lna[3] = { 3, 3, 1 };
- u16 hpf1[3] = { 7, 2, 0 };
- u16 hpf2[3] = { 2, 0, 0 };
- u32 power[3] = { };
- u16 gain_save[2];
- u16 cal_gain[2];
- struct nphy_iqcal_params cal_params[2];
- struct nphy_iq_est est;
- int ret = 0;
- bool playtone = true;
- int desired = 13;
-
- b43_nphy_stay_in_carrier_search(dev, 1);
-
- if (dev->phy.rev < 2)
- b43_nphy_reapply_tx_cal_coeffs(dev);
- b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
- for (i = 0; i < 2; i++) {
- b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]);
- cal_gain[i] = cal_params[i].cal_gain;
- }
- b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, cal_gain);
-
- for (i = 0; i < 2; i++) {
- if (i == 0) {
- rfctl[0] = B43_NPHY_RFCTL_INTC1;
- rfctl[1] = B43_NPHY_RFCTL_INTC2;
- afectl_core = B43_NPHY_AFECTL_C1;
- } else {
- rfctl[0] = B43_NPHY_RFCTL_INTC2;
- rfctl[1] = B43_NPHY_RFCTL_INTC1;
- afectl_core = B43_NPHY_AFECTL_C2;
- }
-
- tmp[1] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
- tmp[2] = b43_phy_read(dev, afectl_core);
- tmp[3] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
- tmp[4] = b43_phy_read(dev, rfctl[0]);
- tmp[5] = b43_phy_read(dev, rfctl[1]);
-
- b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
- (u16)~B43_NPHY_RFSEQCA_RXDIS,
- ((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
- b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
- (1 - i));
- b43_phy_set(dev, afectl_core, 0x0006);
- b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0006);
-
- band = b43_current_band(dev->wl);
-
- if (nphy->rxcalparams & 0xFF000000) {
- if (band == IEEE80211_BAND_5GHZ)
- b43_phy_write(dev, rfctl[0], 0x140);
- else
- b43_phy_write(dev, rfctl[0], 0x110);
- } else {
- if (band == IEEE80211_BAND_5GHZ)
- b43_phy_write(dev, rfctl[0], 0x180);
- else
- b43_phy_write(dev, rfctl[0], 0x120);
- }
-
- if (band == IEEE80211_BAND_5GHZ)
- b43_phy_write(dev, rfctl[1], 0x148);
- else
- b43_phy_write(dev, rfctl[1], 0x114);
-
- if (nphy->rxcalparams & 0x10000) {
- b43_radio_maskset(dev, B2055_C1_GENSPARE2, 0xFC,
- (i + 1));
- b43_radio_maskset(dev, B2055_C2_GENSPARE2, 0xFC,
- (2 - i));
- }
-
- for (j = 0; i < 4; j++) {
- if (j < 3) {
- cur_lna = lna[j];
- cur_hpf1 = hpf1[j];
- cur_hpf2 = hpf2[j];
- } else {
- if (power[1] > 10000) {
- use = 1;
- cur_hpf = cur_hpf1;
- index = 2;
- } else {
- if (power[0] > 10000) {
- use = 1;
- cur_hpf = cur_hpf1;
- index = 1;
- } else {
- index = 0;
- use = 2;
- cur_hpf = cur_hpf2;
- }
- }
- cur_lna = lna[index];
- cur_hpf1 = hpf1[index];
- cur_hpf2 = hpf2[index];
- cur_hpf += desired - hweight32(power[index]);
- cur_hpf = clamp_val(cur_hpf, 0, 10);
- if (use == 1)
- cur_hpf1 = cur_hpf;
- else
- cur_hpf2 = cur_hpf;
- }
-
- tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) |
- (cur_lna << 2));
- b43_nphy_rf_control_override(dev, 0x400, tmp[0], 3,
- false);
- b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
- b43_nphy_stop_playback(dev);
-
- if (playtone) {
- ret = b43_nphy_tx_tone(dev, 4000,
- (nphy->rxcalparams & 0xFFFF),
- false, false);
- playtone = false;
- } else {
- b43_nphy_run_samples(dev, 160, 0xFFFF, 0,
- false, false);
- }
-
- if (ret == 0) {
- if (j < 3) {
- b43_nphy_rx_iq_est(dev, &est, 1024, 32,
- false);
- if (i == 0) {
- real = est.i0_pwr;
- imag = est.q0_pwr;
- } else {
- real = est.i1_pwr;
- imag = est.q1_pwr;
- }
- power[i] = ((real + imag) / 1024) + 1;
- } else {
- b43_nphy_calc_rx_iq_comp(dev, 1 << i);
- }
- b43_nphy_stop_playback(dev);
- }
-
- if (ret != 0)
- break;
- }
-
- b43_radio_mask(dev, B2055_C1_GENSPARE2, 0xFC);
- b43_radio_mask(dev, B2055_C2_GENSPARE2, 0xFC);
- b43_phy_write(dev, rfctl[1], tmp[5]);
- b43_phy_write(dev, rfctl[0], tmp[4]);
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp[3]);
- b43_phy_write(dev, afectl_core, tmp[2]);
- b43_phy_write(dev, B43_NPHY_RFSEQCA, tmp[1]);
-
- if (ret != 0)
- break;
- }
-
- b43_nphy_rf_control_override(dev, 0x400, 0, 3, true);
- b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
- b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
-
- b43_nphy_stay_in_carrier_search(dev, 0);
-
- return ret;
-}
-
-static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev,
- struct nphy_txgains target, u8 type, bool debug)
-{
- return -1;
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */
-static int b43_nphy_cal_rx_iq(struct b43_wldev *dev,
- struct nphy_txgains target, u8 type, bool debug)
-{
- if (dev->phy.rev >= 3)
- return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug);
- else
- return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug);
-}
-
-/*
- * Init N-PHY
- * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N
- */
-int b43_phy_initn(struct b43_wldev *dev)
-{
- struct ssb_bus *bus = dev->dev->bus;
- struct b43_phy *phy = &dev->phy;
- struct b43_phy_n *nphy = phy->n;
- u8 tx_pwr_state;
- struct nphy_txgains target;
- u16 tmp;
- enum ieee80211_band tmp2;
- bool do_rssi_cal;
-
- u16 clip[2];
- bool do_cal = false;
-
- if ((dev->phy.rev >= 3) &&
- (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
- (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) {
- chipco_set32(&dev->dev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40);
- }
- nphy->deaf_count = 0;
- b43_nphy_tables_init(dev);
- nphy->crsminpwr_adjusted = false;
- nphy->noisevars_adjusted = false;
-
- /* Clear all overrides */
- if (dev->phy.rev >= 3) {
- b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0);
- b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
- b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0);
- b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0);
- } else {
- b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
- }
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0);
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0);
- if (dev->phy.rev < 6) {
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0);
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0);
- }
- b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
- ~(B43_NPHY_RFSEQMODE_CAOVER |
- B43_NPHY_RFSEQMODE_TROVER));
- if (dev->phy.rev >= 3)
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, 0);
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0);
-
- if (dev->phy.rev <= 2) {
- tmp = (dev->phy.rev == 2) ? 0x3B : 0x40;
- b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
- ~B43_NPHY_BPHY_CTL3_SCALE,
- tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT);
- }
- b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
- b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
-
- if (bus->sprom.boardflags2_lo & 0x100 ||
- (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
- bus->boardinfo.type == 0x8B))
- b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
- else
- b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);
- b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 0xC8);
- b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50);
- b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30);
-
- b43_nphy_update_mimo_config(dev, nphy->preamble_override);
- b43_nphy_update_txrx_chain(dev);
-
- if (phy->rev < 2) {
- b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8);
- b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4);
- }
-
- tmp2 = b43_current_band(dev->wl);
- if ((nphy->ipa2g_on && tmp2 == IEEE80211_BAND_2GHZ) ||
- (nphy->ipa5g_on && tmp2 == IEEE80211_BAND_5GHZ)) {
- b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1);
- b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F,
- nphy->papd_epsilon_offset[0] << 7);
- b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1);
- b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F,
- nphy->papd_epsilon_offset[1] << 7);
- b43_nphy_int_pa_set_tx_dig_filters(dev);
- } else if (phy->rev >= 5) {
- b43_nphy_ext_pa_set_tx_dig_filters(dev);
- }
-
- b43_nphy_workarounds(dev);
-
- /* Reset CCA, in init code it differs a little from standard way */
- b43_nphy_bmac_clock_fgc(dev, 1);
- tmp = b43_phy_read(dev, B43_NPHY_BBCFG);
- b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA);
- b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA);
- b43_nphy_bmac_clock_fgc(dev, 0);
-
- /* TODO N PHY MAC PHY Clock Set with argument 1 */
-
- b43_nphy_pa_override(dev, false);
+ ssb_write32(dev->dev, SSB_TMSLOW,
+ ssb_read32(dev->dev, SSB_TMSLOW) | B43_TMSLOW_MACPHYCLKEN);
b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
- b43_nphy_pa_override(dev, true);
-
- b43_nphy_classifier(dev, 0, 0);
- b43_nphy_read_clip_detection(dev, clip);
- tx_pwr_state = nphy->txpwrctrl;
- /* TODO N PHY TX power control with argument 0
- (turning off power control) */
- /* TODO Fix the TX Power Settings */
- /* TODO N PHY TX Power Control Idle TSSI */
- /* TODO N PHY TX Power Control Setup */
-
- if (phy->rev >= 3) {
- /* TODO */
- } else {
- b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128,
- b43_ntab_tx_gain_rev0_1_2);
- b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128,
- b43_ntab_tx_gain_rev0_1_2);
- }
-
- if (nphy->phyrxchain != 3)
- ;/* TODO N PHY RX Core Set State with phyrxchain as argument */
- if (nphy->mphase_cal_phase_id > 0)
- ;/* TODO PHY Periodic Calibration Multi-Phase Restart */
-
- do_rssi_cal = false;
- if (phy->rev >= 3) {
- if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
- do_rssi_cal = (nphy->rssical_chanspec_2G == 0);
- else
- do_rssi_cal = (nphy->rssical_chanspec_5G == 0);
-
- if (do_rssi_cal)
- b43_nphy_rssi_cal(dev);
- else
- b43_nphy_restore_rssi_cal(dev);
- } else {
- b43_nphy_rssi_cal(dev);
- }
-
- if (!((nphy->measure_hold & 0x6) != 0)) {
- if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
- do_cal = (nphy->iqcal_chanspec_2G == 0);
- else
- do_cal = (nphy->iqcal_chanspec_5G == 0);
-
- if (nphy->mute)
- do_cal = false;
-
- if (do_cal) {
- target = b43_nphy_get_tx_gains(dev);
-
- if (nphy->antsel_type == 2)
- ;/*TODO NPHY Superswitch Init with argument 1*/
- if (nphy->perical != 2) {
- b43_nphy_rssi_cal(dev);
- if (phy->rev >= 3) {
- nphy->cal_orig_pwr_idx[0] =
- nphy->txpwrindex[0].index_internal;
- nphy->cal_orig_pwr_idx[1] =
- nphy->txpwrindex[1].index_internal;
- /* TODO N PHY Pre Calibrate TX Gain */
- target = b43_nphy_get_tx_gains(dev);
- }
- }
- }
- }
-
- if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) {
- if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0)
- b43_nphy_save_cal(dev);
- else if (nphy->mphase_cal_phase_id == 0)
- ;/* N PHY Periodic Calibration with argument 3 */
- } else {
- b43_nphy_restore_cal(dev);
- }
- b43_nphy_tx_pwr_ctrl_coef_setup(dev);
- /* TODO N PHY TX Power Control Enable with argument tx_pwr_state */
- b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015);
- b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320);
- if (phy->rev >= 3 && phy->rev <= 6)
- b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0014);
- b43_nphy_tx_lp_fbw(dev);
- if (phy->rev >= 3)
- b43_nphy_spur_workaround(dev);
+ b43_phy_read(dev, B43_NPHY_CLASSCTL); /* dummy read */
+ //TODO read core1/2 clip1 thres regs
+
+ if (1 /* FIXME Band is 2.4GHz */)
+ b43_nphy_bphy_init(dev);
+ //TODO disable TX power control
+ //TODO Fix the TX power settings
+ //TODO Init periodic calibration with reason 3
+ b43_nphy_rssi_cal(dev, 2);
+ b43_nphy_rssi_cal(dev, 0);
+ b43_nphy_rssi_cal(dev, 1);
+ //TODO get TX gain
+ //TODO init superswitch
+ //TODO calibrate LO
+ //TODO idle TSSI TX pctl
+ //TODO TX power control power setup
+ //TODO table writes
+ //TODO TX power control coefficients
+ //TODO enable TX power control
+ //TODO control antenna selection
+ //TODO init radar detection
+ //TODO reset channel if changed
b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n");
return 0;
diff --git a/trunk/drivers/net/wireless/b43/phy_n.h b/trunk/drivers/net/wireless/b43/phy_n.h
index 403aad3f894f..1749aef4147d 100644
--- a/trunk/drivers/net/wireless/b43/phy_n.h
+++ b/trunk/drivers/net/wireless/b43/phy_n.h
@@ -231,7 +231,6 @@
#define B43_NPHY_C2_TXIQ_COMP_OFF B43_PHY_N(0x088) /* Core 2 TX I/Q comp offset */
#define B43_NPHY_C1_TXCTL B43_PHY_N(0x08B) /* Core 1 TX control */
#define B43_NPHY_C2_TXCTL B43_PHY_N(0x08C) /* Core 2 TX control */
-#define B43_NPHY_AFECTL_OVER1 B43_PHY_N(0x08F) /* AFE control override 1 */
#define B43_NPHY_SCRAM_SIGCTL B43_PHY_N(0x090) /* Scram signal control */
#define B43_NPHY_SCRAM_SIGCTL_INITST 0x007F /* Initial state value */
#define B43_NPHY_SCRAM_SIGCTL_INITST_SHIFT 0
@@ -706,10 +705,6 @@
#define B43_NPHY_TXPCTL_INIT B43_PHY_N(0x222) /* TX power controll init */
#define B43_NPHY_TXPCTL_INIT_PIDXI1 0x00FF /* Power index init 1 */
#define B43_NPHY_TXPCTL_INIT_PIDXI1_SHIFT 0
-#define B43_NPHY_PAPD_EN0 B43_PHY_N(0x297) /* PAPD Enable0 TBD */
-#define B43_NPHY_EPS_TABLE_ADJ0 B43_PHY_N(0x298) /* EPS Table Adj0 TBD */
-#define B43_NPHY_PAPD_EN1 B43_PHY_N(0x29B) /* PAPD Enable1 TBD */
-#define B43_NPHY_EPS_TABLE_ADJ1 B43_PHY_N(0x29C) /* EPS Table Adj1 TBD */
@@ -924,99 +919,8 @@
struct b43_wldev;
-struct b43_phy_n_iq_comp {
- s16 a0;
- s16 b0;
- s16 a1;
- s16 b1;
-};
-
-struct b43_phy_n_rssical_cache {
- u16 rssical_radio_regs_2G[2];
- u16 rssical_phy_regs_2G[12];
-
- u16 rssical_radio_regs_5G[2];
- u16 rssical_phy_regs_5G[12];
-};
-
-struct b43_phy_n_cal_cache {
- u16 txcal_radio_regs_2G[8];
- u16 txcal_coeffs_2G[8];
- struct b43_phy_n_iq_comp rxcal_coeffs_2G;
-
- u16 txcal_radio_regs_5G[8];
- u16 txcal_coeffs_5G[8];
- struct b43_phy_n_iq_comp rxcal_coeffs_5G;
-};
-
-struct b43_phy_n_txpwrindex {
- s8 index;
- s8 index_internal;
- s8 index_internal_save;
- u16 AfectrlOverride;
- u16 AfeCtrlDacGain;
- u16 rad_gain;
- u8 bbmult;
- u16 iqcomp_a;
- u16 iqcomp_b;
- u16 locomp;
-};
-
struct b43_phy_n {
- u8 antsel_type;
- u8 cal_orig_pwr_idx[2];
- u8 measure_hold;
- u8 phyrxchain;
- u8 perical;
- u32 deaf_count;
- u32 rxcalparams;
- bool hang_avoid;
- bool mute;
- u16 papd_epsilon_offset[2];
- s32 preamble_override;
- u32 bb_mult_save;
- u16 radio_chanspec;
-
- bool gain_boost;
- bool elna_gain_config;
- bool band5g_pwrgain;
-
- u8 mphase_cal_phase_id;
- u16 mphase_txcal_cmdidx;
- u16 mphase_txcal_numcmds;
- u16 mphase_txcal_bestcoeffs[11];
-
- u8 txpwrctrl;
- u16 txcal_bbmult;
- u16 txiqlocal_bestc[11];
- bool txiqlocal_coeffsvalid;
- struct b43_phy_n_txpwrindex txpwrindex[2];
-
- u8 txrx_chain;
- u16 tx_rx_cal_phy_saveregs[11];
- u16 tx_rx_cal_radio_saveregs[22];
-
- u16 rfctrl_intc1_save;
- u16 rfctrl_intc2_save;
-
- u16 classifier_state;
- u16 clip_state[2];
-
- bool aband_spurwar_en;
- bool gband_spurwar_en;
-
- bool ipa2g_on;
- u8 iqcal_chanspec_2G;
- u8 rssical_chanspec_2G;
-
- bool ipa5g_on;
- u8 iqcal_chanspec_5G;
- u8 rssical_chanspec_5G;
-
- struct b43_phy_n_rssical_cache rssical_cache;
- struct b43_phy_n_cal_cache cal_cache;
- bool crsminpwr_adjusted;
- bool noisevars_adjusted;
+ //TODO lots of missing stuff
};
diff --git a/trunk/drivers/net/wireless/b43/pio.c b/trunk/drivers/net/wireless/b43/pio.c
index a6062c3e89a5..c01b8e02412f 100644
--- a/trunk/drivers/net/wireless/b43/pio.c
+++ b/trunk/drivers/net/wireless/b43/pio.c
@@ -559,6 +559,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
b43err(dev->wl, "PIO transmission failure\n");
goto out;
}
+ q->nr_tx_packets++;
B43_WARN_ON(q->buffer_used > q->buffer_size);
if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) ||
@@ -604,6 +605,22 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
}
}
+void b43_pio_get_tx_stats(struct b43_wldev *dev,
+ struct ieee80211_tx_queue_stats *stats)
+{
+ const int nr_queues = dev->wl->hw->queues;
+ struct b43_pio_txqueue *q;
+ int i;
+
+ for (i = 0; i < nr_queues; i++) {
+ q = select_queue_by_priority(dev, i);
+
+ stats[i].len = B43_PIO_MAX_NR_TXPACKETS - q->free_packet_slots;
+ stats[i].limit = B43_PIO_MAX_NR_TXPACKETS;
+ stats[i].count = q->nr_tx_packets;
+ }
+}
+
/* Returns whether we should fetch another frame. */
static bool pio_rx_frame(struct b43_pio_rxqueue *q)
{
diff --git a/trunk/drivers/net/wireless/b43/pio.h b/trunk/drivers/net/wireless/b43/pio.h
index 1e516147424f..7dd649c9ddad 100644
--- a/trunk/drivers/net/wireless/b43/pio.h
+++ b/trunk/drivers/net/wireless/b43/pio.h
@@ -55,6 +55,8 @@
#define B43_PIO_MAX_NR_TXPACKETS 32
+#ifdef CONFIG_B43_PIO
+
struct b43_pio_txpacket {
/* Pointer to the TX queue we belong to. */
struct b43_pio_txqueue *queue;
@@ -90,6 +92,9 @@ struct b43_pio_txqueue {
struct b43_pio_txpacket packets[B43_PIO_MAX_NR_TXPACKETS];
struct list_head packets_list;
+ /* Total number of transmitted packets. */
+ unsigned int nr_tx_packets;
+
/* Shortcut to the 802.11 core revision. This is to
* avoid horrible pointer dereferencing in the fastpaths. */
u8 rev;
@@ -157,9 +162,49 @@ void b43_pio_free(struct b43_wldev *dev);
int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb);
void b43_pio_handle_txstatus(struct b43_wldev *dev,
const struct b43_txstatus *status);
+void b43_pio_get_tx_stats(struct b43_wldev *dev,
+ struct ieee80211_tx_queue_stats *stats);
void b43_pio_rx(struct b43_pio_rxqueue *q);
void b43_pio_tx_suspend(struct b43_wldev *dev);
void b43_pio_tx_resume(struct b43_wldev *dev);
+
+#else /* CONFIG_B43_PIO */
+
+
+static inline int b43_pio_init(struct b43_wldev *dev)
+{
+ return 0;
+}
+static inline void b43_pio_free(struct b43_wldev *dev)
+{
+}
+static inline void b43_pio_stop(struct b43_wldev *dev)
+{
+}
+static inline int b43_pio_tx(struct b43_wldev *dev,
+ struct sk_buff *skb)
+{
+ return 0;
+}
+static inline void b43_pio_handle_txstatus(struct b43_wldev *dev,
+ const struct b43_txstatus *status)
+{
+}
+static inline void b43_pio_get_tx_stats(struct b43_wldev *dev,
+ struct ieee80211_tx_queue_stats *stats)
+{
+}
+static inline void b43_pio_rx(struct b43_pio_rxqueue *q)
+{
+}
+static inline void b43_pio_tx_suspend(struct b43_wldev *dev)
+{
+}
+static inline void b43_pio_tx_resume(struct b43_wldev *dev)
+{
+}
+
+#endif /* CONFIG_B43_PIO */
#endif /* B43_PIO_H_ */
diff --git a/trunk/drivers/net/wireless/b43/tables_nphy.c b/trunk/drivers/net/wireless/b43/tables_nphy.c
index a00d509150f7..4e2336315545 100644
--- a/trunk/drivers/net/wireless/b43/tables_nphy.c
+++ b/trunk/drivers/net/wireless/b43/tables_nphy.c
@@ -1336,7 +1336,7 @@ b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel)
}
-static const u8 b43_ntab_adjustpower0[] = {
+const u8 b43_ntab_adjustpower0[] = {
0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
@@ -1355,7 +1355,7 @@ static const u8 b43_ntab_adjustpower0[] = {
0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F,
};
-static const u8 b43_ntab_adjustpower1[] = {
+const u8 b43_ntab_adjustpower1[] = {
0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
@@ -1374,11 +1374,11 @@ static const u8 b43_ntab_adjustpower1[] = {
0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F,
};
-static const u16 b43_ntab_bdi[] = {
+const u16 b43_ntab_bdi[] = {
0x0070, 0x0126, 0x012C, 0x0246, 0x048D, 0x04D2,
};
-static const u32 b43_ntab_channelest[] = {
+const u32 b43_ntab_channelest[] = {
0x44444444, 0x44444444, 0x44444444, 0x44444444,
0x44444444, 0x44444444, 0x44444444, 0x44444444,
0x10101010, 0x10101010, 0x10101010, 0x10101010,
@@ -1405,7 +1405,7 @@ static const u32 b43_ntab_channelest[] = {
0x10101010, 0x10101010, 0x10101010, 0x10101010,
};
-static const u8 b43_ntab_estimatepowerlt0[] = {
+const u8 b43_ntab_estimatepowerlt0[] = {
0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49,
0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41,
0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39,
@@ -1416,7 +1416,7 @@ static const u8 b43_ntab_estimatepowerlt0[] = {
0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11,
};
-static const u8 b43_ntab_estimatepowerlt1[] = {
+const u8 b43_ntab_estimatepowerlt1[] = {
0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49,
0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41,
0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39,
@@ -1427,14 +1427,14 @@ static const u8 b43_ntab_estimatepowerlt1[] = {
0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11,
};
-static const u8 b43_ntab_framelookup[] = {
+const u8 b43_ntab_framelookup[] = {
0x02, 0x04, 0x14, 0x14, 0x03, 0x05, 0x16, 0x16,
0x0A, 0x0C, 0x1C, 0x1C, 0x0B, 0x0D, 0x1E, 0x1E,
0x06, 0x08, 0x18, 0x18, 0x07, 0x09, 0x1A, 0x1A,
0x0E, 0x10, 0x20, 0x28, 0x0F, 0x11, 0x22, 0x2A,
};
-static const u32 b43_ntab_framestruct[] = {
+const u32 b43_ntab_framestruct[] = {
0x08004A04, 0x00100000, 0x01000A05, 0x00100020,
0x09804506, 0x00100030, 0x09804507, 0x00100030,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -1645,7 +1645,7 @@ static const u32 b43_ntab_framestruct[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
-static const u32 b43_ntab_gainctl0[] = {
+const u32 b43_ntab_gainctl0[] = {
0x007F003F, 0x007E013F, 0x007D023E, 0x007C033E,
0x007B043D, 0x007A053D, 0x0079063C, 0x0078073C,
0x0077083B, 0x0076093B, 0x00750A3A, 0x00740B3A,
@@ -1680,7 +1680,7 @@ static const u32 b43_ntab_gainctl0[] = {
0x00030C01, 0x00020D01, 0x00010E00, 0x00000F00,
};
-static const u32 b43_ntab_gainctl1[] = {
+const u32 b43_ntab_gainctl1[] = {
0x007F003F, 0x007E013F, 0x007D023E, 0x007C033E,
0x007B043D, 0x007A053D, 0x0079063C, 0x0078073C,
0x0077083B, 0x0076093B, 0x00750A3A, 0x00740B3A,
@@ -1715,12 +1715,12 @@ static const u32 b43_ntab_gainctl1[] = {
0x00030C01, 0x00020D01, 0x00010E00, 0x00000F00,
};
-static const u32 b43_ntab_intlevel[] = {
+const u32 b43_ntab_intlevel[] = {
0x00802070, 0x0671188D, 0x0A60192C, 0x0A300E46,
0x00C1188D, 0x080024D2, 0x00000070,
};
-static const u32 b43_ntab_iqlt0[] = {
+const u32 b43_ntab_iqlt0[] = {
0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
@@ -1755,7 +1755,7 @@ static const u32 b43_ntab_iqlt0[] = {
0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
};
-static const u32 b43_ntab_iqlt1[] = {
+const u32 b43_ntab_iqlt1[] = {
0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
@@ -1790,7 +1790,7 @@ static const u32 b43_ntab_iqlt1[] = {
0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
};
-static const u16 b43_ntab_loftlt0[] = {
+const u16 b43_ntab_loftlt0[] = {
0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
@@ -1815,7 +1815,7 @@ static const u16 b43_ntab_loftlt0[] = {
0x0002, 0x0103,
};
-static const u16 b43_ntab_loftlt1[] = {
+const u16 b43_ntab_loftlt1[] = {
0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
@@ -1840,7 +1840,7 @@ static const u16 b43_ntab_loftlt1[] = {
0x0002, 0x0103,
};
-static const u8 b43_ntab_mcs[] = {
+const u8 b43_ntab_mcs[] = {
0x00, 0x08, 0x0A, 0x10, 0x12, 0x19, 0x1A, 0x1C,
0x40, 0x48, 0x4A, 0x50, 0x52, 0x59, 0x5A, 0x5C,
0x80, 0x88, 0x8A, 0x90, 0x92, 0x99, 0x9A, 0x9C,
@@ -1859,7 +1859,7 @@ static const u8 b43_ntab_mcs[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
-static const u32 b43_ntab_noisevar10[] = {
+const u32 b43_ntab_noisevar10[] = {
0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
@@ -1926,7 +1926,7 @@ static const u32 b43_ntab_noisevar10[] = {
0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
};
-static const u32 b43_ntab_noisevar11[] = {
+const u32 b43_ntab_noisevar11[] = {
0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
@@ -1993,7 +1993,7 @@ static const u32 b43_ntab_noisevar11[] = {
0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
};
-static const u16 b43_ntab_pilot[] = {
+const u16 b43_ntab_pilot[] = {
0xFF08, 0xFF08, 0xFF08, 0xFF08, 0xFF08, 0xFF08,
0xFF08, 0xFF08, 0x80D5, 0x80D5, 0x80D5, 0x80D5,
0x80D5, 0x80D5, 0x80D5, 0x80D5, 0xFF0A, 0xFF82,
@@ -2011,12 +2011,12 @@ static const u16 b43_ntab_pilot[] = {
0xF0A0, 0xF028, 0xFFFF, 0xFFFF,
};
-static const u32 b43_ntab_pilotlt[] = {
+const u32 b43_ntab_pilotlt[] = {
0x76540123, 0x62407351, 0x76543201, 0x76540213,
0x76540123, 0x76430521,
};
-static const u32 b43_ntab_tdi20a0[] = {
+const u32 b43_ntab_tdi20a0[] = {
0x00091226, 0x000A1429, 0x000B56AD, 0x000C58B0,
0x000D5AB3, 0x000E9CB6, 0x000F9EBA, 0x0000C13D,
0x00020301, 0x00030504, 0x00040708, 0x0005090B,
@@ -2033,7 +2033,7 @@ static const u32 b43_ntab_tdi20a0[] = {
0x00000000, 0x00000000, 0x00000000,
};
-static const u32 b43_ntab_tdi20a1[] = {
+const u32 b43_ntab_tdi20a1[] = {
0x00014B26, 0x00028D29, 0x000393AD, 0x00049630,
0x0005D833, 0x0006DA36, 0x00099C3A, 0x000A9E3D,
0x000BC081, 0x000CC284, 0x000DC488, 0x000F068B,
@@ -2050,7 +2050,7 @@ static const u32 b43_ntab_tdi20a1[] = {
0x00000000, 0x00000000, 0x00000000,
};
-static const u32 b43_ntab_tdi40a0[] = {
+const u32 b43_ntab_tdi40a0[] = {
0x0011A346, 0x00136CCF, 0x0014F5D9, 0x001641E2,
0x0017CB6B, 0x00195475, 0x001B2383, 0x001CAD0C,
0x001E7616, 0x0000821F, 0x00020BA8, 0x0003D4B2,
@@ -2081,7 +2081,7 @@ static const u32 b43_ntab_tdi40a0[] = {
0x00000000, 0x00000000,
};
-static const u32 b43_ntab_tdi40a1[] = {
+const u32 b43_ntab_tdi40a1[] = {
0x001EDB36, 0x000129CA, 0x0002B353, 0x00047CDD,
0x0005C8E6, 0x000791EF, 0x00091BF9, 0x000AAA07,
0x000C3391, 0x000DFD1A, 0x00120923, 0x0013D22D,
@@ -2112,7 +2112,7 @@ static const u32 b43_ntab_tdi40a1[] = {
0x00000000, 0x00000000,
};
-static const u32 b43_ntab_tdtrn[] = {
+const u32 b43_ntab_tdtrn[] = {
0x061C061C, 0x0050EE68, 0xF592FE36, 0xFE5212F6,
0x00000C38, 0xFE5212F6, 0xF592FE36, 0x0050EE68,
0x061C061C, 0xEE680050, 0xFE36F592, 0x12F6FE52,
@@ -2291,7 +2291,7 @@ static const u32 b43_ntab_tdtrn[] = {
0xFA58FC00, 0x0B64FC7E, 0x0800F7B6, 0x00F006BE,
};
-static const u32 b43_ntab_tmap[] = {
+const u32 b43_ntab_tmap[] = {
0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888,
0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
0xF1111110, 0x11111111, 0x11F11111, 0x00000111,
@@ -2406,544 +2406,6 @@ static const u32 b43_ntab_tmap[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
-const u32 b43_ntab_tx_gain_rev0_1_2[] = {
- 0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42,
- 0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44,
- 0x03c82a42, 0x03c82944, 0x03c82942, 0x03c82844,
- 0x03c82842, 0x03c42b44, 0x03c42b42, 0x03c42a44,
- 0x03c42a42, 0x03c42944, 0x03c42942, 0x03c42844,
- 0x03c42842, 0x03c42744, 0x03c42742, 0x03c42644,
- 0x03c42642, 0x03c42544, 0x03c42542, 0x03c42444,
- 0x03c42442, 0x03c02b44, 0x03c02b42, 0x03c02a44,
- 0x03c02a42, 0x03c02944, 0x03c02942, 0x03c02844,
- 0x03c02842, 0x03c02744, 0x03c02742, 0x03b02b44,
- 0x03b02b42, 0x03b02a44, 0x03b02a42, 0x03b02944,
- 0x03b02942, 0x03b02844, 0x03b02842, 0x03b02744,
- 0x03b02742, 0x03b02644, 0x03b02642, 0x03b02544,
- 0x03b02542, 0x03a02b44, 0x03a02b42, 0x03a02a44,
- 0x03a02a42, 0x03a02944, 0x03a02942, 0x03a02844,
- 0x03a02842, 0x03a02744, 0x03a02742, 0x03902b44,
- 0x03902b42, 0x03902a44, 0x03902a42, 0x03902944,
- 0x03902942, 0x03902844, 0x03902842, 0x03902744,
- 0x03902742, 0x03902644, 0x03902642, 0x03902544,
- 0x03902542, 0x03802b44, 0x03802b42, 0x03802a44,
- 0x03802a42, 0x03802944, 0x03802942, 0x03802844,
- 0x03802842, 0x03802744, 0x03802742, 0x03802644,
- 0x03802642, 0x03802544, 0x03802542, 0x03802444,
- 0x03802442, 0x03802344, 0x03802342, 0x03802244,
- 0x03802242, 0x03802144, 0x03802142, 0x03802044,
- 0x03802042, 0x03801f44, 0x03801f42, 0x03801e44,
- 0x03801e42, 0x03801d44, 0x03801d42, 0x03801c44,
- 0x03801c42, 0x03801b44, 0x03801b42, 0x03801a44,
- 0x03801a42, 0x03801944, 0x03801942, 0x03801844,
- 0x03801842, 0x03801744, 0x03801742, 0x03801644,
- 0x03801642, 0x03801544, 0x03801542, 0x03801444,
- 0x03801442, 0x03801344, 0x03801342, 0x00002b00,
-};
-
-const u32 b43_ntab_tx_gain_rev3plus_2ghz[] = {
- 0x1f410044, 0x1f410042, 0x1f410040, 0x1f41003e,
- 0x1f41003c, 0x1f41003b, 0x1f410039, 0x1f410037,
- 0x1e410044, 0x1e410042, 0x1e410040, 0x1e41003e,
- 0x1e41003c, 0x1e41003b, 0x1e410039, 0x1e410037,
- 0x1d410044, 0x1d410042, 0x1d410040, 0x1d41003e,
- 0x1d41003c, 0x1d41003b, 0x1d410039, 0x1d410037,
- 0x1c410044, 0x1c410042, 0x1c410040, 0x1c41003e,
- 0x1c41003c, 0x1c41003b, 0x1c410039, 0x1c410037,
- 0x1b410044, 0x1b410042, 0x1b410040, 0x1b41003e,
- 0x1b41003c, 0x1b41003b, 0x1b410039, 0x1b410037,
- 0x1a410044, 0x1a410042, 0x1a410040, 0x1a41003e,
- 0x1a41003c, 0x1a41003b, 0x1a410039, 0x1a410037,
- 0x19410044, 0x19410042, 0x19410040, 0x1941003e,
- 0x1941003c, 0x1941003b, 0x19410039, 0x19410037,
- 0x18410044, 0x18410042, 0x18410040, 0x1841003e,
- 0x1841003c, 0x1841003b, 0x18410039, 0x18410037,
- 0x17410044, 0x17410042, 0x17410040, 0x1741003e,
- 0x1741003c, 0x1741003b, 0x17410039, 0x17410037,
- 0x16410044, 0x16410042, 0x16410040, 0x1641003e,
- 0x1641003c, 0x1641003b, 0x16410039, 0x16410037,
- 0x15410044, 0x15410042, 0x15410040, 0x1541003e,
- 0x1541003c, 0x1541003b, 0x15410039, 0x15410037,
- 0x14410044, 0x14410042, 0x14410040, 0x1441003e,
- 0x1441003c, 0x1441003b, 0x14410039, 0x14410037,
- 0x13410044, 0x13410042, 0x13410040, 0x1341003e,
- 0x1341003c, 0x1341003b, 0x13410039, 0x13410037,
- 0x12410044, 0x12410042, 0x12410040, 0x1241003e,
- 0x1241003c, 0x1241003b, 0x12410039, 0x12410037,
- 0x11410044, 0x11410042, 0x11410040, 0x1141003e,
- 0x1141003c, 0x1141003b, 0x11410039, 0x11410037,
- 0x10410044, 0x10410042, 0x10410040, 0x1041003e,
- 0x1041003c, 0x1041003b, 0x10410039, 0x10410037,
-};
-
-const u32 b43_ntab_tx_gain_rev3_5ghz[] = {
- 0xcff70044, 0xcff70042, 0xcff70040, 0xcff7003e,
- 0xcff7003c, 0xcff7003b, 0xcff70039, 0xcff70037,
- 0xcef70044, 0xcef70042, 0xcef70040, 0xcef7003e,
- 0xcef7003c, 0xcef7003b, 0xcef70039, 0xcef70037,
- 0xcdf70044, 0xcdf70042, 0xcdf70040, 0xcdf7003e,
- 0xcdf7003c, 0xcdf7003b, 0xcdf70039, 0xcdf70037,
- 0xccf70044, 0xccf70042, 0xccf70040, 0xccf7003e,
- 0xccf7003c, 0xccf7003b, 0xccf70039, 0xccf70037,
- 0xcbf70044, 0xcbf70042, 0xcbf70040, 0xcbf7003e,
- 0xcbf7003c, 0xcbf7003b, 0xcbf70039, 0xcbf70037,
- 0xcaf70044, 0xcaf70042, 0xcaf70040, 0xcaf7003e,
- 0xcaf7003c, 0xcaf7003b, 0xcaf70039, 0xcaf70037,
- 0xc9f70044, 0xc9f70042, 0xc9f70040, 0xc9f7003e,
- 0xc9f7003c, 0xc9f7003b, 0xc9f70039, 0xc9f70037,
- 0xc8f70044, 0xc8f70042, 0xc8f70040, 0xc8f7003e,
- 0xc8f7003c, 0xc8f7003b, 0xc8f70039, 0xc8f70037,
- 0xc7f70044, 0xc7f70042, 0xc7f70040, 0xc7f7003e,
- 0xc7f7003c, 0xc7f7003b, 0xc7f70039, 0xc7f70037,
- 0xc6f70044, 0xc6f70042, 0xc6f70040, 0xc6f7003e,
- 0xc6f7003c, 0xc6f7003b, 0xc6f70039, 0xc6f70037,
- 0xc5f70044, 0xc5f70042, 0xc5f70040, 0xc5f7003e,
- 0xc5f7003c, 0xc5f7003b, 0xc5f70039, 0xc5f70037,
- 0xc4f70044, 0xc4f70042, 0xc4f70040, 0xc4f7003e,
- 0xc4f7003c, 0xc4f7003b, 0xc4f70039, 0xc4f70037,
- 0xc3f70044, 0xc3f70042, 0xc3f70040, 0xc3f7003e,
- 0xc3f7003c, 0xc3f7003b, 0xc3f70039, 0xc3f70037,
- 0xc2f70044, 0xc2f70042, 0xc2f70040, 0xc2f7003e,
- 0xc2f7003c, 0xc2f7003b, 0xc2f70039, 0xc2f70037,
- 0xc1f70044, 0xc1f70042, 0xc1f70040, 0xc1f7003e,
- 0xc1f7003c, 0xc1f7003b, 0xc1f70039, 0xc1f70037,
- 0xc0f70044, 0xc0f70042, 0xc0f70040, 0xc0f7003e,
- 0xc0f7003c, 0xc0f7003b, 0xc0f70039, 0xc0f70037,
-};
-
-const u32 b43_ntab_tx_gain_rev4_5ghz[] = {
- 0x2ff20044, 0x2ff20042, 0x2ff20040, 0x2ff2003e,
- 0x2ff2003c, 0x2ff2003b, 0x2ff20039, 0x2ff20037,
- 0x2ef20044, 0x2ef20042, 0x2ef20040, 0x2ef2003e,
- 0x2ef2003c, 0x2ef2003b, 0x2ef20039, 0x2ef20037,
- 0x2df20044, 0x2df20042, 0x2df20040, 0x2df2003e,
- 0x2df2003c, 0x2df2003b, 0x2df20039, 0x2df20037,
- 0x2cf20044, 0x2cf20042, 0x2cf20040, 0x2cf2003e,
- 0x2cf2003c, 0x2cf2003b, 0x2cf20039, 0x2cf20037,
- 0x2bf20044, 0x2bf20042, 0x2bf20040, 0x2bf2003e,
- 0x2bf2003c, 0x2bf2003b, 0x2bf20039, 0x2bf20037,
- 0x2af20044, 0x2af20042, 0x2af20040, 0x2af2003e,
- 0x2af2003c, 0x2af2003b, 0x2af20039, 0x2af20037,
- 0x29f20044, 0x29f20042, 0x29f20040, 0x29f2003e,
- 0x29f2003c, 0x29f2003b, 0x29f20039, 0x29f20037,
- 0x28f20044, 0x28f20042, 0x28f20040, 0x28f2003e,
- 0x28f2003c, 0x28f2003b, 0x28f20039, 0x28f20037,
- 0x27f20044, 0x27f20042, 0x27f20040, 0x27f2003e,
- 0x27f2003c, 0x27f2003b, 0x27f20039, 0x27f20037,
- 0x26f20044, 0x26f20042, 0x26f20040, 0x26f2003e,
- 0x26f2003c, 0x26f2003b, 0x26f20039, 0x26f20037,
- 0x25f20044, 0x25f20042, 0x25f20040, 0x25f2003e,
- 0x25f2003c, 0x25f2003b, 0x25f20039, 0x25f20037,
- 0x24f20044, 0x24f20042, 0x24f20040, 0x24f2003e,
- 0x24f2003c, 0x24f2003b, 0x24f20039, 0x24f20038,
- 0x23f20041, 0x23f20040, 0x23f2003f, 0x23f2003e,
- 0x23f2003c, 0x23f2003b, 0x23f20039, 0x23f20037,
- 0x22f20044, 0x22f20042, 0x22f20040, 0x22f2003e,
- 0x22f2003c, 0x22f2003b, 0x22f20039, 0x22f20037,
- 0x21f20044, 0x21f20042, 0x21f20040, 0x21f2003e,
- 0x21f2003c, 0x21f2003b, 0x21f20039, 0x21f20037,
- 0x20d20043, 0x20d20041, 0x20d2003e, 0x20d2003c,
- 0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034,
-};
-
-const u32 b43_ntab_tx_gain_rev5plus_5ghz[] = {
- 0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044,
- 0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c,
- 0x0e620044, 0x0e620042, 0x0e620040, 0x0e62003e,
- 0x0e62003c, 0x0e62003d, 0x0e62003b, 0x0e62003a,
- 0x0d620043, 0x0d620041, 0x0d620040, 0x0d62003e,
- 0x0d62003d, 0x0d62003c, 0x0d62003b, 0x0d62003a,
- 0x0c620041, 0x0c620040, 0x0c62003f, 0x0c62003e,
- 0x0c62003c, 0x0c62003b, 0x0c620039, 0x0c620037,
- 0x0b620046, 0x0b620044, 0x0b620042, 0x0b620040,
- 0x0b62003e, 0x0b62003c, 0x0b62003b, 0x0b62003a,
- 0x0a620041, 0x0a620040, 0x0a62003e, 0x0a62003c,
- 0x0a62003b, 0x0a62003a, 0x0a620039, 0x0a620038,
- 0x0962003e, 0x0962003d, 0x0962003c, 0x0962003b,
- 0x09620039, 0x09620037, 0x09620035, 0x09620033,
- 0x08620044, 0x08620042, 0x08620040, 0x0862003e,
- 0x0862003c, 0x0862003b, 0x0862003a, 0x08620039,
- 0x07620043, 0x07620042, 0x07620040, 0x0762003f,
- 0x0762003d, 0x0762003b, 0x0762003a, 0x07620039,
- 0x0662003e, 0x0662003d, 0x0662003c, 0x0662003b,
- 0x06620039, 0x06620037, 0x06620035, 0x06620033,
- 0x05620046, 0x05620044, 0x05620042, 0x05620040,
- 0x0562003e, 0x0562003c, 0x0562003b, 0x05620039,
- 0x04620044, 0x04620042, 0x04620040, 0x0462003e,
- 0x0462003c, 0x0462003b, 0x04620039, 0x04620038,
- 0x0362003c, 0x0362003b, 0x0362003a, 0x03620039,
- 0x03620038, 0x03620037, 0x03620035, 0x03620033,
- 0x0262004c, 0x0262004a, 0x02620048, 0x02620047,
- 0x02620046, 0x02620044, 0x02620043, 0x02620042,
- 0x0162004a, 0x01620048, 0x01620046, 0x01620044,
- 0x01620043, 0x01620042, 0x01620041, 0x01620040,
- 0x00620042, 0x00620040, 0x0062003e, 0x0062003c,
- 0x0062003b, 0x00620039, 0x00620037, 0x00620035,
-};
-
-const u32 txpwrctrl_tx_gain_ipa[] = {
- 0x5ff7002d, 0x5ff7002b, 0x5ff7002a, 0x5ff70029,
- 0x5ff70028, 0x5ff70027, 0x5ff70026, 0x5ff70025,
- 0x5ef7002d, 0x5ef7002b, 0x5ef7002a, 0x5ef70029,
- 0x5ef70028, 0x5ef70027, 0x5ef70026, 0x5ef70025,
- 0x5df7002d, 0x5df7002b, 0x5df7002a, 0x5df70029,
- 0x5df70028, 0x5df70027, 0x5df70026, 0x5df70025,
- 0x5cf7002d, 0x5cf7002b, 0x5cf7002a, 0x5cf70029,
- 0x5cf70028, 0x5cf70027, 0x5cf70026, 0x5cf70025,
- 0x5bf7002d, 0x5bf7002b, 0x5bf7002a, 0x5bf70029,
- 0x5bf70028, 0x5bf70027, 0x5bf70026, 0x5bf70025,
- 0x5af7002d, 0x5af7002b, 0x5af7002a, 0x5af70029,
- 0x5af70028, 0x5af70027, 0x5af70026, 0x5af70025,
- 0x59f7002d, 0x59f7002b, 0x59f7002a, 0x59f70029,
- 0x59f70028, 0x59f70027, 0x59f70026, 0x59f70025,
- 0x58f7002d, 0x58f7002b, 0x58f7002a, 0x58f70029,
- 0x58f70028, 0x58f70027, 0x58f70026, 0x58f70025,
- 0x57f7002d, 0x57f7002b, 0x57f7002a, 0x57f70029,
- 0x57f70028, 0x57f70027, 0x57f70026, 0x57f70025,
- 0x56f7002d, 0x56f7002b, 0x56f7002a, 0x56f70029,
- 0x56f70028, 0x56f70027, 0x56f70026, 0x56f70025,
- 0x55f7002d, 0x55f7002b, 0x55f7002a, 0x55f70029,
- 0x55f70028, 0x55f70027, 0x55f70026, 0x55f70025,
- 0x54f7002d, 0x54f7002b, 0x54f7002a, 0x54f70029,
- 0x54f70028, 0x54f70027, 0x54f70026, 0x54f70025,
- 0x53f7002d, 0x53f7002b, 0x53f7002a, 0x53f70029,
- 0x53f70028, 0x53f70027, 0x53f70026, 0x53f70025,
- 0x52f7002d, 0x52f7002b, 0x52f7002a, 0x52f70029,
- 0x52f70028, 0x52f70027, 0x52f70026, 0x52f70025,
- 0x51f7002d, 0x51f7002b, 0x51f7002a, 0x51f70029,
- 0x51f70028, 0x51f70027, 0x51f70026, 0x51f70025,
- 0x50f7002d, 0x50f7002b, 0x50f7002a, 0x50f70029,
- 0x50f70028, 0x50f70027, 0x50f70026, 0x50f70025,
-};
-
-const u32 txpwrctrl_tx_gain_ipa_rev5[] = {
- 0x1ff7002d, 0x1ff7002b, 0x1ff7002a, 0x1ff70029,
- 0x1ff70028, 0x1ff70027, 0x1ff70026, 0x1ff70025,
- 0x1ef7002d, 0x1ef7002b, 0x1ef7002a, 0x1ef70029,
- 0x1ef70028, 0x1ef70027, 0x1ef70026, 0x1ef70025,
- 0x1df7002d, 0x1df7002b, 0x1df7002a, 0x1df70029,
- 0x1df70028, 0x1df70027, 0x1df70026, 0x1df70025,
- 0x1cf7002d, 0x1cf7002b, 0x1cf7002a, 0x1cf70029,
- 0x1cf70028, 0x1cf70027, 0x1cf70026, 0x1cf70025,
- 0x1bf7002d, 0x1bf7002b, 0x1bf7002a, 0x1bf70029,
- 0x1bf70028, 0x1bf70027, 0x1bf70026, 0x1bf70025,
- 0x1af7002d, 0x1af7002b, 0x1af7002a, 0x1af70029,
- 0x1af70028, 0x1af70027, 0x1af70026, 0x1af70025,
- 0x19f7002d, 0x19f7002b, 0x19f7002a, 0x19f70029,
- 0x19f70028, 0x19f70027, 0x19f70026, 0x19f70025,
- 0x18f7002d, 0x18f7002b, 0x18f7002a, 0x18f70029,
- 0x18f70028, 0x18f70027, 0x18f70026, 0x18f70025,
- 0x17f7002d, 0x17f7002b, 0x17f7002a, 0x17f70029,
- 0x17f70028, 0x17f70027, 0x17f70026, 0x17f70025,
- 0x16f7002d, 0x16f7002b, 0x16f7002a, 0x16f70029,
- 0x16f70028, 0x16f70027, 0x16f70026, 0x16f70025,
- 0x15f7002d, 0x15f7002b, 0x15f7002a, 0x15f70029,
- 0x15f70028, 0x15f70027, 0x15f70026, 0x15f70025,
- 0x14f7002d, 0x14f7002b, 0x14f7002a, 0x14f70029,
- 0x14f70028, 0x14f70027, 0x14f70026, 0x14f70025,
- 0x13f7002d, 0x13f7002b, 0x13f7002a, 0x13f70029,
- 0x13f70028, 0x13f70027, 0x13f70026, 0x13f70025,
- 0x12f7002d, 0x12f7002b, 0x12f7002a, 0x12f70029,
- 0x12f70028, 0x12f70027, 0x12f70026, 0x12f70025,
- 0x11f7002d, 0x11f7002b, 0x11f7002a, 0x11f70029,
- 0x11f70028, 0x11f70027, 0x11f70026, 0x11f70025,
- 0x10f7002d, 0x10f7002b, 0x10f7002a, 0x10f70029,
- 0x10f70028, 0x10f70027, 0x10f70026, 0x10f70025,
-};
-
-const u32 txpwrctrl_tx_gain_ipa_rev6[] = {
- 0x0ff7002d, 0x0ff7002b, 0x0ff7002a, 0x0ff70029,
- 0x0ff70028, 0x0ff70027, 0x0ff70026, 0x0ff70025,
- 0x0ef7002d, 0x0ef7002b, 0x0ef7002a, 0x0ef70029,
- 0x0ef70028, 0x0ef70027, 0x0ef70026, 0x0ef70025,
- 0x0df7002d, 0x0df7002b, 0x0df7002a, 0x0df70029,
- 0x0df70028, 0x0df70027, 0x0df70026, 0x0df70025,
- 0x0cf7002d, 0x0cf7002b, 0x0cf7002a, 0x0cf70029,
- 0x0cf70028, 0x0cf70027, 0x0cf70026, 0x0cf70025,
- 0x0bf7002d, 0x0bf7002b, 0x0bf7002a, 0x0bf70029,
- 0x0bf70028, 0x0bf70027, 0x0bf70026, 0x0bf70025,
- 0x0af7002d, 0x0af7002b, 0x0af7002a, 0x0af70029,
- 0x0af70028, 0x0af70027, 0x0af70026, 0x0af70025,
- 0x09f7002d, 0x09f7002b, 0x09f7002a, 0x09f70029,
- 0x09f70028, 0x09f70027, 0x09f70026, 0x09f70025,
- 0x08f7002d, 0x08f7002b, 0x08f7002a, 0x08f70029,
- 0x08f70028, 0x08f70027, 0x08f70026, 0x08f70025,
- 0x07f7002d, 0x07f7002b, 0x07f7002a, 0x07f70029,
- 0x07f70028, 0x07f70027, 0x07f70026, 0x07f70025,
- 0x06f7002d, 0x06f7002b, 0x06f7002a, 0x06f70029,
- 0x06f70028, 0x06f70027, 0x06f70026, 0x06f70025,
- 0x05f7002d, 0x05f7002b, 0x05f7002a, 0x05f70029,
- 0x05f70028, 0x05f70027, 0x05f70026, 0x05f70025,
- 0x04f7002d, 0x04f7002b, 0x04f7002a, 0x04f70029,
- 0x04f70028, 0x04f70027, 0x04f70026, 0x04f70025,
- 0x03f7002d, 0x03f7002b, 0x03f7002a, 0x03f70029,
- 0x03f70028, 0x03f70027, 0x03f70026, 0x03f70025,
- 0x02f7002d, 0x02f7002b, 0x02f7002a, 0x02f70029,
- 0x02f70028, 0x02f70027, 0x02f70026, 0x02f70025,
- 0x01f7002d, 0x01f7002b, 0x01f7002a, 0x01f70029,
- 0x01f70028, 0x01f70027, 0x01f70026, 0x01f70025,
- 0x00f7002d, 0x00f7002b, 0x00f7002a, 0x00f70029,
- 0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025,
-};
-
-const u32 txpwrctrl_tx_gain_ipa_5g[] = {
- 0x7ff70035, 0x7ff70033, 0x7ff70032, 0x7ff70031,
- 0x7ff7002f, 0x7ff7002e, 0x7ff7002d, 0x7ff7002b,
- 0x7ff7002a, 0x7ff70029, 0x7ff70028, 0x7ff70027,
- 0x7ff70026, 0x7ff70024, 0x7ff70023, 0x7ff70022,
- 0x7ef70028, 0x7ef70027, 0x7ef70026, 0x7ef70025,
- 0x7ef70024, 0x7ef70023, 0x7df70028, 0x7df70027,
- 0x7df70026, 0x7df70025, 0x7df70024, 0x7df70023,
- 0x7df70022, 0x7cf70029, 0x7cf70028, 0x7cf70027,
- 0x7cf70026, 0x7cf70025, 0x7cf70023, 0x7cf70022,
- 0x7bf70029, 0x7bf70028, 0x7bf70026, 0x7bf70025,
- 0x7bf70024, 0x7bf70023, 0x7bf70022, 0x7bf70021,
- 0x7af70029, 0x7af70028, 0x7af70027, 0x7af70026,
- 0x7af70025, 0x7af70024, 0x7af70023, 0x7af70022,
- 0x79f70029, 0x79f70028, 0x79f70027, 0x79f70026,
- 0x79f70025, 0x79f70024, 0x79f70023, 0x79f70022,
- 0x78f70029, 0x78f70028, 0x78f70027, 0x78f70026,
- 0x78f70025, 0x78f70024, 0x78f70023, 0x78f70022,
- 0x77f70029, 0x77f70028, 0x77f70027, 0x77f70026,
- 0x77f70025, 0x77f70024, 0x77f70023, 0x77f70022,
- 0x76f70029, 0x76f70028, 0x76f70027, 0x76f70026,
- 0x76f70024, 0x76f70023, 0x76f70022, 0x76f70021,
- 0x75f70029, 0x75f70028, 0x75f70027, 0x75f70026,
- 0x75f70025, 0x75f70024, 0x75f70023, 0x74f70029,
- 0x74f70028, 0x74f70026, 0x74f70025, 0x74f70024,
- 0x74f70023, 0x74f70022, 0x73f70029, 0x73f70027,
- 0x73f70026, 0x73f70025, 0x73f70024, 0x73f70023,
- 0x73f70022, 0x72f70028, 0x72f70027, 0x72f70026,
- 0x72f70025, 0x72f70024, 0x72f70023, 0x72f70022,
- 0x71f70028, 0x71f70027, 0x71f70026, 0x71f70025,
- 0x71f70024, 0x71f70023, 0x70f70028, 0x70f70027,
- 0x70f70026, 0x70f70024, 0x70f70023, 0x70f70022,
- 0x70f70021, 0x70f70020, 0x70f70020, 0x70f7001f,
-};
-
-const u16 tbl_iqcal_gainparams[2][9][8] = {
- {
- { 0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69 },
- { 0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69 },
- { 0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68 },
- { 0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67 },
- { 0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66 },
- { 0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65 },
- { 0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65 },
- { 0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65 },
- { 0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65 }
- },
- {
- { 0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79 },
- { 0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79 },
- { 0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79 },
- { 0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78 },
- { 0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78 },
- { 0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78 },
- { 0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78 },
- { 0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78 },
- { 0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78 }
- }
-};
-
-const struct nphy_txiqcal_ladder ladder_lo[] = {
- { 3, 0 },
- { 4, 0 },
- { 6, 0 },
- { 9, 0 },
- { 13, 0 },
- { 18, 0 },
- { 25, 0 },
- { 25, 1 },
- { 25, 2 },
- { 25, 3 },
- { 25, 4 },
- { 25, 5 },
- { 25, 6 },
- { 25, 7 },
- { 35, 7 },
- { 50, 7 },
- { 71, 7 },
- { 100, 7 }
-};
-
-const struct nphy_txiqcal_ladder ladder_iq[] = {
- { 3, 0 },
- { 4, 0 },
- { 6, 0 },
- { 9, 0 },
- { 13, 0 },
- { 18, 0 },
- { 25, 0 },
- { 35, 0 },
- { 50, 0 },
- { 71, 0 },
- { 100, 0 },
- { 100, 1 },
- { 100, 2 },
- { 100, 3 },
- { 100, 4 },
- { 100, 5 },
- { 100, 6 },
- { 100, 7 }
-};
-
-const u16 loscale[] = {
- 256, 256, 271, 271,
- 287, 256, 256, 271,
- 271, 287, 287, 304,
- 304, 256, 256, 271,
- 271, 287, 287, 304,
- 304, 322, 322, 341,
- 341, 362, 362, 383,
- 383, 256, 256, 271,
- 271, 287, 287, 304,
- 304, 322, 322, 256,
- 256, 271, 271, 287,
- 287, 304, 304, 322,
- 322, 341, 341, 362,
- 362, 256, 256, 271,
- 271, 287, 287, 304,
- 304, 322, 322, 256,
- 256, 271, 271, 287,
- 287, 304, 304, 322,
- 322, 341, 341, 362,
- 362, 256, 256, 271,
- 271, 287, 287, 304,
- 304, 322, 322, 341,
- 341, 362, 362, 383,
- 383, 406, 406, 430,
- 430, 455, 455, 482,
- 482, 511, 511, 541,
- 541, 573, 573, 607,
- 607, 643, 643, 681,
- 681, 722, 722, 764,
- 764, 810, 810, 858,
- 858, 908, 908, 962,
- 962, 1019, 1019, 256
-};
-
-const u16 tbl_tx_iqlo_cal_loft_ladder_40[] = {
- 0x0200, 0x0300, 0x0400, 0x0700,
- 0x0900, 0x0c00, 0x1200, 0x1201,
- 0x1202, 0x1203, 0x1204, 0x1205,
- 0x1206, 0x1207, 0x1907, 0x2307,
- 0x3207, 0x4707
-};
-
-const u16 tbl_tx_iqlo_cal_loft_ladder_20[] = {
- 0x0300, 0x0500, 0x0700, 0x0900,
- 0x0d00, 0x1100, 0x1900, 0x1901,
- 0x1902, 0x1903, 0x1904, 0x1905,
- 0x1906, 0x1907, 0x2407, 0x3207,
- 0x4607, 0x6407
-};
-
-const u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = {
- 0x0100, 0x0200, 0x0400, 0x0700,
- 0x0900, 0x0c00, 0x1200, 0x1900,
- 0x2300, 0x3200, 0x4700, 0x4701,
- 0x4702, 0x4703, 0x4704, 0x4705,
- 0x4706, 0x4707
-};
-
-const u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = {
- 0x0200, 0x0300, 0x0600, 0x0900,
- 0x0d00, 0x1100, 0x1900, 0x2400,
- 0x3200, 0x4600, 0x6400, 0x6401,
- 0x6402, 0x6403, 0x6404, 0x6405,
- 0x6406, 0x6407
-};
-
-const u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3] = { };
-
-const u16 tbl_tx_iqlo_cal_startcoefs[B43_NTAB_TX_IQLO_CAL_STARTCOEFS] = { };
-
-const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = {
- 0x8423, 0x8323, 0x8073, 0x8256,
- 0x8045, 0x8223, 0x9423, 0x9323,
- 0x9073, 0x9256, 0x9045, 0x9223
-};
-
-const u16 tbl_tx_iqlo_cal_cmds_recal[] = {
- 0x8101, 0x8253, 0x8053, 0x8234,
- 0x8034, 0x9101, 0x9253, 0x9053,
- 0x9234, 0x9034
-};
-
-const u16 tbl_tx_iqlo_cal_cmds_fullcal[] = {
- 0x8123, 0x8264, 0x8086, 0x8245,
- 0x8056, 0x9123, 0x9264, 0x9086,
- 0x9245, 0x9056
-};
-
-const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = {
- 0x8434, 0x8334, 0x8084, 0x8267,
- 0x8056, 0x8234, 0x9434, 0x9334,
- 0x9084, 0x9267, 0x9056, 0x9234
-};
-
-const s16 tbl_tx_filter_coef_rev4[7][15] = {
- { -377, 137, -407, 208, -1527,
- 956, 93, 186, 93, 230,
- -44, 230, 20, -191, 201 },
- { -77, 20, -98, 49, -93,
- 60, 56, 111, 56, 26,
- -5, 26, 34, -32, 34 },
- { -360, 164, -376, 164, -1533,
- 576, 308, -314, 308, 121,
- -73, 121, 91, 124, 91 },
- { -295, 200, -363, 142, -1391,
- 826, 151, 301, 151, 151,
- 301, 151, 602, -752, 602 },
- { -92, 58, -96, 49, -104,
- 44, 17, 35, 17, 12,
- 25, 12, 13, 27, 13 },
- { -375, 136, -399, 209, -1479,
- 949, 130, 260, 130, 230,
- -44, 230, 201, -191, 201 },
- { 0xed9, 0xc8, 0xe95, 0x8e, 0xa91,
- 0x33a, 0x97, 0x12d, 0x97, 0x97,
- 0x12d, 0x97, 0x25a, 0xd10, 0x25a }
-};
-
-/* addr0, addr1, bmask, shift */
-const struct nphy_rf_control_override_rev2 tbl_rf_control_override_rev2[] = {
- { 0x78, 0x78, 0x0038, 3 }, /* for field == 0x0002 (fls == 2) */
- { 0x7A, 0x7D, 0x0001, 0 }, /* for field == 0x0004 (fls == 3) */
- { 0x7A, 0x7D, 0x0002, 1 }, /* for field == 0x0008 (fls == 4) */
- { 0x7A, 0x7D, 0x0004, 2 }, /* for field == 0x0010 (fls == 5) */
- { 0x7A, 0x7D, 0x0030, 4 }, /* for field == 0x0020 (fls == 6) */
- { 0x7A, 0x7D, 0x00C0, 6 }, /* for field == 0x0040 (fls == 7) */
- { 0x7A, 0x7D, 0x0100, 8 }, /* for field == 0x0080 (fls == 8) */
- { 0x7A, 0x7D, 0x0200, 9 }, /* for field == 0x0100 (fls == 9) */
- { 0x78, 0x78, 0x0004, 2 }, /* for field == 0x0200 (fls == 10) */
- { 0x7B, 0x7E, 0x01FF, 0 }, /* for field == 0x0400 (fls == 11) */
- { 0x7C, 0x7F, 0x01FF, 0 }, /* for field == 0x0800 (fls == 12) */
- { 0x78, 0x78, 0x0100, 8 }, /* for field == 0x1000 (fls == 13) */
- { 0x78, 0x78, 0x0200, 9 }, /* for field == 0x2000 (fls == 14) */
- { 0x78, 0x78, 0xF000, 12 } /* for field == 0x4000 (fls == 15) */
-};
-
-/* val_mask, val_shift, en_addr0, val_addr0, en_addr1, val_addr1 */
-const struct nphy_rf_control_override_rev3 tbl_rf_control_override_rev3[] = {
- { 0x8000, 15, 0xE5, 0xF9, 0xE6, 0xFB }, /* field == 0x0001 (fls 1) */
- { 0x0001, 0, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0002 (fls 2) */
- { 0x0002, 1, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0004 (fls 3) */
- { 0x0004, 2, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0008 (fls 4) */
- { 0x0016, 4, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0010 (fls 5) */
- { 0x0020, 5, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0020 (fls 6) */
- { 0x0040, 6, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0040 (fls 7) */
- { 0x0080, 6, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0080 (fls 8) */
- { 0x0100, 7, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0100 (fls 9) */
- { 0x0007, 0, 0xE7, 0xF8, 0xEC, 0xFA }, /* field == 0x0200 (fls 10) */
- { 0x0070, 4, 0xE7, 0xF8, 0xEC, 0xFA }, /* field == 0x0400 (fls 11) */
- { 0xE000, 13, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0800 (fls 12) */
- { 0xFFFF, 0, 0xE7, 0x7B, 0xEC, 0x7E }, /* field == 0x1000 (fls 13) */
- { 0xFFFF, 0, 0xE7, 0x7C, 0xEC, 0x7F }, /* field == 0x2000 (fls 14) */
- { 0x00C0, 6, 0xE7, 0xF9, 0xEC, 0xFB } /* field == 0x4000 (fls 15) */
-};
-
static inline void assert_ntab_array_sizes(void)
{
#undef check
@@ -2980,72 +2442,6 @@ static inline void assert_ntab_array_sizes(void)
#undef check
}
-u32 b43_ntab_read(struct b43_wldev *dev, u32 offset)
-{
- u32 type, value;
-
- type = offset & B43_NTAB_TYPEMASK;
- offset &= ~B43_NTAB_TYPEMASK;
- B43_WARN_ON(offset > 0xFFFF);
-
- switch (type) {
- case B43_NTAB_8BIT:
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
- value = b43_phy_read(dev, B43_NPHY_TABLE_DATALO) & 0xFF;
- break;
- case B43_NTAB_16BIT:
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
- value = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
- break;
- case B43_NTAB_32BIT:
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
- value = b43_phy_read(dev, B43_NPHY_TABLE_DATAHI);
- value <<= 16;
- value |= b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
- break;
- default:
- B43_WARN_ON(1);
- value = 0;
- }
-
- return value;
-}
-
-void b43_ntab_read_bulk(struct b43_wldev *dev, u32 offset,
- unsigned int nr_elements, void *_data)
-{
- u32 type;
- u8 *data = _data;
- unsigned int i;
-
- type = offset & B43_NTAB_TYPEMASK;
- offset &= ~B43_NTAB_TYPEMASK;
- B43_WARN_ON(offset > 0xFFFF);
-
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
-
- for (i = 0; i < nr_elements; i++) {
- switch (type) {
- case B43_NTAB_8BIT:
- *data = b43_phy_read(dev, B43_NPHY_TABLE_DATALO) & 0xFF;
- data++;
- break;
- case B43_NTAB_16BIT:
- *((u16 *)data) = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
- data += 2;
- break;
- case B43_NTAB_32BIT:
- *((u32 *)data) = b43_phy_read(dev, B43_NPHY_TABLE_DATAHI);
- *((u32 *)data) <<= 16;
- *((u32 *)data) |= b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
- data += 4;
- break;
- default:
- B43_WARN_ON(1);
- }
- }
-}
-
void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value)
{
u32 type;
@@ -3078,91 +2474,3 @@ void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value)
/* Some compiletime assertions... */
assert_ntab_array_sizes();
}
-
-void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
- unsigned int nr_elements, const void *_data)
-{
- u32 type, value;
- const u8 *data = _data;
- unsigned int i;
-
- type = offset & B43_NTAB_TYPEMASK;
- offset &= ~B43_NTAB_TYPEMASK;
- B43_WARN_ON(offset > 0xFFFF);
-
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
-
- for (i = 0; i < nr_elements; i++) {
- switch (type) {
- case B43_NTAB_8BIT:
- value = *data;
- data++;
- B43_WARN_ON(value & ~0xFF);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, value);
- break;
- case B43_NTAB_16BIT:
- value = *((u16 *)data);
- data += 2;
- B43_WARN_ON(value & ~0xFFFF);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, value);
- break;
- case B43_NTAB_32BIT:
- value = *((u32 *)data);
- data += 4;
- b43_phy_write(dev, B43_NPHY_TABLE_DATAHI, value >> 16);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
- value & 0xFFFF);
- break;
- default:
- B43_WARN_ON(1);
- }
- }
-}
-
-#define ntab_upload(dev, offset, data) do { \
- unsigned int i; \
- for (i = 0; i < (offset##_SIZE); i++) \
- b43_ntab_write(dev, (offset) + i, (data)[i]); \
- } while (0)
-
-void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev)
-{
- /* Static tables */
- ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct);
- ntab_upload(dev, B43_NTAB_FRAMELT, b43_ntab_framelookup);
- ntab_upload(dev, B43_NTAB_TMAP, b43_ntab_tmap);
- ntab_upload(dev, B43_NTAB_TDTRN, b43_ntab_tdtrn);
- ntab_upload(dev, B43_NTAB_INTLEVEL, b43_ntab_intlevel);
- ntab_upload(dev, B43_NTAB_PILOT, b43_ntab_pilot);
- ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt);
- ntab_upload(dev, B43_NTAB_TDI20A0, b43_ntab_tdi20a0);
- ntab_upload(dev, B43_NTAB_TDI20A1, b43_ntab_tdi20a1);
- ntab_upload(dev, B43_NTAB_TDI40A0, b43_ntab_tdi40a0);
- ntab_upload(dev, B43_NTAB_TDI40A1, b43_ntab_tdi40a1);
- ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi);
- ntab_upload(dev, B43_NTAB_CHANEST, b43_ntab_channelest);
- ntab_upload(dev, B43_NTAB_MCS, b43_ntab_mcs);
-
- /* Volatile tables */
- ntab_upload(dev, B43_NTAB_NOISEVAR10, b43_ntab_noisevar10);
- ntab_upload(dev, B43_NTAB_NOISEVAR11, b43_ntab_noisevar11);
- ntab_upload(dev, B43_NTAB_C0_ESTPLT, b43_ntab_estimatepowerlt0);
- ntab_upload(dev, B43_NTAB_C1_ESTPLT, b43_ntab_estimatepowerlt1);
- ntab_upload(dev, B43_NTAB_C0_ADJPLT, b43_ntab_adjustpower0);
- ntab_upload(dev, B43_NTAB_C1_ADJPLT, b43_ntab_adjustpower1);
- ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0);
- ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1);
- ntab_upload(dev, B43_NTAB_C0_IQLT, b43_ntab_iqlt0);
- ntab_upload(dev, B43_NTAB_C1_IQLT, b43_ntab_iqlt1);
- ntab_upload(dev, B43_NTAB_C0_LOFEEDTH, b43_ntab_loftlt0);
- ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1);
-}
-
-void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev)
-{
- /* Static tables */
- /* TODO */
-
- /* Volatile tables */
- /* TODO */
-}
diff --git a/trunk/drivers/net/wireless/b43/tables_nphy.h b/trunk/drivers/net/wireless/b43/tables_nphy.h
index 9c1c6ecd3672..4d498b053ec7 100644
--- a/trunk/drivers/net/wireless/b43/tables_nphy.h
+++ b/trunk/drivers/net/wireless/b43/tables_nphy.h
@@ -46,27 +46,6 @@ struct b43_nphy_channeltab_entry {
struct b43_wldev;
-struct nphy_txiqcal_ladder {
- u8 percent;
- u8 g_env;
-};
-
-struct nphy_rf_control_override_rev2 {
- u8 addr0;
- u8 addr1;
- u16 bmask;
- u8 shift;
-};
-
-struct nphy_rf_control_override_rev3 {
- u16 val_mask;
- u8 val_shift;
- u8 en_addr0;
- u8 val_addr0;
- u8 en_addr1;
- u8 val_addr1;
-};
-
/* Upload the default register value table.
* If "ghz5" is true, we upload the 5Ghz table. Otherwise the 2.4Ghz
* table is uploaded. If "ignore_uploadflag" is true, we upload any value
@@ -147,57 +126,34 @@ b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel);
#define B43_NTAB_C1_LOFEEDTH B43_NTAB16(0x1B, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 1 */
#define B43_NTAB_C1_LOFEEDTH_SIZE 128
-#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_40_SIZE 18
-#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_20_SIZE 18
-#define B43_NTAB_TX_IQLO_CAL_IQIMB_LADDER_40_SIZE 18
-#define B43_NTAB_TX_IQLO_CAL_IQIMB_LADDER_20_SIZE 18
-#define B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3 11
-#define B43_NTAB_TX_IQLO_CAL_STARTCOEFS 9
-#define B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3 12
-#define B43_NTAB_TX_IQLO_CAL_CMDS_RECAL 10
-#define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL 10
-#define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3 12
-
-u32 b43_ntab_read(struct b43_wldev *dev, u32 offset);
-void b43_ntab_read_bulk(struct b43_wldev *dev, u32 offset,
- unsigned int nr_elements, void *_data);
void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value);
-void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
- unsigned int nr_elements, const void *_data);
-
-void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev);
-void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev);
-
-extern const u32 b43_ntab_tx_gain_rev0_1_2[];
-extern const u32 b43_ntab_tx_gain_rev3plus_2ghz[];
-extern const u32 b43_ntab_tx_gain_rev3_5ghz[];
-extern const u32 b43_ntab_tx_gain_rev4_5ghz[];
-extern const u32 b43_ntab_tx_gain_rev5plus_5ghz[];
-
-extern const u32 txpwrctrl_tx_gain_ipa[];
-extern const u32 txpwrctrl_tx_gain_ipa_rev5[];
-extern const u32 txpwrctrl_tx_gain_ipa_rev6[];
-extern const u32 txpwrctrl_tx_gain_ipa_5g[];
-extern const u16 tbl_iqcal_gainparams[2][9][8];
-extern const struct nphy_txiqcal_ladder ladder_lo[];
-extern const struct nphy_txiqcal_ladder ladder_iq[];
-extern const u16 loscale[];
-
-extern const u16 tbl_tx_iqlo_cal_loft_ladder_40[];
-extern const u16 tbl_tx_iqlo_cal_loft_ladder_20[];
-extern const u16 tbl_tx_iqlo_cal_iqimb_ladder_40[];
-extern const u16 tbl_tx_iqlo_cal_iqimb_ladder_20[];
-extern const u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[];
-extern const u16 tbl_tx_iqlo_cal_startcoefs[];
-extern const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[];
-extern const u16 tbl_tx_iqlo_cal_cmds_recal[];
-extern const u16 tbl_tx_iqlo_cal_cmds_fullcal[];
-extern const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[];
-extern const s16 tbl_tx_filter_coef_rev4[7][15];
-
-extern const struct nphy_rf_control_override_rev2
- tbl_rf_control_override_rev2[];
-extern const struct nphy_rf_control_override_rev3
- tbl_rf_control_override_rev3[];
+
+extern const u8 b43_ntab_adjustpower0[];
+extern const u8 b43_ntab_adjustpower1[];
+extern const u16 b43_ntab_bdi[];
+extern const u32 b43_ntab_channelest[];
+extern const u8 b43_ntab_estimatepowerlt0[];
+extern const u8 b43_ntab_estimatepowerlt1[];
+extern const u8 b43_ntab_framelookup[];
+extern const u32 b43_ntab_framestruct[];
+extern const u32 b43_ntab_gainctl0[];
+extern const u32 b43_ntab_gainctl1[];
+extern const u32 b43_ntab_intlevel[];
+extern const u32 b43_ntab_iqlt0[];
+extern const u32 b43_ntab_iqlt1[];
+extern const u16 b43_ntab_loftlt0[];
+extern const u16 b43_ntab_loftlt1[];
+extern const u8 b43_ntab_mcs[];
+extern const u32 b43_ntab_noisevar10[];
+extern const u32 b43_ntab_noisevar11[];
+extern const u16 b43_ntab_pilot[];
+extern const u32 b43_ntab_pilotlt[];
+extern const u32 b43_ntab_tdi20a0[];
+extern const u32 b43_ntab_tdi20a1[];
+extern const u32 b43_ntab_tdi40a0[];
+extern const u32 b43_ntab_tdi40a1[];
+extern const u32 b43_ntab_tdtrn[];
+extern const u32 b43_ntab_tmap[];
+
#endif /* B43_TABLES_NPHY_H_ */
diff --git a/trunk/drivers/net/wireless/b43legacy/dma.c b/trunk/drivers/net/wireless/b43legacy/dma.c
index 8b9387c6ff36..0a86bdf53154 100644
--- a/trunk/drivers/net/wireless/b43legacy/dma.c
+++ b/trunk/drivers/net/wireless/b43legacy/dma.c
@@ -1411,6 +1411,7 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev,
b43legacyerr(dev->wl, "DMA tx mapping failure\n");
goto out_unlock;
}
+ ring->nr_tx_packets++;
if ((free_slots(ring) < SLOTS_PER_PACKET) ||
should_inject_overflow(ring)) {
/* This TX ring is full. */
@@ -1526,6 +1527,25 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
spin_unlock(&ring->lock);
}
+void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev,
+ struct ieee80211_tx_queue_stats *stats)
+{
+ const int nr_queues = dev->wl->hw->queues;
+ struct b43legacy_dmaring *ring;
+ unsigned long flags;
+ int i;
+
+ for (i = 0; i < nr_queues; i++) {
+ ring = priority_to_txring(dev, i);
+
+ spin_lock_irqsave(&ring->lock, flags);
+ stats[i].len = ring->used_slots / SLOTS_PER_PACKET;
+ stats[i].limit = ring->nr_slots / SLOTS_PER_PACKET;
+ stats[i].count = ring->nr_tx_packets;
+ spin_unlock_irqrestore(&ring->lock, flags);
+ }
+}
+
static void dma_rx(struct b43legacy_dmaring *ring,
int *slot)
{
diff --git a/trunk/drivers/net/wireless/b43legacy/dma.h b/trunk/drivers/net/wireless/b43legacy/dma.h
index f9681041c2d8..2f186003c31e 100644
--- a/trunk/drivers/net/wireless/b43legacy/dma.h
+++ b/trunk/drivers/net/wireless/b43legacy/dma.h
@@ -243,6 +243,8 @@ struct b43legacy_dmaring {
int used_slots;
/* Currently used slot in the ring. */
int current_slot;
+ /* Total number of packets sent. Statistics only. */
+ unsigned int nr_tx_packets;
/* Frameoffset in octets. */
u32 frameoffset;
/* Descriptor buffer size. */
@@ -290,6 +292,9 @@ void b43legacy_dma_free(struct b43legacy_wldev *dev);
void b43legacy_dma_tx_suspend(struct b43legacy_wldev *dev);
void b43legacy_dma_tx_resume(struct b43legacy_wldev *dev);
+void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev,
+ struct ieee80211_tx_queue_stats *stats);
+
int b43legacy_dma_tx(struct b43legacy_wldev *dev,
struct sk_buff *skb);
void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
@@ -310,6 +315,11 @@ void b43legacy_dma_free(struct b43legacy_wldev *dev)
{
}
static inline
+void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev,
+ struct ieee80211_tx_queue_stats *stats)
+{
+}
+static inline
int b43legacy_dma_tx(struct b43legacy_wldev *dev,
struct sk_buff *skb)
{
diff --git a/trunk/drivers/net/wireless/b43legacy/leds.h b/trunk/drivers/net/wireless/b43legacy/leds.h
index 9ff6750dc57f..82167a90088f 100644
--- a/trunk/drivers/net/wireless/b43legacy/leds.h
+++ b/trunk/drivers/net/wireless/b43legacy/leds.h
@@ -45,7 +45,7 @@ enum b43legacy_led_behaviour {
void b43legacy_leds_init(struct b43legacy_wldev *dev);
void b43legacy_leds_exit(struct b43legacy_wldev *dev);
-#else /* CONFIG_B43LEGACY_LEDS */
+#else /* CONFIG_B43EGACY_LEDS */
/* LED support disabled */
struct b43legacy_led {
diff --git a/trunk/drivers/net/wireless/b43legacy/main.c b/trunk/drivers/net/wireless/b43legacy/main.c
index 08523a45e23b..ab6a18c2e9d9 100644
--- a/trunk/drivers/net/wireless/b43legacy/main.c
+++ b/trunk/drivers/net/wireless/b43legacy/main.c
@@ -61,8 +61,6 @@ MODULE_AUTHOR("Michael Buesch");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(B43legacy_SUPPORTED_FIRMWARE_ID);
-MODULE_FIRMWARE("b43legacy/ucode2.fw");
-MODULE_FIRMWARE("b43legacy/ucode4.fw");
#if defined(CONFIG_B43LEGACY_DMA) && defined(CONFIG_B43LEGACY_PIO)
static int modparam_pio;
@@ -2446,6 +2444,29 @@ static int b43legacy_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
return 0;
}
+static int b43legacy_op_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats)
+{
+ struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+ struct b43legacy_wldev *dev = wl->current_dev;
+ unsigned long flags;
+ int err = -ENODEV;
+
+ if (!dev)
+ goto out;
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ if (likely(b43legacy_status(dev) >= B43legacy_STAT_STARTED)) {
+ if (b43legacy_using_pio(dev))
+ b43legacy_pio_get_tx_stats(dev, stats);
+ else
+ b43legacy_dma_get_tx_stats(dev, stats);
+ err = 0;
+ }
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+out:
+ return err;
+}
+
static int b43legacy_op_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats)
{
@@ -2900,7 +2921,6 @@ static int b43legacy_wireless_core_start(struct b43legacy_wldev *dev)
goto out;
}
/* We are ready to run. */
- ieee80211_wake_queues(dev->wl->hw);
b43legacy_set_status(dev, B43legacy_STAT_STARTED);
/* Start data flow (TX/RX) */
@@ -3321,7 +3341,6 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
b43legacy_security_init(dev);
b43legacy_rng_init(wl);
- ieee80211_wake_queues(dev->wl->hw);
b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED);
b43legacy_leds_init(dev);
@@ -3342,7 +3361,7 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
}
static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev;
@@ -3351,23 +3370,23 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
/* TODO: allow WDS/AP devices to coexist */
- if (vif->type != NL80211_IFTYPE_AP &&
- vif->type != NL80211_IFTYPE_STATION &&
- vif->type != NL80211_IFTYPE_WDS &&
- vif->type != NL80211_IFTYPE_ADHOC)
+ if (conf->type != NL80211_IFTYPE_AP &&
+ conf->type != NL80211_IFTYPE_STATION &&
+ conf->type != NL80211_IFTYPE_WDS &&
+ conf->type != NL80211_IFTYPE_ADHOC)
return -EOPNOTSUPP;
mutex_lock(&wl->mutex);
if (wl->operating)
goto out_mutex_unlock;
- b43legacydbg(wl, "Adding Interface type %d\n", vif->type);
+ b43legacydbg(wl, "Adding Interface type %d\n", conf->type);
dev = wl->current_dev;
wl->operating = 1;
- wl->vif = vif;
- wl->if_type = vif->type;
- memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
+ wl->vif = conf->vif;
+ wl->if_type = conf->type;
+ memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
spin_lock_irqsave(&wl->irq_lock, flags);
b43legacy_adjust_opmode(dev);
@@ -3384,18 +3403,18 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
}
static void b43legacy_op_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
unsigned long flags;
- b43legacydbg(wl, "Removing Interface type %d\n", vif->type);
+ b43legacydbg(wl, "Removing Interface type %d\n", conf->type);
mutex_lock(&wl->mutex);
B43legacy_WARN_ON(!wl->operating);
- B43legacy_WARN_ON(wl->vif != vif);
+ B43legacy_WARN_ON(wl->vif != conf->vif);
wl->vif = NULL;
wl->operating = 0;
@@ -3490,6 +3509,7 @@ static const struct ieee80211_ops b43legacy_hw_ops = {
.bss_info_changed = b43legacy_op_bss_info_changed,
.configure_filter = b43legacy_op_configure_filter,
.get_stats = b43legacy_op_get_stats,
+ .get_tx_stats = b43legacy_op_get_tx_stats,
.start = b43legacy_op_start,
.stop = b43legacy_op_stop,
.set_tim = b43legacy_op_beacon_set_tim,
@@ -3940,7 +3960,7 @@ static struct ssb_driver b43legacy_ssb_driver = {
static void b43legacy_print_driverinfo(void)
{
- const char *feat_pci = "", *feat_leds = "",
+ const char *feat_pci = "", *feat_leds = "", *feat_rfkill = "",
*feat_pio = "", *feat_dma = "";
#ifdef CONFIG_B43LEGACY_PCI_AUTOSELECT
@@ -3949,6 +3969,9 @@ static void b43legacy_print_driverinfo(void)
#ifdef CONFIG_B43LEGACY_LEDS
feat_leds = "L";
#endif
+#ifdef CONFIG_B43LEGACY_RFKILL
+ feat_rfkill = "R";
+#endif
#ifdef CONFIG_B43LEGACY_PIO
feat_pio = "I";
#endif
@@ -3956,9 +3979,9 @@ static void b43legacy_print_driverinfo(void)
feat_dma = "D";
#endif
printk(KERN_INFO "Broadcom 43xx-legacy driver loaded "
- "[ Features: %s%s%s%s, Firmware-ID: "
+ "[ Features: %s%s%s%s%s, Firmware-ID: "
B43legacy_SUPPORTED_FIRMWARE_ID " ]\n",
- feat_pci, feat_leds, feat_pio, feat_dma);
+ feat_pci, feat_leds, feat_rfkill, feat_pio, feat_dma);
}
static int __init b43legacy_init(void)
diff --git a/trunk/drivers/net/wireless/b43legacy/pio.c b/trunk/drivers/net/wireless/b43legacy/pio.c
index 017c0e9c37ef..51866c9a2769 100644
--- a/trunk/drivers/net/wireless/b43legacy/pio.c
+++ b/trunk/drivers/net/wireless/b43legacy/pio.c
@@ -477,6 +477,7 @@ int b43legacy_pio_tx(struct b43legacy_wldev *dev,
list_move_tail(&packet->list, &queue->txqueue);
queue->nr_txfree--;
+ queue->nr_tx_packets++;
B43legacy_WARN_ON(queue->nr_txfree >= B43legacy_PIO_MAXTXPACKETS);
tasklet_schedule(&queue->txtask);
@@ -545,6 +546,18 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev,
tasklet_schedule(&queue->txtask);
}
+void b43legacy_pio_get_tx_stats(struct b43legacy_wldev *dev,
+ struct ieee80211_tx_queue_stats *stats)
+{
+ struct b43legacy_pio *pio = &dev->pio;
+ struct b43legacy_pioqueue *queue;
+
+ queue = pio->queue1;
+ stats[0].len = B43legacy_PIO_MAXTXPACKETS - queue->nr_txfree;
+ stats[0].limit = B43legacy_PIO_MAXTXPACKETS;
+ stats[0].count = queue->nr_tx_packets;
+}
+
static void pio_rx_error(struct b43legacy_pioqueue *queue,
int clear_buffers,
const char *error)
diff --git a/trunk/drivers/net/wireless/b43legacy/pio.h b/trunk/drivers/net/wireless/b43legacy/pio.h
index 8e6773ea6e75..464fec05a06d 100644
--- a/trunk/drivers/net/wireless/b43legacy/pio.h
+++ b/trunk/drivers/net/wireless/b43legacy/pio.h
@@ -74,6 +74,10 @@ struct b43legacy_pioqueue {
* posted to the device. We are waiting for the txstatus.
*/
struct list_head txrunning;
+ /* Total number or packets sent.
+ * (This counter can obviously wrap).
+ */
+ unsigned int nr_tx_packets;
struct tasklet_struct txtask;
struct b43legacy_pio_txpacket
tx_packets_cache[B43legacy_PIO_MAXTXPACKETS];
@@ -102,6 +106,8 @@ int b43legacy_pio_tx(struct b43legacy_wldev *dev,
struct sk_buff *skb);
void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev,
const struct b43legacy_txstatus *status);
+void b43legacy_pio_get_tx_stats(struct b43legacy_wldev *dev,
+ struct ieee80211_tx_queue_stats *stats);
void b43legacy_pio_rx(struct b43legacy_pioqueue *queue);
/* Suspend TX queue in hardware. */
@@ -134,6 +140,11 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev,
{
}
static inline
+void b43legacy_pio_get_tx_stats(struct b43legacy_wldev *dev,
+ struct ieee80211_tx_queue_stats *stats)
+{
+}
+static inline
void b43legacy_pio_rx(struct b43legacy_pioqueue *queue)
{
}
diff --git a/trunk/drivers/net/wireless/hostap/hostap_cs.c b/trunk/drivers/net/wireless/hostap/hostap_cs.c
index d19748d90aaf..c9640a3e02c9 100644
--- a/trunk/drivers/net/wireless/hostap/hostap_cs.c
+++ b/trunk/drivers/net/wireless/hostap/hostap_cs.c
@@ -793,6 +793,13 @@ static struct pcmcia_device_id hostap_cs_ids[] = {
0x4b801a17),
PCMCIA_MFC_DEVICE_PROD_ID12(0, "SanDisk", "ConnectPlus",
0x7a954bd9, 0x74be00c6),
+ PCMCIA_DEVICE_PROD_ID123(
+ "Intersil", "PRISM 2_5 PCMCIA ADAPTER", "ISL37300P",
+ 0x4b801a17, 0x6345a0bf, 0xc9049a39),
+ /* D-Link DWL-650 Rev. P1; manfid 0x000b, 0x7110 */
+ PCMCIA_DEVICE_PROD_ID123(
+ "D-Link", "DWL-650 Wireless PC Card RevP", "ISL37101P-10",
+ 0x1a424a1c, 0x6ea57632, 0xdd97a26b),
PCMCIA_DEVICE_PROD_ID123(
"Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02",
0xe6ec52ce, 0x08649af2, 0x4b74baa0),
@@ -826,13 +833,15 @@ static struct pcmcia_device_id hostap_cs_ids[] = {
"Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio",
"Ver. 1.00",
0x5cd01705, 0x4271660f, 0x9d08ee12),
+ PCMCIA_DEVICE_PROD_ID123(
+ "corega", "WL PCCL-11", "ISL37300P",
+ 0xa21501a, 0x59868926, 0xc9049a39),
+ PCMCIA_DEVICE_PROD_ID123(
+ "The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P",
+ 0xa5f472c2, 0x9c05598d, 0xc9049a39),
PCMCIA_DEVICE_PROD_ID123(
"Wireless LAN" , "11Mbps PC Card", "Version 01.02",
0x4b8870ff, 0x70e946d1, 0x4b74baa0),
- PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092),
- PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2),
- PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b),
- PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39),
PCMCIA_DEVICE_NULL
};
MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids);
diff --git a/trunk/drivers/net/wireless/hostap/hostap_hw.c b/trunk/drivers/net/wireless/hostap/hostap_hw.c
index d70732819423..ff9b5c882184 100644
--- a/trunk/drivers/net/wireless/hostap/hostap_hw.c
+++ b/trunk/drivers/net/wireless/hostap/hostap_hw.c
@@ -2618,15 +2618,6 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id)
int events = 0;
u16 ev;
- /* Detect early interrupt before driver is fully configued */
- if (!dev->base_addr) {
- if (net_ratelimit()) {
- printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n",
- dev->name);
- }
- return IRQ_HANDLED;
- }
-
iface = netdev_priv(dev);
local = iface->local;
diff --git a/trunk/drivers/net/wireless/iwlwifi/Kconfig b/trunk/drivers/net/wireless/iwlwifi/Kconfig
index dc8ed1527666..b16b06c2031f 100644
--- a/trunk/drivers/net/wireless/iwlwifi/Kconfig
+++ b/trunk/drivers/net/wireless/iwlwifi/Kconfig
@@ -1,8 +1,14 @@
config IWLWIFI
tristate "Intel Wireless Wifi"
- depends on PCI && MAC80211
+ depends on PCI && MAC80211 && EXPERIMENTAL
select FW_LOADER
+config IWLWIFI_SPECTRUM_MEASUREMENT
+ bool "Enable Spectrum Measurement in iwlagn driver"
+ depends on IWLWIFI
+ ---help---
+ This option will enable spectrum measurement for the iwlagn driver.
+
config IWLWIFI_DEBUG
bool "Enable full debugging output in iwlagn and iwl3945 drivers"
depends on IWLWIFI
@@ -114,3 +120,9 @@ config IWL3945
inserted in and removed from the running kernel whenever you want),
say M here and read . The
module will be called iwl3945.
+
+config IWL3945_SPECTRUM_MEASUREMENT
+ bool "Enable Spectrum Measurement in iwl3945 driver"
+ depends on IWL3945
+ ---help---
+ This option will enable spectrum measurement for the iwl3945 driver.
diff --git a/trunk/drivers/net/wireless/iwlwifi/Makefile b/trunk/drivers/net/wireless/iwlwifi/Makefile
index 4e378faee650..7f82044af242 100644
--- a/trunk/drivers/net/wireless/iwlwifi/Makefile
+++ b/trunk/drivers/net/wireless/iwlwifi/Makefile
@@ -3,6 +3,7 @@ iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o
iwlcore-objs += iwl-scan.o iwl-led.o
iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
+iwlcore-$(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) += iwl-spectrum.o
iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
CFLAGS_iwl-devtrace.o := -I$(src)
@@ -19,5 +20,3 @@ iwlagn-$(CONFIG_IWL5000) += iwl-1000.o
# 3945
obj-$(CONFIG_IWL3945) += iwl3945.o
iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o
-
-ccflags-y += -D__CHECK_ENDIAN__
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c
index 3bf2e6e9b2d9..8414178bcff4 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008-2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -89,78 +89,8 @@ static void iwl1000_nic_config(struct iwl_priv *priv)
~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK);
}
-static struct iwl_sensitivity_ranges iwl1000_sensitivity = {
- .min_nrg_cck = 95,
- .max_nrg_cck = 0, /* not used, set to 0 */
- .auto_corr_min_ofdm = 90,
- .auto_corr_min_ofdm_mrc = 170,
- .auto_corr_min_ofdm_x1 = 120,
- .auto_corr_min_ofdm_mrc_x1 = 240,
-
- .auto_corr_max_ofdm = 120,
- .auto_corr_max_ofdm_mrc = 210,
- .auto_corr_max_ofdm_x1 = 155,
- .auto_corr_max_ofdm_mrc_x1 = 290,
-
- .auto_corr_min_cck = 125,
- .auto_corr_max_cck = 200,
- .auto_corr_min_cck_mrc = 170,
- .auto_corr_max_cck_mrc = 400,
- .nrg_th_cck = 95,
- .nrg_th_ofdm = 95,
-
- .barker_corr_th_min = 190,
- .barker_corr_th_min_mrc = 390,
- .nrg_th_cca = 62,
-};
-
-static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
-{
- if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
- priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES)
- priv->cfg->num_of_queues =
- priv->cfg->mod_params->num_of_queues;
-
- priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
- priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
- priv->hw_params.scd_bc_tbls_size =
- priv->cfg->num_of_queues *
- sizeof(struct iwl5000_scd_bc_tbl);
- priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
- priv->hw_params.max_stations = IWL5000_STATION_COUNT;
- priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
-
- priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE;
- priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE;
-
- priv->hw_params.max_bsm_size = 0;
- priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
- BIT(IEEE80211_BAND_5GHZ);
- priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
-
- priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
- priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
- priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
- priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
-
- if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
- priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
-
- /* Set initial sensitivity parameters */
- /* Set initial calibration set */
- priv->hw_params.sens = &iwl1000_sensitivity;
- priv->hw_params.calib_init_cfg =
- BIT(IWL_CALIB_XTAL) |
- BIT(IWL_CALIB_LO) |
- BIT(IWL_CALIB_TX_IQ) |
- BIT(IWL_CALIB_TX_IQ_PERD) |
- BIT(IWL_CALIB_BASE_BAND);
-
- return 0;
-}
-
static struct iwl_lib_ops iwl1000_lib = {
- .set_hw_params = iwl1000_hw_set_hw_params,
+ .set_hw_params = iwl5000_hw_set_hw_params,
.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
.txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
.txq_set_sched = iwl5000_txq_set_sched,
@@ -175,8 +105,6 @@ static struct iwl_lib_ops iwl1000_lib = {
.load_ucode = iwl5000_load_ucode,
.dump_nic_event_log = iwl_dump_nic_event_log,
.dump_nic_error_log = iwl_dump_nic_error_log,
- .dump_csr = iwl_dump_csr,
- .dump_fh = iwl_dump_fh,
.init_alive_start = iwl5000_init_alive_start,
.alive_notify = iwl5000_alive_notify,
.send_tx_power = iwl5000_send_tx_power,
@@ -210,10 +138,9 @@ static struct iwl_lib_ops iwl1000_lib = {
.temperature = iwl5000_temperature,
.set_ct_kill = iwl1000_set_ct_threshold,
},
- .add_bcast_station = iwl_add_bcast_station,
};
-static const struct iwl_ops iwl1000_ops = {
+static struct iwl_ops iwl1000_ops = {
.ucode = &iwl5000_ucode,
.lib = &iwl1000_lib,
.hcmd = &iwl5000_hcmd,
@@ -246,8 +173,7 @@ struct iwl_cfg iwl1000_bgn_cfg = {
.use_rts_for_ht = true, /* use rts/cts protection */
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
.support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
+ .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
};
struct iwl_cfg iwl1000_bg_cfg = {
@@ -274,8 +200,6 @@ struct iwl_cfg iwl1000_bg_cfg = {
.led_compensation = 51,
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
.support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
};
MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX));
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-3945-fh.h b/trunk/drivers/net/wireless/iwlwifi/iwl-3945-fh.h
index 042f6bc0df13..08ce259a0e60 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-3945-fh.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-3945-fh.h
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/trunk/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
index 3a876a8ece38..6fd10d443ba3 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/trunk/drivers/net/wireless/iwlwifi/iwl-3945-led.c
index abe2b739c4dc..a871d09d598f 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-3945-led.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-3945-led.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/trunk/drivers/net/wireless/iwlwifi/iwl-3945-led.h
index ce990adc51e7..5a1033ca7aaa 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-3945-led.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-3945-led.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/trunk/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index 47909f94271e..d4b49883b30e 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-3945.c b/trunk/drivers/net/wireless/iwlwifi/iwl-3945.c
index 521584b99fd1..234891d8cc10 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -45,8 +45,8 @@
#include "iwl-sta.h"
#include "iwl-3945.h"
#include "iwl-eeprom.h"
-#include "iwl-core.h"
#include "iwl-helpers.h"
+#include "iwl-core.h"
#include "iwl-led.h"
#include "iwl-3945-led.h"
@@ -1951,7 +1951,11 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
}
/* Add the broadcast address so we can send broadcast frames */
- priv->cfg->ops->lib->add_bcast_station(priv);
+ if (iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL) ==
+ IWL_INVALID_STATION) {
+ IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n");
+ return -EIO;
+ }
/* If we have set the ASSOC_MSK and we are in BSS mode then
* add the IWL_AP_ID to the station rate table */
@@ -2470,9 +2474,11 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
memset((void *)&priv->hw_params, 0,
sizeof(struct iwl_hw_params));
- priv->shared_virt = dma_alloc_coherent(&priv->pci_dev->dev,
- sizeof(struct iwl3945_shared),
- &priv->shared_phys, GFP_KERNEL);
+ priv->shared_virt =
+ pci_alloc_consistent(priv->pci_dev,
+ sizeof(struct iwl3945_shared),
+ &priv->shared_phys);
+
if (!priv->shared_virt) {
IWL_ERR(priv, "failed to allocate pci memory\n");
mutex_unlock(&priv->mutex);
@@ -2790,7 +2796,6 @@ static struct iwl_lib_ops iwl3945_lib = {
.post_associate = iwl3945_post_associate,
.isr = iwl_isr_legacy,
.config_ap = iwl3945_config_ap,
- .add_bcast_station = iwl3945_add_bcast_station,
};
static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
@@ -2799,7 +2804,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
.rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag,
};
-static const struct iwl_ops iwl3945_ops = {
+static struct iwl_ops iwl3945_ops = {
.ucode = &iwl3945_ucode,
.lib = &iwl3945_lib,
.hcmd = &iwl3945_hcmd,
@@ -2825,7 +2830,6 @@ static struct iwl_cfg iwl3945_bg_cfg = {
.ht_greenfield_support = false,
.led_compensation = 64,
.broken_powersave = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
};
static struct iwl_cfg iwl3945_abg_cfg = {
@@ -2843,7 +2847,6 @@ static struct iwl_cfg iwl3945_abg_cfg = {
.ht_greenfield_support = false,
.led_compensation = 64,
.broken_powersave = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
};
struct pci_device_id iwl3945_hw_card_ids[] = {
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-3945.h b/trunk/drivers/net/wireless/iwlwifi/iwl-3945.h
index ae94babe595b..531fa125f5a6 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -171,6 +171,24 @@ struct iwl3945_frame {
#define SCAN_INTERVAL 100
+#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
+#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */
+#define STATUS_INT_ENABLED 2
+#define STATUS_RF_KILL_HW 3
+#define STATUS_INIT 5
+#define STATUS_ALIVE 6
+#define STATUS_READY 7
+#define STATUS_TEMPERATURE 8
+#define STATUS_GEO_CONFIGURED 9
+#define STATUS_EXIT_PENDING 10
+#define STATUS_STATISTICS 12
+#define STATUS_SCANNING 13
+#define STATUS_SCAN_ABORTING 14
+#define STATUS_SCAN_HW 15
+#define STATUS_POWER_PMI 16
+#define STATUS_FW_ERROR 17
+#define STATUS_CONF_PENDING 18
+
#define MAX_TID_COUNT 9
#define IWL_INVALID_RATE 0xFF
@@ -208,8 +226,7 @@ extern void iwl3945_rx_replenish(void *data);
extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
struct ieee80211_hdr *hdr,int left);
-extern int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
- char **buf, bool display);
+extern void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log);
extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv);
/*
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/trunk/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
index 67ef562e8db1..c606366b582c 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-4965.c b/trunk/drivers/net/wireless/iwlwifi/iwl-4965.c
index 1bd2cd836026..31462813bac0 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -581,13 +581,6 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
- /* make sure all queue are not stopped */
- memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
- for (i = 0; i < 4; i++)
- atomic_set(&priv->queue_stop_count[i], 0);
-
- /* reset to 0 to enable all the queue first */
- priv->txq_ctx_active_msk = 0;
/* Map each Tx/cmd queue to its corresponding fifo */
for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
int ac = default_queue_to_tx_fifo[i];
@@ -2213,10 +2206,9 @@ static struct iwl_lib_ops iwl4965_lib = {
.temperature = iwl4965_temperature_calib,
.set_ct_kill = iwl4965_set_ct_threshold,
},
- .add_bcast_station = iwl_add_bcast_station,
};
-static const struct iwl_ops iwl4965_ops = {
+static struct iwl_ops iwl4965_ops = {
.ucode = &iwl4965_ucode,
.lib = &iwl4965_lib,
.hcmd = &iwl4965_hcmd,
@@ -2247,7 +2239,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
.broken_powersave = true,
.led_compensation = 61,
.chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+ .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
};
/* Module firmware */
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/trunk/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
index 714e032f6217..bc056e9ab85f 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c
index e476acb53aa7..cffaae772d51 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -179,24 +179,14 @@ static void iwl5000_gain_computation(struct iwl_priv *priv,
data->delta_gain_code[i] = 0;
continue;
}
-
- delta_g = (priv->cfg->chain_noise_scale *
- ((s32)average_noise[default_chain] -
+ delta_g = (1000 * ((s32)average_noise[default_chain] -
(s32)average_noise[i])) / 1500;
-
/* bound gain by 2 bits value max, 3rd bit is sign */
data->delta_gain_code[i] =
min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
if (delta_g < 0)
- /*
- * set negative sign ...
- * note to Intel developers: This is uCode API format,
- * not the format of any internal device registers.
- * Do not change this format for e.g. 6050 or similar
- * devices. Change format only if more resolution
- * (i.e. more than 2 bits magnitude) is needed.
- */
+ /* set negative sign */
data->delta_gain_code[i] |= (1 << 2);
}
@@ -273,8 +263,8 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
.auto_corr_max_ofdm = 120,
.auto_corr_max_ofdm_mrc = 210,
- .auto_corr_max_ofdm_x1 = 120,
- .auto_corr_max_ofdm_mrc_x1 = 240,
+ .auto_corr_max_ofdm_x1 = 155,
+ .auto_corr_max_ofdm_mrc_x1 = 290,
.auto_corr_min_cck = 125,
.auto_corr_max_cck = 200,
@@ -422,14 +412,12 @@ static void iwl5000_rx_calib_complete(struct iwl_priv *priv,
/*
* ucode
*/
-static int iwl5000_load_section(struct iwl_priv *priv, const char *name,
- struct fw_desc *image, u32 dst_addr)
+static int iwl5000_load_section(struct iwl_priv *priv,
+ struct fw_desc *image,
+ u32 dst_addr)
{
dma_addr_t phy_addr = image->p_addr;
u32 byte_cnt = image->len;
- int ret;
-
- priv->ucode_write_complete = 0;
iwl_write_direct32(priv,
FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
@@ -459,20 +447,6 @@ static int iwl5000_load_section(struct iwl_priv *priv, const char *name,
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE |
FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
- IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name);
- ret = wait_event_interruptible_timeout(priv->wait_command_queue,
- priv->ucode_write_complete, 5 * HZ);
- if (ret == -ERESTARTSYS) {
- IWL_ERR(priv, "Could not load the %s uCode section due "
- "to interrupt\n", name);
- return ret;
- }
- if (!ret) {
- IWL_ERR(priv, "Could not load the %s uCode section\n",
- name);
- return -ETIMEDOUT;
- }
-
return 0;
}
@@ -482,13 +456,48 @@ static int iwl5000_load_given_ucode(struct iwl_priv *priv,
{
int ret = 0;
- ret = iwl5000_load_section(priv, "INST", inst_image,
+ ret = iwl5000_load_section(priv, inst_image,
IWL50_RTC_INST_LOWER_BOUND);
if (ret)
return ret;
- return iwl5000_load_section(priv, "DATA", data_image,
- IWL50_RTC_DATA_LOWER_BOUND);
+ IWL_DEBUG_INFO(priv, "INST uCode section being loaded...\n");
+ ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+ priv->ucode_write_complete, 5 * HZ);
+ if (ret == -ERESTARTSYS) {
+ IWL_ERR(priv, "Could not load the INST uCode section due "
+ "to interrupt\n");
+ return ret;
+ }
+ if (!ret) {
+ IWL_ERR(priv, "Could not load the INST uCode section\n");
+ return -ETIMEDOUT;
+ }
+
+ priv->ucode_write_complete = 0;
+
+ ret = iwl5000_load_section(
+ priv, data_image, IWL50_RTC_DATA_LOWER_BOUND);
+ if (ret)
+ return ret;
+
+ IWL_DEBUG_INFO(priv, "DATA uCode section being loaded...\n");
+
+ ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+ priv->ucode_write_complete, 5 * HZ);
+ if (ret == -ERESTARTSYS) {
+ IWL_ERR(priv, "Could not load the INST uCode section due "
+ "to interrupt\n");
+ return ret;
+ } else if (!ret) {
+ IWL_ERR(priv, "Could not load the DATA uCode section\n");
+ return -ETIMEDOUT;
+ } else
+ ret = 0;
+
+ priv->ucode_write_complete = 0;
+
+ return ret;
}
int iwl5000_load_ucode(struct iwl_priv *priv)
@@ -648,13 +657,6 @@ int iwl5000_alive_notify(struct iwl_priv *priv)
iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
- /* make sure all queue are not stopped */
- memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
- for (i = 0; i < 4; i++)
- atomic_set(&priv->queue_stop_count[i], 0);
-
- /* reset to 0 to enable all the queue first */
- priv->txq_ctx_active_msk = 0;
/* map qos queues to fifos one-to-one */
for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) {
int ac = iwl5000_default_queue_to_tx_fifo[i];
@@ -779,7 +781,7 @@ void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
- if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
+ if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP)
scd_bc_tbl[txq_id].
tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
}
@@ -798,12 +800,12 @@ void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
if (txq_id != IWL_CMD_QUEUE_NUM)
sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
- bc_ent = cpu_to_le16(1 | (sta_id << 12));
+ bc_ent = cpu_to_le16(1 | (sta_id << 12));
scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
- if (read_ptr < TFD_QUEUE_SIZE_BC_DUP)
+ if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP)
scd_bc_tbl[txq_id].
- tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
+ tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
}
static int iwl5000_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
@@ -1462,8 +1464,6 @@ struct iwl_lib_ops iwl5000_lib = {
.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
.dump_nic_event_log = iwl_dump_nic_event_log,
.dump_nic_error_log = iwl_dump_nic_error_log,
- .dump_csr = iwl_dump_csr,
- .dump_fh = iwl_dump_fh,
.load_ucode = iwl5000_load_ucode,
.init_alive_start = iwl5000_init_alive_start,
.alive_notify = iwl5000_alive_notify,
@@ -1499,7 +1499,6 @@ struct iwl_lib_ops iwl5000_lib = {
.temperature = iwl5000_temperature,
.set_ct_kill = iwl5000_set_ct_threshold,
},
- .add_bcast_station = iwl_add_bcast_station,
};
static struct iwl_lib_ops iwl5150_lib = {
@@ -1517,7 +1516,6 @@ static struct iwl_lib_ops iwl5150_lib = {
.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
.dump_nic_event_log = iwl_dump_nic_event_log,
.dump_nic_error_log = iwl_dump_nic_error_log,
- .dump_csr = iwl_dump_csr,
.load_ucode = iwl5000_load_ucode,
.init_alive_start = iwl5000_init_alive_start,
.alive_notify = iwl5000_alive_notify,
@@ -1553,10 +1551,9 @@ static struct iwl_lib_ops iwl5150_lib = {
.temperature = iwl5150_temperature,
.set_ct_kill = iwl5150_set_ct_threshold,
},
- .add_bcast_station = iwl_add_bcast_station,
};
-static const struct iwl_ops iwl5000_ops = {
+static struct iwl_ops iwl5000_ops = {
.ucode = &iwl5000_ucode,
.lib = &iwl5000_lib,
.hcmd = &iwl5000_hcmd,
@@ -1564,7 +1561,7 @@ static const struct iwl_ops iwl5000_ops = {
.led = &iwlagn_led_ops,
};
-static const struct iwl_ops iwl5150_ops = {
+static struct iwl_ops iwl5150_ops = {
.ucode = &iwl5000_ucode,
.lib = &iwl5150_lib,
.hcmd = &iwl5000_hcmd,
@@ -1601,8 +1598,7 @@ struct iwl_cfg iwl5300_agn_cfg = {
.led_compensation = 51,
.use_rts_for_ht = true, /* use rts/cts protection */
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
+ .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
};
struct iwl_cfg iwl5100_bgn_cfg = {
@@ -1627,8 +1623,6 @@ struct iwl_cfg iwl5100_bgn_cfg = {
.led_compensation = 51,
.use_rts_for_ht = true, /* use rts/cts protection */
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
};
struct iwl_cfg iwl5100_abg_cfg = {
@@ -1651,8 +1645,6 @@ struct iwl_cfg iwl5100_abg_cfg = {
.use_bsm = false,
.led_compensation = 51,
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
};
struct iwl_cfg iwl5100_agn_cfg = {
@@ -1677,8 +1669,7 @@ struct iwl_cfg iwl5100_agn_cfg = {
.led_compensation = 51,
.use_rts_for_ht = true, /* use rts/cts protection */
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
+ .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
};
struct iwl_cfg iwl5350_agn_cfg = {
@@ -1703,8 +1694,7 @@ struct iwl_cfg iwl5350_agn_cfg = {
.led_compensation = 51,
.use_rts_for_ht = true, /* use rts/cts protection */
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
+ .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
};
struct iwl_cfg iwl5150_agn_cfg = {
@@ -1729,8 +1719,7 @@ struct iwl_cfg iwl5150_agn_cfg = {
.led_compensation = 51,
.use_rts_for_ht = true, /* use rts/cts protection */
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
+ .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
};
struct iwl_cfg iwl5150_abg_cfg = {
@@ -1753,8 +1742,6 @@ struct iwl_cfg iwl5150_abg_cfg = {
.use_bsm = false,
.led_compensation = 51,
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
};
MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-6000-hw.h b/trunk/drivers/net/wireless/iwlwifi/iwl-6000-hw.h
index ddba39999997..90185777d98b 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-6000-hw.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-6000-hw.h
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c
index c4844adff92a..74e571049273 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008-2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -70,14 +70,6 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
}
-/* Indicate calibration version to uCode. */
-static void iwl6050_set_calib_version(struct iwl_priv *priv)
-{
- if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6)
- iwl_set_bit(priv, CSR_GP_DRIVER_REG,
- CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
-}
-
/* NIC configuration for 6000 series */
static void iwl6000_nic_config(struct iwl_priv *priv)
{
@@ -104,8 +96,6 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
}
/* else do nothing, uCode configured */
- if (priv->cfg->ops->lib->temp_ops.set_calib_version)
- priv->cfg->ops->lib->temp_ops.set_calib_version(priv);
}
static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
@@ -118,7 +108,7 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
.auto_corr_max_ofdm = 145,
.auto_corr_max_ofdm_mrc = 232,
- .auto_corr_max_ofdm_x1 = 110,
+ .auto_corr_max_ofdm_x1 = 145,
.auto_corr_max_ofdm_mrc_x1 = 232,
.auto_corr_min_cck = 125,
@@ -168,25 +158,11 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
/* Set initial sensitivity parameters */
/* Set initial calibration set */
priv->hw_params.sens = &iwl6000_sensitivity;
- switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
- case CSR_HW_REV_TYPE_6x50:
- priv->hw_params.calib_init_cfg =
- BIT(IWL_CALIB_XTAL) |
- BIT(IWL_CALIB_DC) |
- BIT(IWL_CALIB_LO) |
- BIT(IWL_CALIB_TX_IQ) |
- BIT(IWL_CALIB_BASE_BAND);
-
- break;
- default:
- priv->hw_params.calib_init_cfg =
+ priv->hw_params.calib_init_cfg =
BIT(IWL_CALIB_XTAL) |
BIT(IWL_CALIB_LO) |
BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_BASE_BAND);
- break;
- }
-
return 0;
}
@@ -239,8 +215,6 @@ static struct iwl_lib_ops iwl6000_lib = {
.load_ucode = iwl5000_load_ucode,
.dump_nic_event_log = iwl_dump_nic_event_log,
.dump_nic_error_log = iwl_dump_nic_error_log,
- .dump_csr = iwl_dump_csr,
- .dump_fh = iwl_dump_fh,
.init_alive_start = iwl5000_init_alive_start,
.alive_notify = iwl5000_alive_notify,
.send_tx_power = iwl5000_send_tx_power,
@@ -276,10 +250,9 @@ static struct iwl_lib_ops iwl6000_lib = {
.temperature = iwl5000_temperature,
.set_ct_kill = iwl6000_set_ct_threshold,
},
- .add_bcast_station = iwl_add_bcast_station,
};
-static const struct iwl_ops iwl6000_ops = {
+static struct iwl_ops iwl6000_ops = {
.ucode = &iwl5000_ucode,
.lib = &iwl6000_lib,
.hcmd = &iwl5000_hcmd,
@@ -287,68 +260,18 @@ static const struct iwl_ops iwl6000_ops = {
.led = &iwlagn_led_ops,
};
-static struct iwl_lib_ops iwl6050_lib = {
- .set_hw_params = iwl6000_hw_set_hw_params,
- .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
- .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
- .txq_set_sched = iwl5000_txq_set_sched,
- .txq_agg_enable = iwl5000_txq_agg_enable,
- .txq_agg_disable = iwl5000_txq_agg_disable,
- .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
- .txq_free_tfd = iwl_hw_txq_free_tfd,
- .txq_init = iwl_hw_tx_queue_init,
- .rx_handler_setup = iwl5000_rx_handler_setup,
- .setup_deferred_work = iwl5000_setup_deferred_work,
- .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
- .load_ucode = iwl5000_load_ucode,
- .dump_nic_event_log = iwl_dump_nic_event_log,
- .dump_nic_error_log = iwl_dump_nic_error_log,
- .dump_csr = iwl_dump_csr,
- .dump_fh = iwl_dump_fh,
- .init_alive_start = iwl5000_init_alive_start,
- .alive_notify = iwl5000_alive_notify,
- .send_tx_power = iwl5000_send_tx_power,
- .update_chain_flags = iwl_update_chain_flags,
- .set_channel_switch = iwl6000_hw_channel_switch,
- .apm_ops = {
- .init = iwl_apm_init,
- .stop = iwl_apm_stop,
- .config = iwl6000_nic_config,
- .set_pwr_src = iwl_set_pwr_src,
- },
- .eeprom_ops = {
- .regulatory_bands = {
- EEPROM_5000_REG_BAND_1_CHANNELS,
- EEPROM_5000_REG_BAND_2_CHANNELS,
- EEPROM_5000_REG_BAND_3_CHANNELS,
- EEPROM_5000_REG_BAND_4_CHANNELS,
- EEPROM_5000_REG_BAND_5_CHANNELS,
- EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
- EEPROM_5000_REG_BAND_52_HT40_CHANNELS
- },
- .verify_signature = iwlcore_eeprom_verify_signature,
- .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
- .release_semaphore = iwlcore_eeprom_release_semaphore,
- .calib_version = iwl5000_eeprom_calib_version,
- .query_addr = iwl5000_eeprom_query_addr,
- .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
- },
- .post_associate = iwl_post_associate,
- .isr = iwl_isr_ict,
- .config_ap = iwl_config_ap,
- .temp_ops = {
- .temperature = iwl5000_temperature,
- .set_ct_kill = iwl6000_set_ct_threshold,
- .set_calib_version = iwl6050_set_calib_version,
- },
- .add_bcast_station = iwl_add_bcast_station,
+static struct iwl_hcmd_utils_ops iwl6050_hcmd_utils = {
+ .get_hcmd_size = iwl5000_get_hcmd_size,
+ .build_addsta_hcmd = iwl5000_build_addsta_hcmd,
+ .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag,
+ .calc_rssi = iwl5000_calc_rssi,
};
-static const struct iwl_ops iwl6050_ops = {
+static struct iwl_ops iwl6050_ops = {
.ucode = &iwl5000_ucode,
- .lib = &iwl6050_lib,
+ .lib = &iwl6000_lib,
.hcmd = &iwl5000_hcmd,
- .utils = &iwl5000_hcmd_utils,
+ .utils = &iwl6050_hcmd_utils,
.led = &iwlagn_led_ops,
};
@@ -383,8 +306,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
.supports_idle = true,
.adv_thermal_throttle = true,
.support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
+ .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
};
struct iwl_cfg iwl6000i_2abg_cfg = {
@@ -414,8 +336,6 @@ struct iwl_cfg iwl6000i_2abg_cfg = {
.supports_idle = true,
.adv_thermal_throttle = true,
.support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
};
struct iwl_cfg iwl6000i_2bg_cfg = {
@@ -445,8 +365,6 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
.supports_idle = true,
.adv_thermal_throttle = true,
.support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
};
struct iwl_cfg iwl6050_2agn_cfg = {
@@ -477,8 +395,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
.supports_idle = true,
.adv_thermal_throttle = true,
.support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1500,
+ .sm_ps_mode = WLAN_HT_CAP_SM_PS_DYNAMIC,
};
struct iwl_cfg iwl6050_2abg_cfg = {
@@ -508,8 +425,6 @@ struct iwl_cfg iwl6050_2abg_cfg = {
.supports_idle = true,
.adv_thermal_throttle = true,
.support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1500,
};
struct iwl_cfg iwl6000_3agn_cfg = {
@@ -540,8 +455,7 @@ struct iwl_cfg iwl6000_3agn_cfg = {
.supports_idle = true,
.adv_thermal_throttle = true,
.support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
+ .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
};
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-led.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-led.c
index 1a24946bc203..3bccba20f6da 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-led.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-led.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-led.h b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-led.h
index a594e4fdc6b8..ab55f92a161d 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-led.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-led.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 8bf7c20b9d39..b93e49158196 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -298,23 +298,10 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
struct iwl_lq_sta *lq_data, u8 tid,
struct ieee80211_sta *sta)
{
- int ret;
-
if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
sta->addr, tid);
- ret = ieee80211_start_tx_ba_session(sta, tid);
- if (ret == -EAGAIN) {
- /*
- * driver and mac80211 is out of sync
- * this might be cause by reloading firmware
- * stop the tx ba session here
- */
- IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n",
- tid);
- ret = ieee80211_stop_tx_ba_session(sta, tid,
- WLAN_BACK_INITIATOR);
- }
+ ieee80211_start_tx_ba_session(sta, tid);
}
}
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
index e71923961e69..affc0c5a2f2c 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -191,7 +191,7 @@ enum {
IWL_RATE_2M_MASK)
#define IWL_CCK_RATES_MASK \
- (IWL_CCK_BASIC_RATES_MASK | \
+ (IWL_BASIC_RATES_MASK | \
IWL_RATE_5M_MASK | \
IWL_RATE_11M_MASK)
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c
index c5b724eaf306..1c9866daf815 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@@ -73,7 +73,13 @@
#define VD
#endif
-#define DRV_VERSION IWLWIFI_VERSION VD
+#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
+#define VS "s"
+#else
+#define VS
+#endif
+
+#define DRV_VERSION IWLWIFI_VERSION VD VS
MODULE_DESCRIPTION(DRV_DESCRIPTION);
@@ -197,8 +203,7 @@ int iwl_commit_rxon(struct iwl_priv *priv)
priv->start_calib = 0;
/* Add the broadcast address so we can send broadcast frames */
- priv->cfg->ops->lib->add_bcast_station(priv);
-
+ iwl_add_bcast_station(priv);
/* If we have set the ASSOC_MSK and we are in BSS mode then
* add the IWL_AP_ID to the station rate table */
@@ -652,131 +657,6 @@ static void iwl_bg_statistics_periodic(unsigned long data)
iwl_send_statistics_request(priv, CMD_ASYNC, false);
}
-
-static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
- u32 start_idx, u32 num_events,
- u32 mode)
-{
- u32 i;
- u32 ptr; /* SRAM byte address of log data */
- u32 ev, time, data; /* event log data */
- unsigned long reg_flags;
-
- if (mode == 0)
- ptr = base + (4 * sizeof(u32)) + (start_idx * 2 * sizeof(u32));
- else
- ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32));
-
- /* Make sure device is powered up for SRAM reads */
- spin_lock_irqsave(&priv->reg_lock, reg_flags);
- if (iwl_grab_nic_access(priv)) {
- spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
- return;
- }
-
- /* Set starting address; reads will auto-increment */
- _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
- rmb();
-
- /*
- * "time" is actually "data" for mode 0 (no timestamp).
- * place event id # at far right for easier visual parsing.
- */
- for (i = 0; i < num_events; i++) {
- ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- if (mode == 0) {
- trace_iwlwifi_dev_ucode_cont_event(priv,
- 0, time, ev);
- } else {
- data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- trace_iwlwifi_dev_ucode_cont_event(priv,
- time, data, ev);
- }
- }
- /* Allow device to power down */
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-}
-
-static void iwl_continuous_event_trace(struct iwl_priv *priv)
-{
- u32 capacity; /* event log capacity in # entries */
- u32 base; /* SRAM byte address of event log header */
- u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
- u32 num_wraps; /* # times uCode wrapped to top of log */
- u32 next_entry; /* index of next entry to be written by uCode */
-
- if (priv->ucode_type == UCODE_INIT)
- base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
- else
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
- if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- capacity = iwl_read_targ_mem(priv, base);
- num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
- mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
- next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
- } else
- return;
-
- if (num_wraps == priv->event_log.num_wraps) {
- iwl_print_cont_event_trace(priv,
- base, priv->event_log.next_entry,
- next_entry - priv->event_log.next_entry,
- mode);
- priv->event_log.non_wraps_count++;
- } else {
- if ((num_wraps - priv->event_log.num_wraps) > 1)
- priv->event_log.wraps_more_count++;
- else
- priv->event_log.wraps_once_count++;
- trace_iwlwifi_dev_ucode_wrap_event(priv,
- num_wraps - priv->event_log.num_wraps,
- next_entry, priv->event_log.next_entry);
- if (next_entry < priv->event_log.next_entry) {
- iwl_print_cont_event_trace(priv, base,
- priv->event_log.next_entry,
- capacity - priv->event_log.next_entry,
- mode);
-
- iwl_print_cont_event_trace(priv, base, 0,
- next_entry, mode);
- } else {
- iwl_print_cont_event_trace(priv, base,
- next_entry, capacity - next_entry,
- mode);
-
- iwl_print_cont_event_trace(priv, base, 0,
- next_entry, mode);
- }
- }
- priv->event_log.num_wraps = num_wraps;
- priv->event_log.next_entry = next_entry;
-}
-
-/**
- * iwl_bg_ucode_trace - Timer callback to log ucode event
- *
- * The timer is continually set to execute every
- * UCODE_TRACE_PERIOD milliseconds after the last timer expired
- * this function is to perform continuous uCode event logging operation
- * if enabled
- */
-static void iwl_bg_ucode_trace(unsigned long data)
-{
- struct iwl_priv *priv = (struct iwl_priv *)data;
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- if (priv->event_log.ucode_trace) {
- iwl_continuous_event_trace(priv);
- /* Reschedule the timer to occur in UCODE_TRACE_PERIOD */
- mod_timer(&priv->ucode_trace,
- jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
- }
-}
-
static void iwl_rx_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
@@ -809,14 +689,12 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
unsigned long status = priv->status;
- IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n",
+ IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n",
(flags & HW_CARD_DISABLED) ? "Kill" : "On",
- (flags & SW_CARD_DISABLED) ? "Kill" : "On",
- (flags & CT_CARD_DISABLED) ?
- "Reached" : "Not reached");
+ (flags & SW_CARD_DISABLED) ? "Kill" : "On");
if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
- CT_CARD_DISABLED)) {
+ RF_CARD_DISABLED)) {
iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
@@ -830,10 +708,10 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
iwl_write_direct32(priv, HBUS_TARG_MBX_C,
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
}
- if (flags & CT_CARD_DISABLED)
+ if (flags & RF_CARD_DISABLED)
iwl_tt_enter_ct_kill(priv);
}
- if (!(flags & CT_CARD_DISABLED))
+ if (!(flags & RF_CARD_DISABLED))
iwl_tt_exit_ct_kill(priv);
if (flags & HW_CARD_DISABLED)
@@ -883,8 +761,6 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv)
priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
- priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
- iwl_rx_spectrum_measure_notif;
priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
iwl_rx_pm_debug_statistics_notif;
@@ -898,6 +774,7 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv)
priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_reply_statistics;
priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics;
+ iwl_setup_spectrum_handlers(priv);
iwl_setup_rx_scan_handlers(priv);
/* status change handler */
@@ -1757,7 +1634,7 @@ static const char *desc_lookup_text[] = {
"DEBUG_1",
"DEBUG_2",
"DEBUG_3",
- "ADVANCED SYSASSERT"
+ "UNKNOWN"
};
static const char *desc_lookup(int i)
@@ -1828,9 +1705,8 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
* iwl_print_event_log - Dump error event log to syslog
*
*/
-static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
- u32 num_events, u32 mode,
- int pos, char **buf, size_t bufsz)
+static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
+ u32 num_events, u32 mode)
{
u32 i;
u32 base; /* SRAM byte address of event log header */
@@ -1840,7 +1716,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
unsigned long reg_flags;
if (num_events == 0)
- return pos;
+ return;
if (priv->ucode_type == UCODE_INIT)
base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
else
@@ -1868,44 +1744,27 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
if (mode == 0) {
/* data, ev */
- if (bufsz) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- "EVT_LOG:0x%08x:%04u\n",
- time, ev);
- } else {
- trace_iwlwifi_dev_ucode_event(priv, 0,
- time, ev);
- IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n",
- time, ev);
- }
+ trace_iwlwifi_dev_ucode_event(priv, 0, time, ev);
+ IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev);
} else {
data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- if (bufsz) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- "EVT_LOGT:%010u:0x%08x:%04u\n",
- time, data, ev);
- } else {
- IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
+ IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
time, data, ev);
- trace_iwlwifi_dev_ucode_event(priv, time,
- data, ev);
- }
+ trace_iwlwifi_dev_ucode_event(priv, time, data, ev);
}
}
/* Allow device to power down */
iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
- return pos;
}
/**
* iwl_print_last_event_logs - Dump the newest # of event log to syslog
*/
-static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
- u32 num_wraps, u32 next_entry,
- u32 size, u32 mode,
- int pos, char **buf, size_t bufsz)
+static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
+ u32 num_wraps, u32 next_entry,
+ u32 size, u32 mode)
{
/*
* display the newest DEFAULT_LOG_ENTRIES entries
@@ -1913,26 +1772,21 @@ static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
*/
if (num_wraps) {
if (next_entry < size) {
- pos = iwl_print_event_log(priv,
- capacity - (size - next_entry),
- size - next_entry, mode,
- pos, buf, bufsz);
- pos = iwl_print_event_log(priv, 0,
- next_entry, mode,
- pos, buf, bufsz);
+ iwl_print_event_log(priv,
+ capacity - (size - next_entry),
+ size - next_entry, mode);
+ iwl_print_event_log(priv, 0,
+ next_entry, mode);
} else
- pos = iwl_print_event_log(priv, next_entry - size,
- size, mode, pos, buf, bufsz);
+ iwl_print_event_log(priv, next_entry - size,
+ size, mode);
} else {
- if (next_entry < size) {
- pos = iwl_print_event_log(priv, 0, next_entry,
- mode, pos, buf, bufsz);
- } else {
- pos = iwl_print_event_log(priv, next_entry - size,
- size, mode, pos, buf, bufsz);
- }
+ if (next_entry < size)
+ iwl_print_event_log(priv, 0, next_entry, mode);
+ else
+ iwl_print_event_log(priv, next_entry - size,
+ size, mode);
}
- return pos;
}
/* For sanity check only. Actual size is determined by uCode, typ. 512 */
@@ -1940,8 +1794,7 @@ static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
-int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
- char **buf, bool display)
+void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log)
{
u32 base; /* SRAM byte address of event log header */
u32 capacity; /* event log capacity in # entries */
@@ -1949,8 +1802,6 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
u32 num_wraps; /* # times uCode wrapped to top of log */
u32 next_entry; /* index of next entry to be written by uCode */
u32 size; /* # entries that we'll print */
- int pos = 0;
- size_t bufsz = 0;
if (priv->ucode_type == UCODE_INIT)
base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
@@ -1961,7 +1812,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
IWL_ERR(priv,
"Invalid event log pointer 0x%08X for %s uCode\n",
base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
- return -EINVAL;
+ return;
}
/* event log header */
@@ -1987,7 +1838,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
/* bail out if nothing in log */
if (size == 0) {
IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
- return pos;
+ return;
}
#ifdef CONFIG_IWLWIFI_DEBUG
@@ -2002,15 +1853,6 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
size);
#ifdef CONFIG_IWLWIFI_DEBUG
- if (display) {
- if (full_log)
- bufsz = capacity * 48;
- else
- bufsz = size * 48;
- *buf = kmalloc(bufsz, GFP_KERNEL);
- if (!*buf)
- return -ENOMEM;
- }
if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
/*
* if uCode has wrapped back to top of log,
@@ -2018,22 +1860,17 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
* i.e the next one that uCode would fill.
*/
if (num_wraps)
- pos = iwl_print_event_log(priv, next_entry,
- capacity - next_entry, mode,
- pos, buf, bufsz);
+ iwl_print_event_log(priv, next_entry,
+ capacity - next_entry, mode);
/* (then/else) start at top of log */
- pos = iwl_print_event_log(priv, 0,
- next_entry, mode, pos, buf, bufsz);
+ iwl_print_event_log(priv, 0, next_entry, mode);
} else
- pos = iwl_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
+ iwl_print_last_event_logs(priv, capacity, num_wraps,
+ next_entry, size, mode);
#else
- pos = iwl_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
+ iwl_print_last_event_logs(priv, capacity, num_wraps,
+ next_entry, size, mode);
#endif
- return pos;
}
/**
@@ -2439,6 +2276,18 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
return;
}
+static void iwl_bg_up(struct work_struct *data)
+{
+ struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ mutex_lock(&priv->mutex);
+ __iwl_up(priv);
+ mutex_unlock(&priv->mutex);
+}
+
static void iwl_bg_restart(struct work_struct *data)
{
struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
@@ -2455,13 +2304,7 @@ static void iwl_bg_restart(struct work_struct *data)
ieee80211_restart_hw(priv->hw);
} else {
iwl_down(priv);
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- mutex_lock(&priv->mutex);
- __iwl_up(priv);
- mutex_unlock(&priv->mutex);
+ queue_work(priv->workqueue, &priv->up);
}
}
@@ -2597,7 +2440,7 @@ void iwl_post_associate(struct iwl_priv *priv)
* Not a mac80211 entry point function, but it fits in with all the
* other mac80211 functions grouped here.
*/
-static int iwl_mac_setup_register(struct iwl_priv *priv)
+static int iwl_setup_mac(struct iwl_priv *priv)
{
int ret;
struct ieee80211_hw *hw = priv->hw;
@@ -2613,10 +2456,6 @@ static int iwl_mac_setup_register(struct iwl_priv *priv)
hw->flags |= IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
- if (priv->cfg->sku & IWL_SKU_N)
- hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
- IEEE80211_HW_SUPPORTS_STATIC_SMPS;
-
hw->sta_data_size = sizeof(struct iwl_station_priv);
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION) |
@@ -2631,7 +2470,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv)
*/
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
- hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX + 1;
+ hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
/* we create the 802.11 header and a zero-length SSID element */
hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
@@ -2829,18 +2668,14 @@ void iwl_config_ap(struct iwl_priv *priv)
}
static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_key_conf *keyconf,
- struct ieee80211_sta *sta,
- u32 iv32, u16 *phase1key)
+ struct ieee80211_key_conf *keyconf, const u8 *addr,
+ u32 iv32, u16 *phase1key)
{
struct iwl_priv *priv = hw->priv;
IWL_DEBUG_MAC80211(priv, "enter\n");
- iwl_update_tkip_key(priv, keyconf,
- sta ? sta->addr : iwl_bcast_addr,
- iv32, phase1key);
+ iwl_update_tkip_key(priv, keyconf, addr, iv32, phase1key);
IWL_DEBUG_MAC80211(priv, "leave\n");
}
@@ -2941,28 +2776,14 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
return ret;
case IEEE80211_AMPDU_TX_START:
IWL_DEBUG_HT(priv, "start Tx\n");
- ret = iwl_tx_agg_start(priv, sta->addr, tid, ssn);
- if (ret == 0) {
- priv->agg_tids_count++;
- IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
- priv->agg_tids_count);
- }
- return ret;
+ return iwl_tx_agg_start(priv, sta->addr, tid, ssn);
case IEEE80211_AMPDU_TX_STOP:
IWL_DEBUG_HT(priv, "stop Tx\n");
ret = iwl_tx_agg_stop(priv, sta->addr, tid);
- if ((ret == 0) && (priv->agg_tids_count > 0)) {
- priv->agg_tids_count--;
- IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
- priv->agg_tids_count);
- }
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return 0;
else
return ret;
- case IEEE80211_AMPDU_TX_OPERATIONAL:
- /* do nothing */
- return -EOPNOTSUPP;
default:
IWL_DEBUG_HT(priv, "unknown\n");
return -EINVAL;
@@ -3012,8 +2833,6 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw,
break;
case STA_NOTIFY_AWAKE:
WARN_ON(!sta_priv->client);
- if (!sta_priv->asleep)
- break;
sta_priv->asleep = false;
sta_id = iwl_find_station(priv, sta->addr);
if (sta_id != IWL_INVALID_STATION)
@@ -3290,6 +3109,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
init_waitqueue_head(&priv->wait_command_queue);
+ INIT_WORK(&priv->up, iwl_bg_up);
INIT_WORK(&priv->restart, iwl_bg_restart);
INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
@@ -3306,10 +3126,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
priv->statistics_periodic.data = (unsigned long)priv;
priv->statistics_periodic.function = iwl_bg_statistics_periodic;
- init_timer(&priv->ucode_trace);
- priv->ucode_trace.data = (unsigned long)priv;
- priv->ucode_trace.function = iwl_bg_ucode_trace;
-
if (!priv->cfg->use_isr_legacy)
tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
iwl_irq_tasklet, (unsigned long)priv);
@@ -3328,7 +3144,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
cancel_delayed_work(&priv->alive_start);
cancel_work_sync(&priv->beacon_update);
del_timer_sync(&priv->statistics_periodic);
- del_timer_sync(&priv->ucode_trace);
}
static void iwl_init_hw_rates(struct iwl_priv *priv,
@@ -3364,7 +3179,6 @@ static int iwl_init_drv(struct iwl_priv *priv)
INIT_LIST_HEAD(&priv->free_frames);
mutex_init(&priv->mutex);
- mutex_init(&priv->sync_cmd_mutex);
/* Clear the driver's (not device's) station table */
iwl_clear_stations_table(priv);
@@ -3374,15 +3188,6 @@ static int iwl_init_drv(struct iwl_priv *priv)
priv->band = IEEE80211_BAND_2GHZ;
priv->iw_mode = NL80211_IFTYPE_STATION;
- priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
- priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
- priv->agg_tids_count = 0;
-
- /* initialize force reset */
- priv->force_reset[IWL_RF_RESET].reset_duration =
- IWL_DELAY_NEXT_FORCE_RF_RESET;
- priv->force_reset[IWL_FW_RESET].reset_duration =
- IWL_DELAY_NEXT_FORCE_FW_RELOAD;
/* Choose which receivers/antennas to use */
if (priv->cfg->ops->hcmd->set_rxon_chain)
@@ -3459,6 +3264,7 @@ static struct ieee80211_ops iwl_hw_ops = {
.set_key = iwl_mac_set_key,
.update_tkip_key = iwl_mac_update_tkip_key,
.get_stats = iwl_mac_get_stats,
+ .get_tx_stats = iwl_mac_get_tx_stats,
.conf_tx = iwl_mac_conf_tx,
.reset_tsf = iwl_mac_reset_tsf,
.bss_info_changed = iwl_bss_info_changed,
@@ -3559,14 +3365,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
*/
spin_lock_init(&priv->reg_lock);
spin_lock_init(&priv->lock);
-
- /*
- * stop and reset the on-board processor just in case it is in a
- * strange state ... like being left stranded by a primary kernel
- * and this is now the kdump kernel trying to start up
- */
- iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
-
iwl_hw_detect(priv);
IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n",
priv->cfg->name, priv->hw_rev);
@@ -3641,9 +3439,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
iwl_setup_deferred_work(priv);
iwl_setup_rx_handlers(priv);
- /*********************************************
- * 8. Enable interrupts and read RFKILL state
- *********************************************/
+ /**********************************
+ * 8. Setup and register mac80211
+ **********************************/
/* enable interrupts if needed: hw bug w/a */
pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
@@ -3654,6 +3452,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
iwl_enable_interrupts(priv);
+ err = iwl_setup_mac(priv);
+ if (err)
+ goto out_remove_sysfs;
+
+ err = iwl_dbgfs_register(priv, DRV_NAME);
+ if (err)
+ IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
+
/* If platform's RF_KILL switch is NOT set to KILL */
if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
clear_bit(STATUS_RF_KILL_HW, &priv->status);
@@ -3665,18 +3471,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
iwl_power_initialize(priv);
iwl_tt_initialize(priv);
-
- /**************************************************
- * 9. Setup and register with mac80211 and debugfs
- **************************************************/
- err = iwl_mac_setup_register(priv);
- if (err)
- goto out_remove_sysfs;
-
- err = iwl_dbgfs_register(priv, DRV_NAME);
- if (err)
- IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
-
return 0;
out_remove_sysfs:
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-calib.c b/trunk/drivers/net/wireless/iwlwifi/iwl-calib.c
index 845831ac053e..95a57b36a7ea 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -414,6 +414,7 @@ static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv,
/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
static int iwl_sensitivity_write(struct iwl_priv *priv)
{
+ int ret = 0;
struct iwl_sensitivity_cmd cmd ;
struct iwl_sensitivity_data *data = NULL;
struct iwl_host_cmd cmd_out = {
@@ -476,7 +477,11 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)
memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
sizeof(u16)*HD_TABLE_SIZE);
- return iwl_send_cmd(priv, &cmd_out);
+ ret = iwl_send_cmd(priv, &cmd_out);
+ if (ret)
+ IWL_ERR(priv, "SENSITIVITY_CMD failed\n");
+
+ return ret;
}
void iwl_init_sensitivity(struct iwl_priv *priv)
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-calib.h b/trunk/drivers/net/wireless/iwlwifi/iwl-calib.h
index 2b7b1df83ba0..b6cef989a796 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-calib.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-calib.h
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h b/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h
index ab3c77b92cc8..cfd6c8423113 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -120,6 +120,7 @@ enum {
CALIBRATION_COMPLETE_NOTIFICATION = 0x67,
/* 802.11h related */
+ RADAR_NOTIFICATION = 0x70, /* not used */
REPLY_QUIET_CMD = 0x71, /* not used */
REPLY_CHANNEL_SWITCH = 0x72,
CHANNEL_SWITCH_NOTIFICATION = 0x73,
@@ -2247,22 +2248,10 @@ struct iwl_link_quality_cmd {
__le32 reserved2;
} __attribute__ ((packed));
-/*
- * BT configuration enable flags:
- * bit 0 - 1: BT channel announcement enabled
- * 0: disable
- * bit 1 - 1: priority of BT device enabled
- * 0: disable
- * bit 2 - 1: BT 2 wire support enabled
- * 0: disable
- */
-#define BT_COEX_DISABLE (0x0)
-#define BT_ENABLE_CHANNEL_ANNOUNCE BIT(0)
-#define BT_ENABLE_PRIORITY BIT(1)
-#define BT_ENABLE_2_WIRE BIT(2)
-
#define BT_COEX_DISABLE (0x0)
-#define BT_COEX_ENABLE (BT_ENABLE_CHANNEL_ANNOUNCE | BT_ENABLE_PRIORITY)
+#define BT_COEX_MODE_2W (0x1)
+#define BT_COEX_MODE_3W (0x2)
+#define BT_COEX_MODE_4W (0x3)
#define BT_LEAD_TIME_MIN (0x0)
#define BT_LEAD_TIME_DEF (0x1E)
@@ -2521,7 +2510,7 @@ struct iwl_card_state_notif {
#define HW_CARD_DISABLED 0x01
#define SW_CARD_DISABLED 0x02
-#define CT_CARD_DISABLED 0x04
+#define RF_CARD_DISABLED 0x04
#define RXON_CARD_DISABLED 0x10
struct iwl_ct_kill_config {
@@ -2623,6 +2612,7 @@ struct iwl_ssid_ie {
#define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF)
#define IWL_GOOD_CRC_TH cpu_to_le16(1)
#define IWL_MAX_SCAN_SIZE 1024
+#define IWL_MAX_CMD_SIZE 4096
#define IWL_MAX_PROBE_REQUEST 200
/*
@@ -2995,7 +2985,7 @@ struct statistics_rx_ht_phy {
__le32 agg_crc32_good;
__le32 agg_mpdu_cnt;
__le32 agg_cnt;
- __le32 unsupport_mcs;
+ __le32 reserved2;
} __attribute__ ((packed));
#define INTERFERENCE_DATA_AVAILABLE cpu_to_le32(1)
@@ -3098,8 +3088,8 @@ struct statistics_div {
} __attribute__ ((packed));
struct statistics_general {
- __le32 temperature; /* radio temperature */
- __le32 temperature_m; /* for 5000 and up, this is radio voltage */
+ __le32 temperature;
+ __le32 temperature_m;
struct statistics_dbg dbg;
__le32 sleep_time;
__le32 slots_out;
@@ -3107,12 +3097,7 @@ struct statistics_general {
__le32 ttl_timestamp;
struct statistics_div div;
__le32 rx_enable_counter;
- /*
- * num_of_sos_states:
- * count the number of times we have to re-tune
- * in order to get out of bad PHY status
- */
- __le32 num_of_sos_states;
+ __le32 reserved1;
__le32 reserved2;
__le32 reserved3;
} __attribute__ ((packed));
@@ -3177,30 +3162,13 @@ struct iwl_notif_statistics {
/*
* MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command)
- *
- * uCode send MISSED_BEACONS_NOTIFICATION to driver when detect beacon missed
- * in regardless of how many missed beacons, which mean when driver receive the
- * notification, inside the command, it can find all the beacons information
- * which include number of total missed beacons, number of consecutive missed
- * beacons, number of beacons received and number of beacons expected to
- * receive.
- *
- * If uCode detected consecutive_missed_beacons > 5, it will reset the radio
- * in order to bring the radio/PHY back to working state; which has no relation
- * to when driver will perform sensitivity calibration.
- *
- * Driver should set it own missed_beacon_threshold to decide when to perform
- * sensitivity calibration based on number of consecutive missed beacons in
- * order to improve overall performance, especially in noisy environment.
- *
*/
-
-#define IWL_MISSED_BEACON_THRESHOLD_MIN (1)
-#define IWL_MISSED_BEACON_THRESHOLD_DEF (5)
-#define IWL_MISSED_BEACON_THRESHOLD_MAX IWL_MISSED_BEACON_THRESHOLD_DEF
+/* if ucode missed CONSECUTIVE_MISSED_BCONS_TH beacons in a row,
+ * then this notification will be sent. */
+#define CONSECUTIVE_MISSED_BCONS_TH 20
struct iwl_missed_beacon_notif {
- __le32 consecutive_missed_beacons;
+ __le32 consequtive_missed_beacons;
__le32 total_missed_becons;
__le32 num_expected_beacons;
__le32 num_recvd_beacons;
@@ -3470,7 +3438,11 @@ enum {
IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7,
IWL_PHY_CALIBRATE_DC_CMD = 8,
IWL_PHY_CALIBRATE_LO_CMD = 9,
+ IWL_PHY_CALIBRATE_RX_BB_CMD = 10,
IWL_PHY_CALIBRATE_TX_IQ_CMD = 11,
+ IWL_PHY_CALIBRATE_RX_IQ_CMD = 12,
+ IWL_PHY_CALIBRATION_NOISE_CMD = 13,
+ IWL_PHY_CALIBRATE_AGC_TABLE_CMD = 14,
IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16,
IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17,
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c
index 112149e9b31e..f36f804804fc 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2,7 +2,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -47,26 +47,6 @@ MODULE_VERSION(IWLWIFI_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
-/*
- * set bt_coex_active to true, uCode will do kill/defer
- * every time the priority line is asserted (BT is sending signals on the
- * priority line in the PCIx).
- * set bt_coex_active to false, uCode will ignore the BT activity and
- * perform the normal operation
- *
- * User might experience transmit issue on some platform due to WiFi/BT
- * co-exist problem. The possible behaviors are:
- * Able to scan and finding all the available AP
- * Not able to associate with any AP
- * On those platforms, WiFi communication can be restored by set
- * "bt_coex_active" module parameter to "false"
- *
- * default: bt_coex_active = true (BT_COEX_ENABLE)
- */
-static bool bt_coex_active = true;
-module_param(bt_coex_active, bool, S_IRUGO);
-MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist\n");
-
static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
{COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
0, COEX_UNASSOC_IDLE_FLAGS},
@@ -277,8 +257,8 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
spin_lock_irqsave(&priv->lock, flags);
priv->cfg->ops->lib->apm_ops.init(priv);
- /* Set interrupt coalescing calibration timer to default (512 usecs) */
- iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF);
+ /* Set interrupt coalescing timer to 512 usecs */
+ iwl_write8(priv, CSR_INT_COALESCING, 512 / 32);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -470,6 +450,8 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
if (priv->cfg->ht_greenfield_support)
ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
+ ht_info->cap |= (IEEE80211_HT_CAP_SM_PS &
+ (priv->cfg->sm_ps_mode << 2));
max_bit_rate = MAX_BIT_RATE_20_MHZ;
if (priv->hw_params.ht40_channel & BIT(band)) {
ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
@@ -654,7 +636,7 @@ EXPORT_SYMBOL(iwlcore_rts_tx_cmd_flag);
static bool is_single_rx_stream(struct iwl_priv *priv)
{
- return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
+ return !priv->current_ht_config.is_ht ||
priv->current_ht_config.single_chain_sufficient;
}
@@ -1021,18 +1003,28 @@ static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
*/
static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
{
- /* # Rx chains when idling, depending on SMPS mode */
- switch (priv->current_ht_config.smps) {
- case IEEE80211_SMPS_STATIC:
- case IEEE80211_SMPS_DYNAMIC:
- return IWL_NUM_IDLE_CHAINS_SINGLE;
- case IEEE80211_SMPS_OFF:
- return active_cnt;
+ int idle_cnt = active_cnt;
+ bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
+
+ /* # Rx chains when idling and maybe trying to save power */
+ switch (priv->cfg->sm_ps_mode) {
+ case WLAN_HT_CAP_SM_PS_STATIC:
+ idle_cnt = (is_cam) ? active_cnt : IWL_NUM_IDLE_CHAINS_SINGLE;
+ break;
+ case WLAN_HT_CAP_SM_PS_DYNAMIC:
+ idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL :
+ IWL_NUM_IDLE_CHAINS_SINGLE;
+ break;
+ case WLAN_HT_CAP_SM_PS_DISABLED:
+ break;
+ case WLAN_HT_CAP_SM_PS_INVALID:
default:
- WARN(1, "invalid SMPS mode %d",
- priv->current_ht_config.smps);
- return active_cnt;
+ IWL_ERR(priv, "invalid sm_ps mode %u\n",
+ priv->cfg->sm_ps_mode);
+ WARN_ON(1);
+ break;
}
+ return idle_cnt;
}
/* up to 4 chains */
@@ -1371,11 +1363,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
priv->cfg->ops->lib->dump_nic_error_log(priv);
- if (priv->cfg->ops->lib->dump_csr)
- priv->cfg->ops->lib->dump_csr(priv);
- if (priv->cfg->ops->lib->dump_fh)
- priv->cfg->ops->lib->dump_fh(priv, NULL, false);
- priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false);
+ priv->cfg->ops->lib->dump_nic_event_log(priv, false);
#ifdef CONFIG_IWLWIFI_DEBUG
if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)
iwl_print_rx_config_cmd(priv);
@@ -1670,9 +1658,9 @@ EXPORT_SYMBOL(iwl_set_tx_power);
void iwl_free_isr_ict(struct iwl_priv *priv)
{
if (priv->ict_tbl_vir) {
- dma_free_coherent(&priv->pci_dev->dev,
- (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
- priv->ict_tbl_vir, priv->ict_tbl_dma);
+ pci_free_consistent(priv->pci_dev, (sizeof(u32) * ICT_COUNT) +
+ PAGE_SIZE, priv->ict_tbl_vir,
+ priv->ict_tbl_dma);
priv->ict_tbl_vir = NULL;
}
}
@@ -1688,9 +1676,9 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv)
if (priv->cfg->use_isr_legacy)
return 0;
/* allocate shrared data table */
- priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev,
- (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
- &priv->ict_tbl_dma, GFP_KERNEL);
+ priv->ict_tbl_vir = pci_alloc_consistent(priv->pci_dev, (sizeof(u32) *
+ ICT_COUNT) + PAGE_SIZE,
+ &priv->ict_tbl_dma);
if (!priv->ict_tbl_vir)
return -ENOMEM;
@@ -1825,16 +1813,6 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
if (val == 0xffffffff)
val = 0;
- /*
- * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
- * (bit 15 before shifting it to 31) to clear when using interrupt
- * coalescing. fortunately, bits 18 and 19 stay set when this happens
- * so we use them to decide on the real state of the Rx bit.
- * In order words, bit 15 is set if bit 18 or bit 19 are set.
- */
- if (val & 0xC0000)
- val |= 0x8000;
-
inta = (0xff & val) | ((0xff00 & val) << 16);
IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n",
inta, inta_mask, val);
@@ -1997,20 +1975,13 @@ EXPORT_SYMBOL(iwl_isr_legacy);
int iwl_send_bt_config(struct iwl_priv *priv)
{
struct iwl_bt_cmd bt_cmd = {
+ .flags = BT_COEX_MODE_4W,
.lead_time = BT_LEAD_TIME_DEF,
.max_kill = BT_MAX_KILL_DEF,
.kill_ack_mask = 0,
.kill_cts_mask = 0,
};
- if (!bt_coex_active)
- bt_cmd.flags = BT_COEX_DISABLE;
- else
- bt_cmd.flags = BT_COEX_ENABLE;
-
- IWL_DEBUG_INFO(priv, "BT coex %s\n",
- (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
-
return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
sizeof(struct iwl_bt_cmd), &bt_cmd);
}
@@ -2628,43 +2599,44 @@ int iwl_set_mode(struct iwl_priv *priv, int mode)
EXPORT_SYMBOL(iwl_set_mode);
int iwl_mac_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct iwl_priv *priv = hw->priv;
- int err = 0;
-
- IWL_DEBUG_MAC80211(priv, "enter: type %d\n", vif->type);
+ unsigned long flags;
- mutex_lock(&priv->mutex);
+ IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type);
if (priv->vif) {
IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n");
- err = -EOPNOTSUPP;
- goto out;
+ return -EOPNOTSUPP;
}
- priv->vif = vif;
- priv->iw_mode = vif->type;
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->vif = conf->vif;
+ priv->iw_mode = conf->type;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ mutex_lock(&priv->mutex);
- if (vif->addr) {
- IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr);
- memcpy(priv->mac_addr, vif->addr, ETH_ALEN);
+ if (conf->mac_addr) {
+ IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr);
+ memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
}
- if (iwl_set_mode(priv, vif->type) == -EAGAIN)
+ if (iwl_set_mode(priv, conf->type) == -EAGAIN)
/* we are not ready, will run again when ready */
set_bit(STATUS_MODE_PENDING, &priv->status);
- out:
mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
- return err;
+ return 0;
}
EXPORT_SYMBOL(iwl_mac_add_interface);
void iwl_mac_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct iwl_priv *priv = hw->priv;
@@ -2677,7 +2649,7 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
iwlcore_commit_rxon(priv);
}
- if (priv->vif == vif) {
+ if (priv->vif == conf->vif) {
priv->vif = NULL;
memset(priv->bssid, 0, ETH_ALEN);
}
@@ -2717,21 +2689,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
}
- if (changed & (IEEE80211_CONF_CHANGE_SMPS |
- IEEE80211_CONF_CHANGE_CHANNEL)) {
- /* mac80211 uses static for non-HT which is what we want */
- priv->current_ht_config.smps = conf->smps_mode;
-
- /*
- * Recalculate chain counts.
- *
- * If monitor mode is enabled then mac80211 will
- * set up the SM PS mode to OFF if an HT channel is
- * configured.
- */
- if (priv->cfg->ops->hcmd->set_rxon_chain)
- priv->cfg->ops->hcmd->set_rxon_chain(priv);
- }
/* during scanning mac80211 will delay channel setting until
* scan finish with changed = 0
@@ -2829,6 +2786,10 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
iwl_set_tx_power(priv, conf->power_level, false);
}
+ /* call to ensure that 4965 rx_chain is set properly in monitor mode */
+ if (priv->cfg->ops->hcmd->set_rxon_chain)
+ priv->cfg->ops->hcmd->set_rxon_chain(priv);
+
if (!iwl_is_ready(priv)) {
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
goto out;
@@ -2851,6 +2812,42 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
}
EXPORT_SYMBOL(iwl_mac_config);
+int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats)
+{
+ struct iwl_priv *priv = hw->priv;
+ int i, avail;
+ struct iwl_tx_queue *txq;
+ struct iwl_queue *q;
+ unsigned long flags;
+
+ IWL_DEBUG_MAC80211(priv, "enter\n");
+
+ if (!iwl_is_ready_rf(priv)) {
+ IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
+ return -EIO;
+ }
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ for (i = 0; i < AC_NUM; i++) {
+ txq = &priv->txq[i];
+ q = &txq->q;
+ avail = iwl_queue_space(q);
+
+ stats[i].len = q->n_window - avail;
+ stats[i].limit = q->n_window - q->high_mark;
+ stats[i].count = q->n_window;
+
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ IWL_DEBUG_MAC80211(priv, "leave\n");
+
+ return 0;
+}
+EXPORT_SYMBOL(iwl_mac_get_tx_stats);
+
void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = hw->priv;
@@ -3200,207 +3197,6 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
EXPORT_SYMBOL(iwl_update_stats);
#endif
-const static char *get_csr_string(int cmd)
-{
- switch (cmd) {
- IWL_CMD(CSR_HW_IF_CONFIG_REG);
- IWL_CMD(CSR_INT_COALESCING);
- IWL_CMD(CSR_INT);
- IWL_CMD(CSR_INT_MASK);
- IWL_CMD(CSR_FH_INT_STATUS);
- IWL_CMD(CSR_GPIO_IN);
- IWL_CMD(CSR_RESET);
- IWL_CMD(CSR_GP_CNTRL);
- IWL_CMD(CSR_HW_REV);
- IWL_CMD(CSR_EEPROM_REG);
- IWL_CMD(CSR_EEPROM_GP);
- IWL_CMD(CSR_OTP_GP_REG);
- IWL_CMD(CSR_GIO_REG);
- IWL_CMD(CSR_GP_UCODE_REG);
- IWL_CMD(CSR_GP_DRIVER_REG);
- IWL_CMD(CSR_UCODE_DRV_GP1);
- IWL_CMD(CSR_UCODE_DRV_GP2);
- IWL_CMD(CSR_LED_REG);
- IWL_CMD(CSR_DRAM_INT_TBL_REG);
- IWL_CMD(CSR_GIO_CHICKEN_BITS);
- IWL_CMD(CSR_ANA_PLL_CFG);
- IWL_CMD(CSR_HW_REV_WA_REG);
- IWL_CMD(CSR_DBG_HPET_MEM_REG);
- default:
- return "UNKNOWN";
-
- }
-}
-
-void iwl_dump_csr(struct iwl_priv *priv)
-{
- int i;
- u32 csr_tbl[] = {
- CSR_HW_IF_CONFIG_REG,
- CSR_INT_COALESCING,
- CSR_INT,
- CSR_INT_MASK,
- CSR_FH_INT_STATUS,
- CSR_GPIO_IN,
- CSR_RESET,
- CSR_GP_CNTRL,
- CSR_HW_REV,
- CSR_EEPROM_REG,
- CSR_EEPROM_GP,
- CSR_OTP_GP_REG,
- CSR_GIO_REG,
- CSR_GP_UCODE_REG,
- CSR_GP_DRIVER_REG,
- CSR_UCODE_DRV_GP1,
- CSR_UCODE_DRV_GP2,
- CSR_LED_REG,
- CSR_DRAM_INT_TBL_REG,
- CSR_GIO_CHICKEN_BITS,
- CSR_ANA_PLL_CFG,
- CSR_HW_REV_WA_REG,
- CSR_DBG_HPET_MEM_REG
- };
- IWL_ERR(priv, "CSR values:\n");
- IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is "
- "CSR_INT_PERIODIC_REG)\n");
- for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) {
- IWL_ERR(priv, " %25s: 0X%08x\n",
- get_csr_string(csr_tbl[i]),
- iwl_read32(priv, csr_tbl[i]));
- }
-}
-EXPORT_SYMBOL(iwl_dump_csr);
-
-const static char *get_fh_string(int cmd)
-{
- switch (cmd) {
- IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
- IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
- IWL_CMD(FH_RSCSR_CHNL0_WPTR);
- IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
- IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
- IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
- IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
- IWL_CMD(FH_TSSR_TX_STATUS_REG);
- IWL_CMD(FH_TSSR_TX_ERROR_REG);
- default:
- return "UNKNOWN";
-
- }
-}
-
-int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
-{
- int i;
-#ifdef CONFIG_IWLWIFI_DEBUG
- int pos = 0;
- size_t bufsz = 0;
-#endif
- u32 fh_tbl[] = {
- FH_RSCSR_CHNL0_STTS_WPTR_REG,
- FH_RSCSR_CHNL0_RBDCB_BASE_REG,
- FH_RSCSR_CHNL0_WPTR,
- FH_MEM_RCSR_CHNL0_CONFIG_REG,
- FH_MEM_RSSR_SHARED_CTRL_REG,
- FH_MEM_RSSR_RX_STATUS_REG,
- FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
- FH_TSSR_TX_STATUS_REG,
- FH_TSSR_TX_ERROR_REG
- };
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (display) {
- bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
- *buf = kmalloc(bufsz, GFP_KERNEL);
- if (!*buf)
- return -ENOMEM;
- pos += scnprintf(*buf + pos, bufsz - pos,
- "FH register values:\n");
- for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- " %34s: 0X%08x\n",
- get_fh_string(fh_tbl[i]),
- iwl_read_direct32(priv, fh_tbl[i]));
- }
- return pos;
- }
-#endif
- IWL_ERR(priv, "FH register values:\n");
- for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
- IWL_ERR(priv, " %34s: 0X%08x\n",
- get_fh_string(fh_tbl[i]),
- iwl_read_direct32(priv, fh_tbl[i]));
- }
- return 0;
-}
-EXPORT_SYMBOL(iwl_dump_fh);
-
-static void iwl_force_rf_reset(struct iwl_priv *priv)
-{
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- if (!iwl_is_associated(priv)) {
- IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n");
- return;
- }
- /*
- * There is no easy and better way to force reset the radio,
- * the only known method is switching channel which will force to
- * reset and tune the radio.
- * Use internal short scan (single channel) operation to should
- * achieve this objective.
- * Driver should reset the radio when number of consecutive missed
- * beacon, or any other uCode error condition detected.
- */
- IWL_DEBUG_INFO(priv, "perform radio reset.\n");
- iwl_internal_short_hw_scan(priv);
- return;
-}
-
-
-int iwl_force_reset(struct iwl_priv *priv, int mode)
-{
- struct iwl_force_reset *force_reset;
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return -EINVAL;
-
- if (mode >= IWL_MAX_FORCE_RESET) {
- IWL_DEBUG_INFO(priv, "invalid reset request.\n");
- return -EINVAL;
- }
- force_reset = &priv->force_reset[mode];
- force_reset->reset_request_count++;
- if (force_reset->last_force_reset_jiffies &&
- time_after(force_reset->last_force_reset_jiffies +
- force_reset->reset_duration, jiffies)) {
- IWL_DEBUG_INFO(priv, "force reset rejected\n");
- force_reset->reset_reject_count++;
- return -EAGAIN;
- }
- force_reset->reset_success_count++;
- force_reset->last_force_reset_jiffies = jiffies;
- IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode);
- switch (mode) {
- case IWL_RF_RESET:
- iwl_force_rf_reset(priv);
- break;
- case IWL_FW_RESET:
- IWL_ERR(priv, "On demand firmware reload\n");
- /* Set the FW error flag -- cleared on iwl_down */
- set_bit(STATUS_FW_ERROR, &priv->status);
- wake_up_interruptible(&priv->wait_command_queue);
- /*
- * Keep the restart process from trying to send host
- * commands by clearing the INIT status bit
- */
- clear_bit(STATUS_READY, &priv->status);
- queue_work(priv->workqueue, &priv->restart);
- break;
- }
- return 0;
-}
-
#ifdef CONFIG_PM
int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h
index 4ef7739f9e8e..fe37d6a6bf97 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -63,6 +63,8 @@
#ifndef __iwl_core_h__
#define __iwl_core_h__
+#include
+
/************************
* forward declarations *
************************/
@@ -70,8 +72,8 @@ struct iwl_host_cmd;
struct iwl_cmd;
-#define IWLWIFI_VERSION "in-tree:"
-#define DRV_COPYRIGHT "Copyright(c) 2003-2010 Intel Corporation"
+#define IWLWIFI_VERSION UTS_RELEASE "-k"
+#define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation"
#define DRV_AUTHOR ""
#define IWL_PCI_DEVICE(dev, subdev, cfg) \
@@ -117,7 +119,6 @@ struct iwl_apm_ops {
struct iwl_temp_ops {
void (*temperature)(struct iwl_priv *priv);
void (*set_ct_kill)(struct iwl_priv *priv);
- void (*set_calib_version)(struct iwl_priv *priv);
};
struct iwl_ucode_ops {
@@ -168,11 +169,8 @@ struct iwl_lib_ops {
int (*is_valid_rtc_data_addr)(u32 addr);
/* 1st ucode load */
int (*load_ucode)(struct iwl_priv *priv);
- int (*dump_nic_event_log)(struct iwl_priv *priv,
- bool full_log, char **buf, bool display);
+ void (*dump_nic_event_log)(struct iwl_priv *priv, bool full_log);
void (*dump_nic_error_log)(struct iwl_priv *priv);
- void (*dump_csr)(struct iwl_priv *priv);
- int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display);
int (*set_channel_switch)(struct iwl_priv *priv, u16 channel);
/* power management */
struct iwl_apm_ops apm_ops;
@@ -189,8 +187,6 @@ struct iwl_lib_ops {
/* temperature */
struct iwl_temp_ops temp_ops;
- /* station management */
- void (*add_bcast_station)(struct iwl_priv *priv);
};
struct iwl_led_ops {
@@ -234,9 +230,8 @@ struct iwl_mod_params {
* @chain_noise_num_beacons: number of beacons used to compute chain noise
* @adv_thermal_throttle: support advance thermal throttle
* @support_ct_kill_exit: support ct kill exit condition
+ * @sm_ps_mode: spatial multiplexing power save mode
* @support_wimax_coexist: support wimax/wifi co-exist
- * @plcp_delta_threshold: plcp error rate threshold used to trigger
- * radio tuning when there is a high receiving plcp error rate
*
* We enable the driver to be backward compatible wrt API version. The
* driver specifies which APIs it supports (with @ucode_api_max being the
@@ -292,9 +287,8 @@ struct iwl_cfg {
const bool supports_idle;
bool adv_thermal_throttle;
bool support_ct_kill_exit;
+ u8 sm_ps_mode;
const bool support_wimax_coexist;
- u8 plcp_delta_threshold;
- s32 chain_noise_scale;
};
/***************************
@@ -338,11 +332,13 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
int iwl_commit_rxon(struct iwl_priv *priv);
int iwl_set_mode(struct iwl_priv *priv, int mode);
int iwl_mac_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
+ struct ieee80211_if_init_conf *conf);
void iwl_mac_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
+ struct ieee80211_if_init_conf *conf);
int iwl_mac_config(struct ieee80211_hw *hw, u32 changed);
void iwl_config_ap(struct iwl_priv *priv);
+int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats);
void iwl_mac_reset_tsf(struct ieee80211_hw *hw);
int iwl_alloc_txq_mem(struct iwl_priv *priv);
void iwl_free_txq_mem(struct iwl_priv *priv);
@@ -415,13 +411,13 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
void iwl_cmd_queue_free(struct iwl_priv *priv);
int iwl_rx_queue_alloc(struct iwl_priv *priv);
void iwl_rx_handle(struct iwl_priv *priv);
-void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
+int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
struct iwl_rx_queue *q);
void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
void iwl_rx_replenish(struct iwl_priv *priv);
void iwl_rx_replenish_now(struct iwl_priv *priv);
int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
-void iwl_rx_queue_restock(struct iwl_priv *priv);
+int iwl_rx_queue_restock(struct iwl_priv *priv);
int iwl_rx_queue_space(const struct iwl_rx_queue *q);
void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority);
void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
@@ -429,8 +425,6 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
/* Handlers */
void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
-void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb);
void iwl_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
void iwl_reply_statistics(struct iwl_priv *priv,
@@ -451,9 +445,9 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
void iwl_hw_txq_ctx_free(struct iwl_priv *priv);
int iwl_hw_tx_queue_init(struct iwl_priv *priv,
struct iwl_tx_queue *txq);
+int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
void iwl_free_tfds_in_queue(struct iwl_priv *priv,
int sta_id, int tid, int freed);
-void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
int slots_num, u32 txq_id);
void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
@@ -503,8 +497,6 @@ void iwl_init_scan_params(struct iwl_priv *priv);
int iwl_scan_cancel(struct iwl_priv *priv);
int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req);
-int iwl_internal_short_hw_scan(struct iwl_priv *priv);
-int iwl_force_reset(struct iwl_priv *priv, int mode);
u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
const u8 *ie, int ie_len, int left);
void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
@@ -535,6 +527,14 @@ int iwl_send_calib_results(struct iwl_priv *priv);
int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len);
void iwl_calib_free_results(struct iwl_priv *priv);
+/*******************************************************************************
+ * Spectrum Measureemtns in iwl-spectrum.c
+ ******************************************************************************/
+#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
+void iwl_setup_spectrum_handlers(struct iwl_priv *priv);
+#else
+static inline void iwl_setup_spectrum_handlers(struct iwl_priv *priv) {}
+#endif
/*****************************************************
* S e n d i n g H o s t C o m m a n d s *
*****************************************************/
@@ -583,10 +583,7 @@ int iwl_pci_resume(struct pci_dev *pdev);
* Error Handling Debugging
******************************************************/
void iwl_dump_nic_error_log(struct iwl_priv *priv);
-int iwl_dump_nic_event_log(struct iwl_priv *priv,
- bool full_log, char **buf, bool display);
-void iwl_dump_csr(struct iwl_priv *priv);
-int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display);
+void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log);
#ifdef CONFIG_IWLWIFI_DEBUG
void iwl_print_rx_config_cmd(struct iwl_priv *priv);
#else
@@ -606,7 +603,7 @@ void iwlcore_free_geos(struct iwl_priv *priv);
/*************** DRIVER STATUS FUNCTIONS *****/
#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
-/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */
+#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */
#define STATUS_INT_ENABLED 2
#define STATUS_RF_KILL_HW 3
#define STATUS_CT_KILL 4
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-csr.h b/trunk/drivers/net/wireless/iwlwifi/iwl-csr.h
index 808b7146bead..1ec8cb4d5eae 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -369,7 +369,7 @@
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000)
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001)
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002)
-#define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6 (0x00000004)
+
/* GIO Chicken Bits (PCI Express bus link power management) */
#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000)
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h b/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h
index 1c7b53d511c7..d61293ab67c9 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* Portions of this file are derived from the ipw3945 project.
*
@@ -67,6 +67,57 @@ do { \
DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
} while (0)
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+struct iwl_debugfs {
+ const char *name;
+ struct dentry *dir_drv;
+ struct dentry *dir_data;
+ struct dentry *dir_debug;
+ struct dentry *dir_rf;
+ struct dir_data_files {
+ struct dentry *file_sram;
+ struct dentry *file_nvm;
+ struct dentry *file_stations;
+ struct dentry *file_log_event;
+ struct dentry *file_channels;
+ struct dentry *file_status;
+ struct dentry *file_interrupt;
+ struct dentry *file_qos;
+ struct dentry *file_thermal_throttling;
+ struct dentry *file_led;
+ struct dentry *file_disable_ht40;
+ struct dentry *file_sleep_level_override;
+ struct dentry *file_current_sleep_command;
+ } dbgfs_data_files;
+ struct dir_rf_files {
+ struct dentry *file_disable_sensitivity;
+ struct dentry *file_disable_chain_noise;
+ struct dentry *file_disable_tx_power;
+ } dbgfs_rf_files;
+ struct dir_debug_files {
+ struct dentry *file_rx_statistics;
+ struct dentry *file_tx_statistics;
+ struct dentry *file_traffic_log;
+ struct dentry *file_rx_queue;
+ struct dentry *file_tx_queue;
+ struct dentry *file_ucode_rx_stats;
+ struct dentry *file_ucode_tx_stats;
+ struct dentry *file_ucode_general_stats;
+ struct dentry *file_sensitivity;
+ struct dentry *file_chain_noise;
+ struct dentry *file_tx_power;
+ struct dentry *file_power_save_status;
+ struct dentry *file_clear_ucode_statistics;
+ struct dentry *file_clear_traffic_statistics;
+ } dbgfs_debug_files;
+ u32 sram_offset;
+ u32 sram_len;
+};
+
+int iwl_dbgfs_register(struct iwl_priv *priv, const char *name);
+void iwl_dbgfs_unregister(struct iwl_priv *priv);
+#endif
+
#else
#define IWL_DEBUG(__priv, level, fmt, args...)
#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...)
@@ -75,10 +126,9 @@ static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
{}
#endif /* CONFIG_IWLWIFI_DEBUG */
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-int iwl_dbgfs_register(struct iwl_priv *priv, const char *name);
-void iwl_dbgfs_unregister(struct iwl_priv *priv);
-#else
+
+
+#ifndef CONFIG_IWLWIFI_DEBUGFS
static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
{
return 0;
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 7bf44f146799..21e0f6699daf 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -2,7 +2,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -41,28 +41,43 @@
#include "iwl-calib.h"
/* create and remove of files */
-#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
- if (!debugfs_create_file(#name, mode, parent, priv, \
- &iwl_dbgfs_##name##_ops)) \
- goto err; \
+#define DEBUGFS_ADD_DIR(name, parent) do { \
+ dbgfs->dir_##name = debugfs_create_dir(#name, parent); \
+ if (!(dbgfs->dir_##name)) \
+ goto err; \
} while (0)
-#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \
- struct dentry *__tmp; \
- __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \
- parent, ptr); \
- if (IS_ERR(__tmp) || !__tmp) \
- goto err; \
+#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
+ dbgfs->dbgfs_##parent##_files.file_##name = \
+ debugfs_create_file(#name, mode, \
+ dbgfs->dir_##parent, priv, \
+ &iwl_dbgfs_##name##_ops); \
+ if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \
+ goto err; \
} while (0)
-#define DEBUGFS_ADD_X32(name, parent, ptr) do { \
- struct dentry *__tmp; \
- __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR, \
- parent, ptr); \
- if (IS_ERR(__tmp) || !__tmp) \
- goto err; \
+#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \
+ dbgfs->dbgfs_##parent##_files.file_##name = \
+ debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \
+ dbgfs->dir_##parent, ptr); \
+ if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \
+ || !dbgfs->dbgfs_##parent##_files.file_##name) \
+ goto err; \
} while (0)
+#define DEBUGFS_ADD_X32(name, parent, ptr) do { \
+ dbgfs->dbgfs_##parent##_files.file_##name = \
+ debugfs_create_x32(#name, S_IRUSR, dbgfs->dir_##parent, ptr); \
+ if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \
+ || !dbgfs->dbgfs_##parent##_files.file_##name) \
+ goto err; \
+} while (0)
+
+#define DEBUGFS_REMOVE(name) do { \
+ debugfs_remove(name); \
+ name = NULL; \
+} while (0);
+
/* file operation */
#define DEBUGFS_READ_FUNC(name) \
static ssize_t iwl_dbgfs_##name##_read(struct file *file, \
@@ -110,7 +125,7 @@ static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
char *buf;
int pos = 0;
@@ -169,7 +184,7 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
char *buf;
int pos = 0;
int cnt;
@@ -217,28 +232,28 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
ssize_t ret;
int i;
int pos = 0;
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
size_t bufsz;
/* default is to dump the entire data segment */
- if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
- priv->dbgfs_sram_offset = 0x800000;
+ if (!priv->dbgfs->sram_offset && !priv->dbgfs->sram_len) {
+ priv->dbgfs->sram_offset = 0x800000;
if (priv->ucode_type == UCODE_INIT)
- priv->dbgfs_sram_len = priv->ucode_init_data.len;
+ priv->dbgfs->sram_len = priv->ucode_init_data.len;
else
- priv->dbgfs_sram_len = priv->ucode_data.len;
+ priv->dbgfs->sram_len = priv->ucode_data.len;
}
- bufsz = 30 + priv->dbgfs_sram_len * sizeof(char) * 10;
+ bufsz = 30 + priv->dbgfs->sram_len * sizeof(char) * 10;
buf = kmalloc(bufsz, GFP_KERNEL);
if (!buf)
return -ENOMEM;
pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
- priv->dbgfs_sram_len);
+ priv->dbgfs->sram_len);
pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
- priv->dbgfs_sram_offset);
- for (i = priv->dbgfs_sram_len; i > 0; i -= 4) {
- val = iwl_read_targ_mem(priv, priv->dbgfs_sram_offset + \
- priv->dbgfs_sram_len - i);
+ priv->dbgfs->sram_offset);
+ for (i = priv->dbgfs->sram_len; i > 0; i -= 4) {
+ val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \
+ priv->dbgfs->sram_len - i);
if (i < 4) {
switch (i) {
case 1:
@@ -278,11 +293,11 @@ static ssize_t iwl_dbgfs_sram_write(struct file *file,
return -EFAULT;
if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
- priv->dbgfs_sram_offset = offset;
- priv->dbgfs_sram_len = len;
+ priv->dbgfs->sram_offset = offset;
+ priv->dbgfs->sram_len = len;
} else {
- priv->dbgfs_sram_offset = 0;
- priv->dbgfs_sram_len = 0;
+ priv->dbgfs->sram_offset = 0;
+ priv->dbgfs->sram_len = 0;
}
return count;
@@ -291,7 +306,7 @@ static ssize_t iwl_dbgfs_sram_write(struct file *file,
static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
struct iwl_station_entry *station;
int max_sta = priv->hw_params.max_stations;
char *buf;
@@ -361,7 +376,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
loff_t *ppos)
{
ssize_t ret;
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
int pos = 0, ofs = 0, buf_size = 0;
const u8 *ptr;
char *buf;
@@ -405,24 +420,6 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
return ret;
}
-static ssize_t iwl_dbgfs_log_event_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- char *buf;
- int pos = 0;
- ssize_t ret = -ENOMEM;
-
- ret = pos = priv->cfg->ops->lib->dump_nic_event_log(
- priv, true, &buf, true);
- if (buf) {
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
- kfree(buf);
- }
- return ret;
-}
-
static ssize_t iwl_dbgfs_log_event_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
@@ -439,8 +436,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file,
if (sscanf(buf, "%d", &event_log_flag) != 1)
return -EFAULT;
if (event_log_flag == 1)
- priv->cfg->ops->lib->dump_nic_event_log(priv, true,
- NULL, false);
+ priv->cfg->ops->lib->dump_nic_event_log(priv, true);
return count;
}
@@ -450,7 +446,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file,
static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
struct ieee80211_channel *channels = NULL;
const struct ieee80211_supported_band *supp_band = NULL;
int pos = 0, i, bufsz = PAGE_SIZE;
@@ -523,13 +519,15 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
char buf[512];
int pos = 0;
const size_t bufsz = sizeof(buf);
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
test_bit(STATUS_HCMD_ACTIVE, &priv->status));
+ pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_SYNC_ACTIVE: %d\n",
+ test_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
test_bit(STATUS_INT_ENABLED, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
@@ -569,7 +567,7 @@ static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
int pos = 0;
int cnt = 0;
char *buf;
@@ -656,7 +654,7 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
int pos = 0, i;
char buf[256];
const size_t bufsz = sizeof(buf);
@@ -679,7 +677,7 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
int pos = 0;
char buf[256];
const size_t bufsz = sizeof(buf);
@@ -705,7 +703,7 @@ static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
struct iwl_tt_restriction *restriction;
char buf[100];
@@ -765,7 +763,7 @@ static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
char buf[100];
int pos = 0;
const size_t bufsz = sizeof(buf);
@@ -813,9 +811,7 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
priv->power_data.debug_sleep_level_override = value;
- mutex_lock(&priv->mutex);
iwl_power_update_mode(priv, true);
- mutex_unlock(&priv->mutex);
return count;
}
@@ -824,7 +820,7 @@ static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
char buf[10];
int pos, value;
const size_t bufsz = sizeof(buf);
@@ -842,7 +838,7 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
char buf[200];
int pos = 0, i;
const size_t bufsz = sizeof(buf);
@@ -863,7 +859,7 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file,
}
DEBUGFS_READ_WRITE_FILE_OPS(sram);
-DEBUGFS_READ_WRITE_FILE_OPS(log_event);
+DEBUGFS_WRITE_FILE_OPS(log_event);
DEBUGFS_READ_FILE_OPS(nvm);
DEBUGFS_READ_FILE_OPS(stations);
DEBUGFS_READ_FILE_OPS(channels);
@@ -980,7 +976,7 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
struct iwl_tx_queue *txq;
struct iwl_queue *q;
char *buf;
@@ -1026,7 +1022,7 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
struct iwl_rx_queue *rxq = &priv->rxq;
char buf[256];
int pos = 0;
@@ -1067,33 +1063,36 @@ static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf,
return p;
}
-static const char ucode_stats_header[] =
- "%-32s current acumulative delta max\n";
-static const char ucode_stats_short_format[] =
- " %-30s %10u\n";
-static const char ucode_stats_format[] =
- " %-30s %10u %10u %10u %10u\n";
static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
int pos = 0;
char *buf;
- int bufsz = sizeof(struct statistics_rx_phy) * 40 +
- sizeof(struct statistics_rx_non_phy) * 40 +
- sizeof(struct statistics_rx_ht_phy) * 40 + 400;
+ int bufsz = sizeof(struct statistics_rx_phy) * 20 +
+ sizeof(struct statistics_rx_non_phy) * 20 +
+ sizeof(struct statistics_rx_ht_phy) * 20 + 400;
ssize_t ret;
- struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
- struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
+ struct statistics_rx_phy *ofdm, *accum_ofdm;
+ struct statistics_rx_phy *cck, *accum_cck;
struct statistics_rx_non_phy *general, *accum_general;
- struct statistics_rx_non_phy *delta_general, *max_general;
- struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht;
+ struct statistics_rx_ht_phy *ht, *accum_ht;
if (!iwl_is_alive(priv))
return -EAGAIN;
+ /* make request to uCode to retrieve statistics information */
+ mutex_lock(&priv->mutex);
+ ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
+ mutex_unlock(&priv->mutex);
+
+ if (ret) {
+ IWL_ERR(priv,
+ "Error sending statistics request: %zd\n", ret);
+ return -EAGAIN;
+ }
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf) {
IWL_ERR(priv, "Can not allocate Buffer\n");
@@ -1112,401 +1111,264 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
accum_cck = &priv->accum_statistics.rx.cck;
accum_general = &priv->accum_statistics.rx.general;
accum_ht = &priv->accum_statistics.rx.ofdm_ht;
- delta_ofdm = &priv->delta_statistics.rx.ofdm;
- delta_cck = &priv->delta_statistics.rx.cck;
- delta_general = &priv->delta_statistics.rx.general;
- delta_ht = &priv->delta_statistics.rx.ofdm_ht;
- max_ofdm = &priv->max_delta.rx.ofdm;
- max_cck = &priv->max_delta.rx.cck;
- max_general = &priv->max_delta.rx.general;
- max_ht = &priv->max_delta.rx.ofdm_ht;
-
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
- "Statistics_Rx - OFDM:");
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "ina_cnt:", le32_to_cpu(ofdm->ina_cnt),
- accum_ofdm->ina_cnt,
- delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "fina_cnt:",
- le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
- delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "plcp_err:",
- le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
- delta_ofdm->plcp_err, max_ofdm->plcp_err);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "crc32_err:",
- le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
- delta_ofdm->crc32_err, max_ofdm->crc32_err);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "overrun_err:",
+ pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\t\t\tcurrent\t\t\taccumulative\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(ofdm->ina_cnt), accum_ofdm->ina_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err);
+ pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "overrun_err:\t\t%u\t\t\t%u\n",
le32_to_cpu(ofdm->overrun_err),
- accum_ofdm->overrun_err,
- delta_ofdm->overrun_err, max_ofdm->overrun_err);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "early_overrun_err:",
+ accum_ofdm->overrun_err);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "early_overrun_err:\t%u\t\t\t%u\n",
le32_to_cpu(ofdm->early_overrun_err),
- accum_ofdm->early_overrun_err,
- delta_ofdm->early_overrun_err,
- max_ofdm->early_overrun_err);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "crc32_good:",
+ accum_ofdm->early_overrun_err);
+ pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n",
le32_to_cpu(ofdm->crc32_good),
- accum_ofdm->crc32_good,
- delta_ofdm->crc32_good, max_ofdm->crc32_good);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "false_alarm_cnt:",
+ accum_ofdm->crc32_good);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "false_alarm_cnt:\t%u\t\t\t%u\n",
le32_to_cpu(ofdm->false_alarm_cnt),
- accum_ofdm->false_alarm_cnt,
- delta_ofdm->false_alarm_cnt,
- max_ofdm->false_alarm_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "fina_sync_err_cnt:",
+ accum_ofdm->false_alarm_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "fina_sync_err_cnt:\t%u\t\t\t%u\n",
le32_to_cpu(ofdm->fina_sync_err_cnt),
- accum_ofdm->fina_sync_err_cnt,
- delta_ofdm->fina_sync_err_cnt,
- max_ofdm->fina_sync_err_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "sfd_timeout:",
+ accum_ofdm->fina_sync_err_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "sfd_timeout:\t\t%u\t\t\t%u\n",
le32_to_cpu(ofdm->sfd_timeout),
- accum_ofdm->sfd_timeout,
- delta_ofdm->sfd_timeout,
- max_ofdm->sfd_timeout);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "fina_timeout:",
+ accum_ofdm->sfd_timeout);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "fina_timeout:\t\t%u\t\t\t%u\n",
le32_to_cpu(ofdm->fina_timeout),
- accum_ofdm->fina_timeout,
- delta_ofdm->fina_timeout,
- max_ofdm->fina_timeout);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "unresponded_rts:",
+ accum_ofdm->fina_timeout);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "unresponded_rts:\t%u\t\t\t%u\n",
le32_to_cpu(ofdm->unresponded_rts),
- accum_ofdm->unresponded_rts,
- delta_ofdm->unresponded_rts,
- max_ofdm->unresponded_rts);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "rxe_frame_lmt_ovrun:",
+ accum_ofdm->unresponded_rts);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "rxe_frame_lmt_ovrun:\t%u\t\t\t%u\n",
le32_to_cpu(ofdm->rxe_frame_limit_overrun),
- accum_ofdm->rxe_frame_limit_overrun,
- delta_ofdm->rxe_frame_limit_overrun,
- max_ofdm->rxe_frame_limit_overrun);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "sent_ack_cnt:",
+ accum_ofdm->rxe_frame_limit_overrun);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "sent_ack_cnt:\t\t%u\t\t\t%u\n",
le32_to_cpu(ofdm->sent_ack_cnt),
- accum_ofdm->sent_ack_cnt,
- delta_ofdm->sent_ack_cnt,
- max_ofdm->sent_ack_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "sent_cts_cnt:",
+ accum_ofdm->sent_ack_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "sent_cts_cnt:\t\t%u\t\t\t%u\n",
le32_to_cpu(ofdm->sent_cts_cnt),
- accum_ofdm->sent_cts_cnt,
- delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "sent_ba_rsp_cnt:",
+ accum_ofdm->sent_cts_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "sent_ba_rsp_cnt:\t%u\t\t\t%u\n",
le32_to_cpu(ofdm->sent_ba_rsp_cnt),
- accum_ofdm->sent_ba_rsp_cnt,
- delta_ofdm->sent_ba_rsp_cnt,
- max_ofdm->sent_ba_rsp_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "dsp_self_kill:",
+ accum_ofdm->sent_ba_rsp_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "dsp_self_kill:\t\t%u\t\t\t%u\n",
le32_to_cpu(ofdm->dsp_self_kill),
- accum_ofdm->dsp_self_kill,
- delta_ofdm->dsp_self_kill,
- max_ofdm->dsp_self_kill);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "mh_format_err:",
+ accum_ofdm->dsp_self_kill);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "mh_format_err:\t\t%u\t\t\t%u\n",
le32_to_cpu(ofdm->mh_format_err),
- accum_ofdm->mh_format_err,
- delta_ofdm->mh_format_err,
- max_ofdm->mh_format_err);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "re_acq_main_rssi_sum:",
+ accum_ofdm->mh_format_err);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "re_acq_main_rssi_sum:\t%u\t\t\t%u\n",
le32_to_cpu(ofdm->re_acq_main_rssi_sum),
- accum_ofdm->re_acq_main_rssi_sum,
- delta_ofdm->re_acq_main_rssi_sum,
- max_ofdm->re_acq_main_rssi_sum);
-
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
- "Statistics_Rx - CCK:");
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "ina_cnt:",
- le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
- delta_cck->ina_cnt, max_cck->ina_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "fina_cnt:",
- le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
- delta_cck->fina_cnt, max_cck->fina_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "plcp_err:",
- le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
- delta_cck->plcp_err, max_cck->plcp_err);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "crc32_err:",
- le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
- delta_cck->crc32_err, max_cck->crc32_err);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "overrun_err:",
+ accum_ofdm->re_acq_main_rssi_sum);
+
+ pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\t\t\tcurrent\t\t\taccumulative\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(cck->plcp_err), accum_cck->plcp_err);
+ pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(cck->crc32_err), accum_cck->crc32_err);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "overrun_err:\t\t%u\t\t\t%u\n",
le32_to_cpu(cck->overrun_err),
- accum_cck->overrun_err,
- delta_cck->overrun_err, max_cck->overrun_err);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "early_overrun_err:",
+ accum_cck->overrun_err);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "early_overrun_err:\t%u\t\t\t%u\n",
le32_to_cpu(cck->early_overrun_err),
- accum_cck->early_overrun_err,
- delta_cck->early_overrun_err,
- max_cck->early_overrun_err);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "crc32_good:",
- le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
- delta_cck->crc32_good,
- max_cck->crc32_good);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "false_alarm_cnt:",
+ accum_cck->early_overrun_err);
+ pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(cck->crc32_good), accum_cck->crc32_good);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "false_alarm_cnt:\t%u\t\t\t%u\n",
le32_to_cpu(cck->false_alarm_cnt),
- accum_cck->false_alarm_cnt,
- delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "fina_sync_err_cnt:",
+ accum_cck->false_alarm_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "fina_sync_err_cnt:\t%u\t\t\t%u\n",
le32_to_cpu(cck->fina_sync_err_cnt),
- accum_cck->fina_sync_err_cnt,
- delta_cck->fina_sync_err_cnt,
- max_cck->fina_sync_err_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "sfd_timeout:",
+ accum_cck->fina_sync_err_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "sfd_timeout:\t\t%u\t\t\t%u\n",
le32_to_cpu(cck->sfd_timeout),
- accum_cck->sfd_timeout,
- delta_cck->sfd_timeout, max_cck->sfd_timeout);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "fina_timeout:",
+ accum_cck->sfd_timeout);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "fina_timeout:\t\t%u\t\t\t%u\n",
le32_to_cpu(cck->fina_timeout),
- accum_cck->fina_timeout,
- delta_cck->fina_timeout, max_cck->fina_timeout);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "unresponded_rts:",
+ accum_cck->fina_timeout);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "unresponded_rts:\t%u\t\t\t%u\n",
le32_to_cpu(cck->unresponded_rts),
- accum_cck->unresponded_rts,
- delta_cck->unresponded_rts,
- max_cck->unresponded_rts);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "rxe_frame_lmt_ovrun:",
+ accum_cck->unresponded_rts);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "rxe_frame_lmt_ovrun:\t%u\t\t\t%u\n",
le32_to_cpu(cck->rxe_frame_limit_overrun),
- accum_cck->rxe_frame_limit_overrun,
- delta_cck->rxe_frame_limit_overrun,
- max_cck->rxe_frame_limit_overrun);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "sent_ack_cnt:",
+ accum_cck->rxe_frame_limit_overrun);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "sent_ack_cnt:\t\t%u\t\t\t%u\n",
le32_to_cpu(cck->sent_ack_cnt),
- accum_cck->sent_ack_cnt,
- delta_cck->sent_ack_cnt,
- max_cck->sent_ack_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "sent_cts_cnt:",
+ accum_cck->sent_ack_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "sent_cts_cnt:\t\t%u\t\t\t%u\n",
le32_to_cpu(cck->sent_cts_cnt),
- accum_cck->sent_cts_cnt,
- delta_cck->sent_cts_cnt,
- max_cck->sent_cts_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "sent_ba_rsp_cnt:",
+ accum_cck->sent_cts_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "sent_ba_rsp_cnt:\t%u\t\t\t%u\n",
le32_to_cpu(cck->sent_ba_rsp_cnt),
- accum_cck->sent_ba_rsp_cnt,
- delta_cck->sent_ba_rsp_cnt,
- max_cck->sent_ba_rsp_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "dsp_self_kill:",
+ accum_cck->sent_ba_rsp_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "dsp_self_kill:\t\t%u\t\t\t%u\n",
le32_to_cpu(cck->dsp_self_kill),
- accum_cck->dsp_self_kill,
- delta_cck->dsp_self_kill,
- max_cck->dsp_self_kill);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "mh_format_err:",
+ accum_cck->dsp_self_kill);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "mh_format_err:\t\t%u\t\t\t%u\n",
le32_to_cpu(cck->mh_format_err),
- accum_cck->mh_format_err,
- delta_cck->mh_format_err, max_cck->mh_format_err);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "re_acq_main_rssi_sum:",
+ accum_cck->mh_format_err);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "re_acq_main_rssi_sum:\t%u\t\t\t%u\n",
le32_to_cpu(cck->re_acq_main_rssi_sum),
- accum_cck->re_acq_main_rssi_sum,
- delta_cck->re_acq_main_rssi_sum,
- max_cck->re_acq_main_rssi_sum);
-
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
- "Statistics_Rx - GENERAL:");
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "bogus_cts:",
+ accum_cck->re_acq_main_rssi_sum);
+
+ pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\t\t\tcurrent\t\t\taccumulative\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts:\t\t%u\t\t\t%u\n",
le32_to_cpu(general->bogus_cts),
- accum_general->bogus_cts,
- delta_general->bogus_cts, max_general->bogus_cts);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "bogus_ack:",
+ accum_general->bogus_cts);
+ pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack:\t\t%u\t\t\t%u\n",
le32_to_cpu(general->bogus_ack),
- accum_general->bogus_ack,
- delta_general->bogus_ack, max_general->bogus_ack);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "non_bssid_frames:",
+ accum_general->bogus_ack);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "non_bssid_frames:\t%u\t\t\t%u\n",
le32_to_cpu(general->non_bssid_frames),
- accum_general->non_bssid_frames,
- delta_general->non_bssid_frames,
- max_general->non_bssid_frames);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "filtered_frames:",
+ accum_general->non_bssid_frames);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "filtered_frames:\t%u\t\t\t%u\n",
le32_to_cpu(general->filtered_frames),
- accum_general->filtered_frames,
- delta_general->filtered_frames,
- max_general->filtered_frames);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "non_channel_beacons:",
+ accum_general->filtered_frames);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "non_channel_beacons:\t%u\t\t\t%u\n",
le32_to_cpu(general->non_channel_beacons),
- accum_general->non_channel_beacons,
- delta_general->non_channel_beacons,
- max_general->non_channel_beacons);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "channel_beacons:",
+ accum_general->non_channel_beacons);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "channel_beacons:\t%u\t\t\t%u\n",
le32_to_cpu(general->channel_beacons),
- accum_general->channel_beacons,
- delta_general->channel_beacons,
- max_general->channel_beacons);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "num_missed_bcon:",
+ accum_general->channel_beacons);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "num_missed_bcon:\t%u\t\t\t%u\n",
le32_to_cpu(general->num_missed_bcon),
- accum_general->num_missed_bcon,
- delta_general->num_missed_bcon,
- max_general->num_missed_bcon);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "adc_rx_saturation_time:",
+ accum_general->num_missed_bcon);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "adc_rx_saturation_time:\t%u\t\t\t%u\n",
le32_to_cpu(general->adc_rx_saturation_time),
- accum_general->adc_rx_saturation_time,
- delta_general->adc_rx_saturation_time,
- max_general->adc_rx_saturation_time);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "ina_detect_search_tm:",
+ accum_general->adc_rx_saturation_time);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "ina_detect_search_tm:\t%u\t\t\t%u\n",
le32_to_cpu(general->ina_detection_search_time),
- accum_general->ina_detection_search_time,
- delta_general->ina_detection_search_time,
- max_general->ina_detection_search_time);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "beacon_silence_rssi_a:",
+ accum_general->ina_detection_search_time);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "beacon_silence_rssi_a:\t%u\t\t\t%u\n",
le32_to_cpu(general->beacon_silence_rssi_a),
- accum_general->beacon_silence_rssi_a,
- delta_general->beacon_silence_rssi_a,
- max_general->beacon_silence_rssi_a);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "beacon_silence_rssi_b:",
+ accum_general->beacon_silence_rssi_a);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "beacon_silence_rssi_b:\t%u\t\t\t%u\n",
le32_to_cpu(general->beacon_silence_rssi_b),
- accum_general->beacon_silence_rssi_b,
- delta_general->beacon_silence_rssi_b,
- max_general->beacon_silence_rssi_b);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "beacon_silence_rssi_c:",
+ accum_general->beacon_silence_rssi_b);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "beacon_silence_rssi_c:\t%u\t\t\t%u\n",
le32_to_cpu(general->beacon_silence_rssi_c),
- accum_general->beacon_silence_rssi_c,
- delta_general->beacon_silence_rssi_c,
- max_general->beacon_silence_rssi_c);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "interference_data_flag:",
+ accum_general->beacon_silence_rssi_c);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "interference_data_flag:\t%u\t\t\t%u\n",
le32_to_cpu(general->interference_data_flag),
- accum_general->interference_data_flag,
- delta_general->interference_data_flag,
- max_general->interference_data_flag);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "channel_load:",
+ accum_general->interference_data_flag);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "channel_load:\t\t%u\t\t\t%u\n",
le32_to_cpu(general->channel_load),
- accum_general->channel_load,
- delta_general->channel_load,
- max_general->channel_load);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "dsp_false_alarms:",
+ accum_general->channel_load);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "dsp_false_alarms:\t%u\t\t\t%u\n",
le32_to_cpu(general->dsp_false_alarms),
- accum_general->dsp_false_alarms,
- delta_general->dsp_false_alarms,
- max_general->dsp_false_alarms);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "beacon_rssi_a:",
+ accum_general->dsp_false_alarms);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "beacon_rssi_a:\t\t%u\t\t\t%u\n",
le32_to_cpu(general->beacon_rssi_a),
- accum_general->beacon_rssi_a,
- delta_general->beacon_rssi_a,
- max_general->beacon_rssi_a);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "beacon_rssi_b:",
+ accum_general->beacon_rssi_a);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "beacon_rssi_b:\t\t%u\t\t\t%u\n",
le32_to_cpu(general->beacon_rssi_b),
- accum_general->beacon_rssi_b,
- delta_general->beacon_rssi_b,
- max_general->beacon_rssi_b);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "beacon_rssi_c:",
+ accum_general->beacon_rssi_b);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "beacon_rssi_c:\t\t%u\t\t\t%u\n",
le32_to_cpu(general->beacon_rssi_c),
- accum_general->beacon_rssi_c,
- delta_general->beacon_rssi_c,
- max_general->beacon_rssi_c);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "beacon_energy_a:",
+ accum_general->beacon_rssi_c);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "beacon_energy_a:\t%u\t\t\t%u\n",
le32_to_cpu(general->beacon_energy_a),
- accum_general->beacon_energy_a,
- delta_general->beacon_energy_a,
- max_general->beacon_energy_a);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "beacon_energy_b:",
+ accum_general->beacon_energy_a);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "beacon_energy_b:\t%u\t\t\t%u\n",
le32_to_cpu(general->beacon_energy_b),
- accum_general->beacon_energy_b,
- delta_general->beacon_energy_b,
- max_general->beacon_energy_b);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "beacon_energy_c:",
+ accum_general->beacon_energy_b);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "beacon_energy_c:\t%u\t\t\t%u\n",
le32_to_cpu(general->beacon_energy_c),
- accum_general->beacon_energy_c,
- delta_general->beacon_energy_c,
- max_general->beacon_energy_c);
+ accum_general->beacon_energy_c);
pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n");
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
- "Statistics_Rx - OFDM_HT:");
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "plcp_err:",
- le32_to_cpu(ht->plcp_err), accum_ht->plcp_err,
- delta_ht->plcp_err, max_ht->plcp_err);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "overrun_err:",
- le32_to_cpu(ht->overrun_err), accum_ht->overrun_err,
- delta_ht->overrun_err, max_ht->overrun_err);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "early_overrun_err:",
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\t\t\tcurrent\t\t\taccumulative\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(ht->plcp_err), accum_ht->plcp_err);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "overrun_err:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(ht->overrun_err), accum_ht->overrun_err);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "early_overrun_err:\t%u\t\t\t%u\n",
le32_to_cpu(ht->early_overrun_err),
- accum_ht->early_overrun_err,
- delta_ht->early_overrun_err,
- max_ht->early_overrun_err);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "crc32_good:",
- le32_to_cpu(ht->crc32_good), accum_ht->crc32_good,
- delta_ht->crc32_good, max_ht->crc32_good);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "crc32_err:",
- le32_to_cpu(ht->crc32_err), accum_ht->crc32_err,
- delta_ht->crc32_err, max_ht->crc32_err);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "mh_format_err:",
+ accum_ht->early_overrun_err);
+ pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(ht->crc32_good), accum_ht->crc32_good);
+ pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(ht->crc32_err), accum_ht->crc32_err);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "mh_format_err:\t\t%u\t\t\t%u\n",
le32_to_cpu(ht->mh_format_err),
- accum_ht->mh_format_err,
- delta_ht->mh_format_err, max_ht->mh_format_err);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "agg_crc32_good:",
+ accum_ht->mh_format_err);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "agg_crc32_good:\t\t%u\t\t\t%u\n",
le32_to_cpu(ht->agg_crc32_good),
- accum_ht->agg_crc32_good,
- delta_ht->agg_crc32_good, max_ht->agg_crc32_good);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "agg_mpdu_cnt:",
+ accum_ht->agg_crc32_good);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "agg_mpdu_cnt:\t\t%u\t\t\t%u\n",
le32_to_cpu(ht->agg_mpdu_cnt),
- accum_ht->agg_mpdu_cnt,
- delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "agg_cnt:",
- le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt,
- delta_ht->agg_cnt, max_ht->agg_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "unsupport_mcs:",
- le32_to_cpu(ht->unsupport_mcs),
- accum_ht->unsupport_mcs,
- delta_ht->unsupport_mcs, max_ht->unsupport_mcs);
+ accum_ht->agg_mpdu_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
@@ -1517,16 +1379,26 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
int pos = 0;
char *buf;
- int bufsz = (sizeof(struct statistics_tx) * 48) + 250;
+ int bufsz = (sizeof(struct statistics_tx) * 24) + 250;
ssize_t ret;
- struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
+ struct statistics_tx *tx, *accum_tx;
if (!iwl_is_alive(priv))
return -EAGAIN;
+ /* make request to uCode to retrieve statistics information */
+ mutex_lock(&priv->mutex);
+ ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
+ mutex_unlock(&priv->mutex);
+
+ if (ret) {
+ IWL_ERR(priv,
+ "Error sending statistics request: %zd\n", ret);
+ return -EAGAIN;
+ }
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf) {
IWL_ERR(priv, "Can not allocate Buffer\n");
@@ -1539,148 +1411,106 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
*/
tx = &priv->statistics.tx;
accum_tx = &priv->accum_statistics.tx;
- delta_tx = &priv->delta_statistics.tx;
- max_tx = &priv->max_delta.tx;
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
- "Statistics_Tx:");
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "preamble:",
+ pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\t\t\tcurrent\t\t\taccumulative\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "preamble:\t\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->preamble_cnt),
- accum_tx->preamble_cnt,
- delta_tx->preamble_cnt, max_tx->preamble_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "rx_detected_cnt:",
+ accum_tx->preamble_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "rx_detected_cnt:\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->rx_detected_cnt),
- accum_tx->rx_detected_cnt,
- delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "bt_prio_defer_cnt:",
+ accum_tx->rx_detected_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "bt_prio_defer_cnt:\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->bt_prio_defer_cnt),
- accum_tx->bt_prio_defer_cnt,
- delta_tx->bt_prio_defer_cnt,
- max_tx->bt_prio_defer_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "bt_prio_kill_cnt:",
+ accum_tx->bt_prio_defer_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "bt_prio_kill_cnt:\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->bt_prio_kill_cnt),
- accum_tx->bt_prio_kill_cnt,
- delta_tx->bt_prio_kill_cnt,
- max_tx->bt_prio_kill_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "few_bytes_cnt:",
+ accum_tx->bt_prio_kill_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "few_bytes_cnt:\t\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->few_bytes_cnt),
- accum_tx->few_bytes_cnt,
- delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "cts_timeout:",
- le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
- delta_tx->cts_timeout, max_tx->cts_timeout);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "ack_timeout:",
+ accum_tx->few_bytes_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "cts_timeout:\t\t\t%u\t\t\t%u\n",
+ le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "ack_timeout:\t\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->ack_timeout),
- accum_tx->ack_timeout,
- delta_tx->ack_timeout, max_tx->ack_timeout);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "expected_ack_cnt:",
+ accum_tx->ack_timeout);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "expected_ack_cnt:\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->expected_ack_cnt),
- accum_tx->expected_ack_cnt,
- delta_tx->expected_ack_cnt,
- max_tx->expected_ack_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "actual_ack_cnt:",
+ accum_tx->expected_ack_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "actual_ack_cnt:\t\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->actual_ack_cnt),
- accum_tx->actual_ack_cnt,
- delta_tx->actual_ack_cnt,
- max_tx->actual_ack_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "dump_msdu_cnt:",
+ accum_tx->actual_ack_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "dump_msdu_cnt:\t\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->dump_msdu_cnt),
- accum_tx->dump_msdu_cnt,
- delta_tx->dump_msdu_cnt,
- max_tx->dump_msdu_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "abort_nxt_frame_mismatch:",
+ accum_tx->dump_msdu_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "abort_nxt_frame_mismatch:"
+ "\t%u\t\t\t%u\n",
le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt),
- accum_tx->burst_abort_next_frame_mismatch_cnt,
- delta_tx->burst_abort_next_frame_mismatch_cnt,
- max_tx->burst_abort_next_frame_mismatch_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "abort_missing_nxt_frame:",
+ accum_tx->burst_abort_next_frame_mismatch_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "abort_missing_nxt_frame:"
+ "\t%u\t\t\t%u\n",
le32_to_cpu(tx->burst_abort_missing_next_frame_cnt),
- accum_tx->burst_abort_missing_next_frame_cnt,
- delta_tx->burst_abort_missing_next_frame_cnt,
- max_tx->burst_abort_missing_next_frame_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "cts_timeout_collision:",
+ accum_tx->burst_abort_missing_next_frame_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "cts_timeout_collision:\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->cts_timeout_collision),
- accum_tx->cts_timeout_collision,
- delta_tx->cts_timeout_collision,
- max_tx->cts_timeout_collision);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "ack_ba_timeout_collision:",
+ accum_tx->cts_timeout_collision);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "ack_ba_timeout_collision:\t%u\t\t\t%u\n",
le32_to_cpu(tx->ack_or_ba_timeout_collision),
- accum_tx->ack_or_ba_timeout_collision,
- delta_tx->ack_or_ba_timeout_collision,
- max_tx->ack_or_ba_timeout_collision);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "agg ba_timeout:",
+ accum_tx->ack_or_ba_timeout_collision);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "agg ba_timeout:\t\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->agg.ba_timeout),
- accum_tx->agg.ba_timeout,
- delta_tx->agg.ba_timeout,
- max_tx->agg.ba_timeout);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "agg ba_resched_frames:",
+ accum_tx->agg.ba_timeout);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "agg ba_resched_frames:\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->agg.ba_reschedule_frames),
- accum_tx->agg.ba_reschedule_frames,
- delta_tx->agg.ba_reschedule_frames,
- max_tx->agg.ba_reschedule_frames);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "agg scd_query_agg_frame:",
+ accum_tx->agg.ba_reschedule_frames);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "agg scd_query_agg_frame:\t%u\t\t\t%u\n",
le32_to_cpu(tx->agg.scd_query_agg_frame_cnt),
- accum_tx->agg.scd_query_agg_frame_cnt,
- delta_tx->agg.scd_query_agg_frame_cnt,
- max_tx->agg.scd_query_agg_frame_cnt);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "agg scd_query_no_agg:",
+ accum_tx->agg.scd_query_agg_frame_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "agg scd_query_no_agg:\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->agg.scd_query_no_agg),
- accum_tx->agg.scd_query_no_agg,
- delta_tx->agg.scd_query_no_agg,
- max_tx->agg.scd_query_no_agg);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "agg scd_query_agg:",
+ accum_tx->agg.scd_query_no_agg);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "agg scd_query_agg:\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->agg.scd_query_agg),
- accum_tx->agg.scd_query_agg,
- delta_tx->agg.scd_query_agg,
- max_tx->agg.scd_query_agg);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "agg scd_query_mismatch:",
+ accum_tx->agg.scd_query_agg);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "agg scd_query_mismatch:\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->agg.scd_query_mismatch),
- accum_tx->agg.scd_query_mismatch,
- delta_tx->agg.scd_query_mismatch,
- max_tx->agg.scd_query_mismatch);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "agg frame_not_ready:",
+ accum_tx->agg.scd_query_mismatch);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "agg frame_not_ready:\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->agg.frame_not_ready),
- accum_tx->agg.frame_not_ready,
- delta_tx->agg.frame_not_ready,
- max_tx->agg.frame_not_ready);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "agg underrun:",
+ accum_tx->agg.frame_not_ready);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "agg underrun:\t\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->agg.underrun),
- accum_tx->agg.underrun,
- delta_tx->agg.underrun, max_tx->agg.underrun);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "agg bt_prio_kill:",
+ accum_tx->agg.underrun);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "agg bt_prio_kill:\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->agg.bt_prio_kill),
- accum_tx->agg.bt_prio_kill,
- delta_tx->agg.bt_prio_kill,
- max_tx->agg.bt_prio_kill);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "agg rx_ba_rsp_cnt:",
+ accum_tx->agg.bt_prio_kill);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "agg rx_ba_rsp_cnt:\t\t%u\t\t\t%u\n",
le32_to_cpu(tx->agg.rx_ba_rsp_cnt),
- accum_tx->agg.rx_ba_rsp_cnt,
- delta_tx->agg.rx_ba_rsp_cnt,
- max_tx->agg.rx_ba_rsp_cnt);
+ accum_tx->agg.rx_ba_rsp_cnt);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
@@ -1691,19 +1521,28 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
int pos = 0;
char *buf;
- int bufsz = sizeof(struct statistics_general) * 10 + 300;
+ int bufsz = sizeof(struct statistics_general) * 4 + 250;
ssize_t ret;
struct statistics_general *general, *accum_general;
- struct statistics_general *delta_general, *max_general;
- struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
- struct statistics_div *div, *accum_div, *delta_div, *max_div;
+ struct statistics_dbg *dbg, *accum_dbg;
+ struct statistics_div *div, *accum_div;
if (!iwl_is_alive(priv))
return -EAGAIN;
+ /* make request to uCode to retrieve statistics information */
+ mutex_lock(&priv->mutex);
+ ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
+ mutex_unlock(&priv->mutex);
+
+ if (ret) {
+ IWL_ERR(priv,
+ "Error sending statistics request: %zd\n", ret);
+ return -EAGAIN;
+ }
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf) {
IWL_ERR(priv, "Can not allocate Buffer\n");
@@ -1718,78 +1557,52 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
dbg = &priv->statistics.general.dbg;
div = &priv->statistics.general.div;
accum_general = &priv->accum_statistics.general;
- delta_general = &priv->delta_statistics.general;
- max_general = &priv->max_delta.general;
accum_dbg = &priv->accum_statistics.general.dbg;
- delta_dbg = &priv->delta_statistics.general.dbg;
- max_dbg = &priv->max_delta.general.dbg;
accum_div = &priv->accum_statistics.general.div;
- delta_div = &priv->delta_statistics.general.div;
- max_div = &priv->max_delta.general.div;
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
- "Statistics_General:");
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format,
- "temperature:",
+ pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\t\t\tcurrent\t\t\taccumulative\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "temperature:\t\t\t%u\n",
le32_to_cpu(general->temperature));
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format,
- "temperature_m:",
+ pos += scnprintf(buf + pos, bufsz - pos, "temperature_m:\t\t\t%u\n",
le32_to_cpu(general->temperature_m));
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "burst_check:",
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "burst_check:\t\t\t%u\t\t\t%u\n",
le32_to_cpu(dbg->burst_check),
- accum_dbg->burst_check,
- delta_dbg->burst_check, max_dbg->burst_check);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "burst_count:",
+ accum_dbg->burst_check);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "burst_count:\t\t\t%u\t\t\t%u\n",
le32_to_cpu(dbg->burst_count),
- accum_dbg->burst_count,
- delta_dbg->burst_count, max_dbg->burst_count);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "sleep_time:",
+ accum_dbg->burst_count);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "sleep_time:\t\t\t%u\t\t\t%u\n",
le32_to_cpu(general->sleep_time),
- accum_general->sleep_time,
- delta_general->sleep_time, max_general->sleep_time);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "slots_out:",
+ accum_general->sleep_time);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "slots_out:\t\t\t%u\t\t\t%u\n",
le32_to_cpu(general->slots_out),
- accum_general->slots_out,
- delta_general->slots_out, max_general->slots_out);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "slots_idle:",
+ accum_general->slots_out);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "slots_idle:\t\t\t%u\t\t\t%u\n",
le32_to_cpu(general->slots_idle),
- accum_general->slots_idle,
- delta_general->slots_idle, max_general->slots_idle);
+ accum_general->slots_idle);
pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n",
le32_to_cpu(general->ttl_timestamp));
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "tx_on_a:",
- le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
- delta_div->tx_on_a, max_div->tx_on_a);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "tx_on_b:",
- le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
- delta_div->tx_on_b, max_div->tx_on_b);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "exec_time:",
- le32_to_cpu(div->exec_time), accum_div->exec_time,
- delta_div->exec_time, max_div->exec_time);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "probe_time:",
- le32_to_cpu(div->probe_time), accum_div->probe_time,
- delta_div->probe_time, max_div->probe_time);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "rx_enable_counter:",
+ pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a:\t\t\t%u\t\t\t%u\n",
+ le32_to_cpu(div->tx_on_a), accum_div->tx_on_a);
+ pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b:\t\t\t%u\t\t\t%u\n",
+ le32_to_cpu(div->tx_on_b), accum_div->tx_on_b);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "exec_time:\t\t\t%u\t\t\t%u\n",
+ le32_to_cpu(div->exec_time), accum_div->exec_time);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "probe_time:\t\t\t%u\t\t\t%u\n",
+ le32_to_cpu(div->probe_time), accum_div->probe_time);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "rx_enable_counter:\t\t%u\t\t\t%u\n",
le32_to_cpu(general->rx_enable_counter),
- accum_general->rx_enable_counter,
- delta_general->rx_enable_counter,
- max_general->rx_enable_counter);
- pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
- "num_of_sos_states:",
- le32_to_cpu(general->num_of_sos_states),
- accum_general->num_of_sos_states,
- delta_general->num_of_sos_states,
- max_general->num_of_sos_states);
+ accum_general->rx_enable_counter);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
return ret;
@@ -1799,7 +1612,7 @@ static ssize_t iwl_dbgfs_sensitivity_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
int pos = 0;
int cnt = 0;
char *buf;
@@ -1880,7 +1693,7 @@ static ssize_t iwl_dbgfs_chain_noise_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
int pos = 0;
int cnt = 0;
char *buf;
@@ -1938,15 +1751,26 @@ static ssize_t iwl_dbgfs_tx_power_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
char buf[128];
int pos = 0;
+ ssize_t ret;
const size_t bufsz = sizeof(buf);
struct statistics_tx *tx;
if (!iwl_is_alive(priv))
pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
else {
+ /* make request to uCode to retrieve statistics information */
+ mutex_lock(&priv->mutex);
+ ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
+ mutex_unlock(&priv->mutex);
+
+ if (ret) {
+ IWL_ERR(priv, "Error sending statistics request: %zd\n",
+ ret);
+ return -EAGAIN;
+ }
tx = &priv->statistics.tx;
if (tx->tx_power.ant_a ||
tx->tx_power.ant_b ||
@@ -1978,7 +1802,7 @@ static ssize_t iwl_dbgfs_power_save_status_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct iwl_priv *priv = file->private_data;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
char buf[60];
int pos = 0;
const size_t bufsz = sizeof(buf);
@@ -2021,262 +1845,6 @@ static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file,
return count;
}
-static ssize_t iwl_dbgfs_csr_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- char buf[8];
- int buf_size;
- int csr;
-
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &csr) != 1)
- return -EFAULT;
-
- if (priv->cfg->ops->lib->dump_csr)
- priv->cfg->ops->lib->dump_csr(priv);
-
- return count;
-}
-
-static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos) {
-
- struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
- int pos = 0;
- char buf[128];
- const size_t bufsz = sizeof(buf);
- ssize_t ret;
-
- pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n",
- priv->event_log.ucode_trace ? "On" : "Off");
- pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n",
- priv->event_log.non_wraps_count);
- pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n",
- priv->event_log.wraps_once_count);
- pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n",
- priv->event_log.wraps_more_count);
-
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
- return ret;
-}
-
-static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- char buf[8];
- int buf_size;
- int trace;
-
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &trace) != 1)
- return -EFAULT;
-
- if (trace) {
- priv->event_log.ucode_trace = true;
- /* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */
- mod_timer(&priv->ucode_trace,
- jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
- } else {
- priv->event_log.ucode_trace = false;
- del_timer_sync(&priv->ucode_trace);
- }
-
- return count;
-}
-
-static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
- char *buf;
- int pos = 0;
- ssize_t ret = -EFAULT;
-
- if (priv->cfg->ops->lib->dump_fh) {
- ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true);
- if (buf) {
- ret = simple_read_from_buffer(user_buf,
- count, ppos, buf, pos);
- kfree(buf);
- }
- }
-
- return ret;
-}
-
-static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos) {
-
- struct iwl_priv *priv = file->private_data;
- int pos = 0;
- char buf[12];
- const size_t bufsz = sizeof(buf);
- ssize_t ret;
-
- pos += scnprintf(buf + pos, bufsz - pos, "%d\n",
- priv->missed_beacon_threshold);
-
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
- return ret;
-}
-
-static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- char buf[8];
- int buf_size;
- int missed;
-
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &missed) != 1)
- return -EINVAL;
-
- if (missed < IWL_MISSED_BEACON_THRESHOLD_MIN ||
- missed > IWL_MISSED_BEACON_THRESHOLD_MAX)
- priv->missed_beacon_threshold =
- IWL_MISSED_BEACON_THRESHOLD_DEF;
- else
- priv->missed_beacon_threshold = missed;
-
- return count;
-}
-
-static ssize_t iwl_dbgfs_internal_scan_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- char buf[8];
- int buf_size;
- int scan;
-
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &scan) != 1)
- return -EINVAL;
-
- iwl_internal_short_hw_scan(priv);
-
- return count;
-}
-
-static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos) {
-
- struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
- int pos = 0;
- char buf[12];
- const size_t bufsz = sizeof(buf);
- ssize_t ret;
-
- pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
- priv->cfg->plcp_delta_threshold);
-
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
- return ret;
-}
-
-static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos) {
-
- struct iwl_priv *priv = file->private_data;
- char buf[8];
- int buf_size;
- int plcp;
-
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &plcp) != 1)
- return -EINVAL;
- if ((plcp <= IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
- (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
- priv->cfg->plcp_delta_threshold =
- IWL_MAX_PLCP_ERR_THRESHOLD_DEF;
- else
- priv->cfg->plcp_delta_threshold = plcp;
- return count;
-}
-
-static ssize_t iwl_dbgfs_force_reset_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos) {
-
- struct iwl_priv *priv = file->private_data;
- int i, pos = 0;
- char buf[300];
- const size_t bufsz = sizeof(buf);
- struct iwl_force_reset *force_reset;
-
- for (i = 0; i < IWL_MAX_FORCE_RESET; i++) {
- force_reset = &priv->force_reset[i];
- pos += scnprintf(buf + pos, bufsz - pos,
- "Force reset method %d\n", i);
- pos += scnprintf(buf + pos, bufsz - pos,
- "\tnumber of reset request: %d\n",
- force_reset->reset_request_count);
- pos += scnprintf(buf + pos, bufsz - pos,
- "\tnumber of reset request success: %d\n",
- force_reset->reset_success_count);
- pos += scnprintf(buf + pos, bufsz - pos,
- "\tnumber of reset request reject: %d\n",
- force_reset->reset_reject_count);
- pos += scnprintf(buf + pos, bufsz - pos,
- "\treset duration: %lu\n",
- force_reset->reset_duration);
- }
- return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_dbgfs_force_reset_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos) {
-
- struct iwl_priv *priv = file->private_data;
- char buf[8];
- int buf_size;
- int reset, ret;
-
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &reset) != 1)
- return -EINVAL;
- switch (reset) {
- case IWL_RF_RESET:
- case IWL_FW_RESET:
- ret = iwl_force_reset(priv, reset);
- break;
- default:
- return -EINVAL;
- }
- return ret ? ret : count;
-}
-
DEBUGFS_READ_FILE_OPS(rx_statistics);
DEBUGFS_READ_FILE_OPS(tx_statistics);
DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
@@ -2291,13 +1859,6 @@ DEBUGFS_READ_FILE_OPS(tx_power);
DEBUGFS_READ_FILE_OPS(power_save_status);
DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
-DEBUGFS_WRITE_FILE_OPS(csr);
-DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
-DEBUGFS_READ_FILE_OPS(fh_reg);
-DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
-DEBUGFS_WRITE_FILE_OPS(internal_scan);
-DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
-DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
/*
* Create the debugfs files and directories
@@ -2305,74 +1866,69 @@ DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
*/
int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
{
+ struct iwl_debugfs *dbgfs;
struct dentry *phyd = priv->hw->wiphy->debugfsdir;
- struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
-
- dir_drv = debugfs_create_dir(name, phyd);
- if (!dir_drv)
- return -ENOMEM;
-
- priv->debugfs_dir = dir_drv;
+ int ret = 0;
- dir_data = debugfs_create_dir("data", dir_drv);
- if (!dir_data)
- goto err;
- dir_rf = debugfs_create_dir("rf", dir_drv);
- if (!dir_rf)
+ dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL);
+ if (!dbgfs) {
+ ret = -ENOMEM;
goto err;
- dir_debug = debugfs_create_dir("debug", dir_drv);
- if (!dir_debug)
+ }
+
+ priv->dbgfs = dbgfs;
+ dbgfs->name = name;
+ dbgfs->dir_drv = debugfs_create_dir(name, phyd);
+ if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)) {
+ ret = -ENOENT;
goto err;
+ }
- DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
- DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
- DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR);
- DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
- DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
- DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
- DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
- DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
- DEBUGFS_ADD_FILE(led, dir_data, S_IRUSR);
- DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR);
- DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);
- DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR);
- DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
- DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR);
- DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR);
- DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR);
- DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR);
- DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR);
- DEBUGFS_ADD_FILE(tx_power, dir_debug, S_IRUSR);
- DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
- DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR);
- DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);
- DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR);
- DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
- DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
- DEBUGFS_ADD_FILE(internal_scan, dir_debug, S_IWUSR);
- DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
- DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
+ DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
+ DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
+ DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv);
+ DEBUGFS_ADD_FILE(nvm, data, S_IRUSR);
+ DEBUGFS_ADD_FILE(sram, data, S_IWUSR | S_IRUSR);
+ DEBUGFS_ADD_FILE(log_event, data, S_IWUSR);
+ DEBUGFS_ADD_FILE(stations, data, S_IRUSR);
+ DEBUGFS_ADD_FILE(channels, data, S_IRUSR);
+ DEBUGFS_ADD_FILE(status, data, S_IRUSR);
+ DEBUGFS_ADD_FILE(interrupt, data, S_IWUSR | S_IRUSR);
+ DEBUGFS_ADD_FILE(qos, data, S_IRUSR);
+ DEBUGFS_ADD_FILE(led, data, S_IRUSR);
+ DEBUGFS_ADD_FILE(sleep_level_override, data, S_IWUSR | S_IRUSR);
+ DEBUGFS_ADD_FILE(current_sleep_command, data, S_IRUSR);
+ DEBUGFS_ADD_FILE(thermal_throttling, data, S_IRUSR);
+ DEBUGFS_ADD_FILE(disable_ht40, data, S_IWUSR | S_IRUSR);
+ DEBUGFS_ADD_FILE(rx_statistics, debug, S_IRUSR);
+ DEBUGFS_ADD_FILE(tx_statistics, debug, S_IRUSR);
+ DEBUGFS_ADD_FILE(traffic_log, debug, S_IWUSR | S_IRUSR);
+ DEBUGFS_ADD_FILE(rx_queue, debug, S_IRUSR);
+ DEBUGFS_ADD_FILE(tx_queue, debug, S_IRUSR);
+ DEBUGFS_ADD_FILE(tx_power, debug, S_IRUSR);
+ DEBUGFS_ADD_FILE(power_save_status, debug, S_IRUSR);
+ DEBUGFS_ADD_FILE(clear_ucode_statistics, debug, S_IWUSR);
+ DEBUGFS_ADD_FILE(clear_traffic_statistics, debug, S_IWUSR);
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
- DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
- DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
- DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
- DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
- DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
- DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
+ DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR);
+ DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR);
+ DEBUGFS_ADD_FILE(ucode_general_stats, debug, S_IRUSR);
+ DEBUGFS_ADD_FILE(sensitivity, debug, S_IRUSR);
+ DEBUGFS_ADD_FILE(chain_noise, debug, S_IRUSR);
}
- DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal);
- DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
+ DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
+ DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
&priv->disable_chain_noise_cal);
if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
- DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf,
+ DEBUGFS_ADD_BOOL(disable_tx_power, rf,
&priv->disable_tx_power_cal);
return 0;
err:
- IWL_ERR(priv, "Can't create the debugfs directory\n");
+ IWL_ERR(priv, "Can't open the debugfs directory\n");
iwl_dbgfs_unregister(priv);
- return -ENOMEM;
+ return ret;
}
EXPORT_SYMBOL(iwl_dbgfs_register);
@@ -2382,11 +1938,56 @@ EXPORT_SYMBOL(iwl_dbgfs_register);
*/
void iwl_dbgfs_unregister(struct iwl_priv *priv)
{
- if (!priv->debugfs_dir)
+ if (!priv->dbgfs)
return;
- debugfs_remove_recursive(priv->debugfs_dir);
- priv->debugfs_dir = NULL;
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sleep_level_override);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_current_sleep_command);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40);
+ DEBUGFS_REMOVE(priv->dbgfs->dir_data);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_statistics);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_statistics);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_power_save_status);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
+ file_clear_ucode_statistics);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
+ file_clear_traffic_statistics);
+ if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
+ file_ucode_rx_stats);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
+ file_ucode_tx_stats);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
+ file_ucode_general_stats);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
+ file_sensitivity);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
+ file_chain_noise);
+ }
+ DEBUGFS_REMOVE(priv->dbgfs->dir_debug);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
+ if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
+ ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power);
+ DEBUGFS_REMOVE(priv->dbgfs->dir_rf);
+ DEBUGFS_REMOVE(priv->dbgfs->dir_drv);
+ kfree(priv->dbgfs);
+ priv->dbgfs = NULL;
}
EXPORT_SYMBOL(iwl_dbgfs_unregister);
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h b/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h
index 7914d65a5a55..3822cf53e368 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -512,7 +512,6 @@ struct iwl_ht_config {
bool is_ht;
bool is_40mhz;
bool single_chain_sufficient;
- enum ieee80211_smps_mode smps; /* current smps mode */
/* BSS related data */
u8 extension_chan_offset;
u8 ht_protection;
@@ -985,74 +984,6 @@ struct iwl_switch_rxon {
__le16 channel;
};
-/*
- * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds
- * to perform continuous uCode event logging operation if enabled
- */
-#define UCODE_TRACE_PERIOD (100)
-
-/*
- * iwl_event_log: current uCode event log position
- *
- * @ucode_trace: enable/disable ucode continuous trace timer
- * @num_wraps: how many times the event buffer wraps
- * @next_entry: the entry just before the next one that uCode would fill
- * @non_wraps_count: counter for no wrap detected when dump ucode events
- * @wraps_once_count: counter for wrap once detected when dump ucode events
- * @wraps_more_count: counter for wrap more than once detected
- * when dump ucode events
- */
-struct iwl_event_log {
- bool ucode_trace;
- u32 num_wraps;
- u32 next_entry;
- int non_wraps_count;
- int wraps_once_count;
- int wraps_more_count;
-};
-
-/*
- * host interrupt timeout value
- * used with setting interrupt coalescing timer
- * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
- *
- * default interrupt coalescing timer is 64 x 32 = 2048 usecs
- * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs
- */
-#define IWL_HOST_INT_TIMEOUT_MAX (0xFF)
-#define IWL_HOST_INT_TIMEOUT_DEF (0x40)
-#define IWL_HOST_INT_TIMEOUT_MIN (0x0)
-#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF)
-#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
-#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
-
-/*
- * This is the threshold value of plcp error rate per 100mSecs. It is
- * used to set and check for the validity of plcp_delta.
- */
-#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (0)
-#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50)
-#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100)
-#define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF (200)
-#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255)
-
-#define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3)
-#define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
-
-enum iwl_reset {
- IWL_RF_RESET = 0,
- IWL_FW_RESET,
- IWL_MAX_FORCE_RESET,
-};
-
-struct iwl_force_reset {
- int reset_request_count;
- int reset_success_count;
- int reset_reject_count;
- unsigned long reset_duration;
- unsigned long last_force_reset_jiffies;
-};
-
struct iwl_priv {
/* ieee device used by generic ieee processing code */
@@ -1073,22 +1004,13 @@ struct iwl_priv {
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
+#if defined(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) || defined(CONFIG_IWL3945_SPECTRUM_MEASUREMENT)
/* spectrum measurement report caching */
struct iwl_spectrum_notification measure_report;
u8 measurement_status;
-
+#endif
/* ucode beacon time */
u32 ucode_beacon_time;
- int missed_beacon_threshold;
-
- /* storing the jiffies when the plcp error rate is received */
- unsigned long plcp_jiffies;
-
- /* reporting the number of tids has AGG on. 0 means no AGGREGATION */
- u8 agg_tids_count;
-
- /* force reset */
- struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
/* we allocate array of iwl4965_channel_info for NIC's valid channels.
* Access via channel # using indirect index array */
@@ -1107,6 +1029,7 @@ struct iwl_priv {
struct iwl_calib_result calib_results[IWL_CALIB_MAX];
/* Scan related variables */
+ unsigned long last_scan_jiffies;
unsigned long next_scan_jiffies;
unsigned long scan_start;
unsigned long scan_pass_start;
@@ -1114,7 +1037,6 @@ struct iwl_priv {
void *scan;
int scan_bands;
struct cfg80211_scan_request *scan_request;
- bool is_internal_short_scan;
u8 scan_tx_ant[IEEE80211_NUM_BANDS];
u8 mgmt_tx_ant;
@@ -1123,7 +1045,6 @@ struct iwl_priv {
spinlock_t hcmd_lock; /* protect hcmd */
spinlock_t reg_lock; /* protect hw register access */
struct mutex mutex;
- struct mutex sync_cmd_mutex; /* enable serialization of sync commands */
/* basic pci-network driver stuff */
struct pci_dev *pci_dev;
@@ -1214,8 +1135,6 @@ struct iwl_priv {
struct iwl_notif_statistics statistics;
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_notif_statistics accum_statistics;
- struct iwl_notif_statistics delta_statistics;
- struct iwl_notif_statistics max_delta;
#endif
/* context information */
@@ -1288,10 +1207,15 @@ struct iwl_priv {
struct workqueue_struct *workqueue;
+ struct work_struct up;
struct work_struct restart;
+ struct work_struct calibrated_work;
struct work_struct scan_completed;
struct work_struct rx_replenish;
struct work_struct abort_scan;
+ struct work_struct update_link_led;
+ struct work_struct auth_work;
+ struct work_struct report_work;
struct work_struct request_scan;
struct work_struct beacon_update;
struct work_struct tt_work;
@@ -1327,8 +1251,7 @@ struct iwl_priv {
u16 rx_traffic_idx;
u8 *tx_traffic;
u8 *rx_traffic;
- struct dentry *debugfs_dir;
- u32 dbgfs_sram_offset, dbgfs_sram_len;
+ struct iwl_debugfs *dbgfs;
#endif /* CONFIG_IWLWIFI_DEBUGFS */
#endif /* CONFIG_IWLWIFI_DEBUG */
@@ -1338,7 +1261,6 @@ struct iwl_priv {
u32 disable_tx_power_cal;
struct work_struct run_time_calib_work;
struct timer_list statistics_periodic;
- struct timer_list ucode_trace;
bool hw_ready;
/*For 3945*/
#define IWL_DEFAULT_TX_POWER 0x0F
@@ -1346,8 +1268,6 @@ struct iwl_priv {
struct iwl3945_notif_statistics statistics_39;
u32 sta_supp_rates;
-
- struct iwl_event_log event_log;
}; /*iwl_priv */
static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.c
index 36580d8d8b8d..83cc4e500a96 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.c
@@ -37,6 +37,4 @@ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_wrap_event);
#endif
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h
index ff4d012ce260..d9c7363b1bbb 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h
@@ -90,50 +90,6 @@ TRACE_EVENT(iwlwifi_dev_iowrite32,
TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val)
);
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM iwlwifi_ucode
-
-TRACE_EVENT(iwlwifi_dev_ucode_cont_event,
- TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
- TP_ARGS(priv, time, data, ev),
- TP_STRUCT__entry(
- PRIV_ENTRY
-
- __field(u32, time)
- __field(u32, data)
- __field(u32, ev)
- ),
- TP_fast_assign(
- PRIV_ASSIGN;
- __entry->time = time;
- __entry->data = data;
- __entry->ev = ev;
- ),
- TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
- __entry->priv, __entry->time, __entry->data, __entry->ev)
-);
-
-TRACE_EVENT(iwlwifi_dev_ucode_wrap_event,
- TP_PROTO(struct iwl_priv *priv, u32 wraps, u32 n_entry, u32 p_entry),
- TP_ARGS(priv, wraps, n_entry, p_entry),
- TP_STRUCT__entry(
- PRIV_ENTRY
-
- __field(u32, wraps)
- __field(u32, n_entry)
- __field(u32, p_entry)
- ),
- TP_fast_assign(
- PRIV_ASSIGN;
- __entry->wraps = wraps;
- __entry->n_entry = n_entry;
- __entry->p_entry = p_entry;
- ),
- TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X",
- __entry->priv, __entry->wraps, __entry->n_entry,
- __entry->p_entry)
-);
-
#undef TRACE_SYSTEM
#define TRACE_SYSTEM iwlwifi
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index fd37152abae3..4a30969689ff 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 4e1ba824dc50..0cd9c02ee044 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h b/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h
index 113c3669b9ce..65fa8a69fd5a 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -379,25 +379,6 @@
#define FH_TSSR_TX_STATUS_REG (FH_TSSR_LOWER_BOUND + 0x010)
-/**
- * Bit fields for TSSR(Tx Shared Status & Control) error status register:
- * 31: Indicates an address error when accessed to internal memory
- * uCode/driver must write "1" in order to clear this flag
- * 30: Indicates that Host did not send the expected number of dwords to FH
- * uCode/driver must write "1" in order to clear this flag
- * 16-9:Each status bit is for one channel. Indicates that an (Error) ActDMA
- * command was received from the scheduler while the TRB was already full
- * with previous command
- * uCode/driver must write "1" in order to clear this flag
- * 7-0: Each status bit indicates a channel's TxCredit error. When an error
- * bit is set, it indicates that the FH has received a full indication
- * from the RTC TxFIFO and the current value of the TxCredit counter was
- * not equal to zero. This mean that the credit mechanism was not
- * synchronized to the TxFIFO status
- * uCode/driver must write "1" in order to clear this flag
- */
-#define FH_TSSR_TX_ERROR_REG (FH_TSSR_LOWER_BOUND + 0x018)
-
#define FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) ((1 << (_chnl)) << 24)
#define FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl) ((1 << (_chnl)) << 16)
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/trunk/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 73681c4fefe7..30e9ea6d54ec 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -2,7 +2,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -58,6 +58,7 @@ const char *get_cmd_string(u8 cmd)
IWL_CMD(COEX_PRIORITY_TABLE_CMD);
IWL_CMD(COEX_MEDIUM_NOTIFICATION);
IWL_CMD(COEX_EVENT_CMD);
+ IWL_CMD(RADAR_NOTIFICATION);
IWL_CMD(REPLY_QUIET_CMD);
IWL_CMD(REPLY_CHANNEL_SWITCH);
IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
@@ -164,13 +165,15 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
/* A synchronous command can not have a callback set. */
BUG_ON(cmd->callback);
- IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
+ if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) {
+ IWL_ERR(priv,
+ "Error sending %s: Already sending a host command\n",
get_cmd_string(cmd->id));
- mutex_lock(&priv->sync_cmd_mutex);
+ ret = -EBUSY;
+ goto out;
+ }
set_bit(STATUS_HCMD_ACTIVE, &priv->status);
- IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s \n",
- get_cmd_string(cmd->id));
cmd_idx = iwl_enqueue_hcmd(priv, cmd);
if (cmd_idx < 0) {
@@ -191,8 +194,6 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
- IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n",
- get_cmd_string(cmd->id));
ret = -ETIMEDOUT;
goto cancel;
}
@@ -237,7 +238,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
cmd->reply_page = 0;
}
out:
- mutex_unlock(&priv->sync_cmd_mutex);
+ clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
return ret;
}
EXPORT_SYMBOL(iwl_send_cmd_sync);
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-helpers.h b/trunk/drivers/net/wireless/iwlwifi/iwl-helpers.h
index 51a67fb2e185..bd0b12efb5c7 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@@ -80,8 +80,8 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev,
struct fw_desc *desc)
{
if (desc->v_addr)
- dma_free_coherent(&pci_dev->dev, desc->len,
- desc->v_addr, desc->p_addr);
+ pci_free_consistent(pci_dev, desc->len,
+ desc->v_addr, desc->p_addr);
desc->v_addr = NULL;
desc->len = 0;
}
@@ -89,8 +89,7 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev,
static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev,
struct fw_desc *desc)
{
- desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len,
- &desc->p_addr, GFP_KERNEL);
+ desc->v_addr = pci_alloc_consistent(pci_dev, desc->len, &desc->p_addr);
return (desc->v_addr != NULL) ? 0 : -ENOMEM;
}
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-io.h b/trunk/drivers/net/wireless/iwlwifi/iwl-io.h
index c719baf2585a..e552d4c4bdbe 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* Portions of this file are derived from the ipw3945 project.
*
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-led.c b/trunk/drivers/net/wireless/iwlwifi/iwl-led.c
index a6f9c918aabc..46c7a95b88f0 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-led.h b/trunk/drivers/net/wireless/iwlwifi/iwl-led.h
index 49a70baa3fb6..f47f053f02ea 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-led.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-led.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-power.c b/trunk/drivers/net/wireless/iwlwifi/iwl-power.c
index 1a1a9f081cc7..8ccc0bb1d9ed 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@@ -303,12 +303,13 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
sizeof(struct iwl_powertable_cmd), cmd);
}
-/* priv->mutex must be held */
+
int iwl_power_update_mode(struct iwl_priv *priv, bool force)
{
int ret = 0;
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
- bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS;
+ bool enabled = (priv->iw_mode == NL80211_IFTYPE_STATION) &&
+ (priv->hw->conf.flags & IEEE80211_CONF_PS);
bool update_chains;
struct iwl_powertable_cmd cmd;
int dtimper;
@@ -318,7 +319,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
if (priv->vif)
- dtimper = priv->hw->conf.ps_dtim_period;
+ dtimper = priv->vif->bss_conf.dtim_period;
else
dtimper = 1;
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-power.h b/trunk/drivers/net/wireless/iwlwifi/iwl-power.h
index 5db91c10dcc8..310c32e8f698 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h b/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h
index d2d2a9174900..6d95832db06d 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c
index 0d09f571e185..2dbce85404aa 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@@ -123,11 +123,12 @@ EXPORT_SYMBOL(iwl_rx_queue_space);
/**
* iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
*/
-void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
+int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
{
unsigned long flags;
u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg;
u32 reg;
+ int ret = 0;
spin_lock_irqsave(&q->lock, flags);
@@ -160,6 +161,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q
exit_unlock:
spin_unlock_irqrestore(&q->lock, flags);
+ return ret;
}
EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr);
/**
@@ -182,13 +184,14 @@ static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv,
* also updates the memory address in the firmware to reference the new
* target buffer.
*/
-void iwl_rx_queue_restock(struct iwl_priv *priv)
+int iwl_rx_queue_restock(struct iwl_priv *priv)
{
struct iwl_rx_queue *rxq = &priv->rxq;
struct list_head *element;
struct iwl_rx_mem_buffer *rxb;
unsigned long flags;
int write;
+ int ret = 0;
spin_lock_irqsave(&rxq->lock, flags);
write = rxq->write & ~0x7;
@@ -217,8 +220,10 @@ void iwl_rx_queue_restock(struct iwl_priv *priv)
spin_lock_irqsave(&rxq->lock, flags);
rxq->need_update = 1;
spin_unlock_irqrestore(&rxq->lock, flags);
- iwl_rx_queue_update_write_ptr(priv, rxq);
+ ret = iwl_rx_queue_update_write_ptr(priv, rxq);
}
+
+ return ret;
}
EXPORT_SYMBOL(iwl_rx_queue_restock);
@@ -345,10 +350,10 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
}
}
- dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
- rxq->dma_addr);
- dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
- rxq->rb_stts, rxq->rb_stts_dma);
+ pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+ rxq->dma_addr);
+ pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status),
+ rxq->rb_stts, rxq->rb_stts_dma);
rxq->bd = NULL;
rxq->rb_stts = NULL;
}
@@ -357,7 +362,7 @@ EXPORT_SYMBOL(iwl_rx_queue_free);
int iwl_rx_queue_alloc(struct iwl_priv *priv)
{
struct iwl_rx_queue *rxq = &priv->rxq;
- struct device *dev = &priv->pci_dev->dev;
+ struct pci_dev *dev = priv->pci_dev;
int i;
spin_lock_init(&rxq->lock);
@@ -365,13 +370,12 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv)
INIT_LIST_HEAD(&rxq->rx_used);
/* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
- rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr,
- GFP_KERNEL);
+ rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr);
if (!rxq->bd)
goto err_bd;
- rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status),
- &rxq->rb_stts_dma, GFP_KERNEL);
+ rxq->rb_stts = pci_alloc_consistent(dev, sizeof(struct iwl_rb_status),
+ &rxq->rb_stts_dma);
if (!rxq->rb_stts)
goto err_rb;
@@ -388,8 +392,8 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv)
return 0;
err_rb:
- dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
- rxq->dma_addr);
+ pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+ rxq->dma_addr);
err_bd:
return -ENOMEM;
}
@@ -469,8 +473,8 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
(rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
(rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
- /* Set interrupt coalescing timer to default (2048 usecs) */
- iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
+ /* Set interrupt coalescing timer to 64 x 32 = 2048 usecs */
+ iwl_write8(priv, CSR_INT_COALESCING, 0x40);
return 0;
}
@@ -495,10 +499,9 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
struct iwl_missed_beacon_notif *missed_beacon;
missed_beacon = &pkt->u.missed_beacon;
- if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
- priv->missed_beacon_threshold) {
+ if (le32_to_cpu(missed_beacon->consequtive_missed_beacons) > 5) {
IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
- le32_to_cpu(missed_beacon->consecutive_missed_beacons),
+ le32_to_cpu(missed_beacon->consequtive_missed_beacons),
le32_to_cpu(missed_beacon->total_missed_becons),
le32_to_cpu(missed_beacon->num_recvd_beacons),
le32_to_cpu(missed_beacon->num_expected_beacons));
@@ -508,24 +511,6 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
}
EXPORT_SYMBOL(iwl_rx_missed_beacon_notif);
-void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
-{
- struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
-
- if (!report->state) {
- IWL_DEBUG_11H(priv,
- "Spectrum Measure Notification: Start\n");
- return;
- }
-
- memcpy(&priv->measure_report, report, sizeof(*report));
- priv->measurement_status |= MEASUREMENT_READY;
-}
-EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif);
-
-
/* Calculate noise level, based on measurements during network silence just
* before arriving beacon. This measurement can be done only if we know
@@ -579,24 +564,15 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv,
int i;
__le32 *prev_stats;
u32 *accum_stats;
- u32 *delta, *max_delta;
prev_stats = (__le32 *)&priv->statistics;
accum_stats = (u32 *)&priv->accum_statistics;
- delta = (u32 *)&priv->delta_statistics;
- max_delta = (u32 *)&priv->max_delta;
for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics);
- i += sizeof(__le32), stats++, prev_stats++, delta++,
- max_delta++, accum_stats++) {
- if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
- *delta = (le32_to_cpu(*stats) -
+ i += sizeof(__le32), stats++, prev_stats++, accum_stats++)
+ if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats))
+ *accum_stats += (le32_to_cpu(*stats) -
le32_to_cpu(*prev_stats));
- *accum_stats += *delta;
- if (*delta > *max_delta)
- *max_delta = *delta;
- }
- }
/* reset accumulative statistics for "no-counter" type statistics */
priv->accum_statistics.general.temperature =
@@ -616,23 +592,11 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv,
#define REG_RECALIB_PERIOD (60)
-/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
-#define ACK_CNT_RATIO (50)
-#define BA_TIMEOUT_CNT (5)
-#define BA_TIMEOUT_MAX (16)
-
-#define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n"
void iwl_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
int change;
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- int combined_plcp_delta;
- unsigned int plcp_msec;
- unsigned long plcp_received_jiffies;
- int actual_ack_cnt_delta;
- int expected_ack_cnt_delta;
- int ba_timeout_delta;
IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
(int)sizeof(priv->statistics),
@@ -647,94 +611,6 @@ void iwl_rx_statistics(struct iwl_priv *priv,
#ifdef CONFIG_IWLWIFI_DEBUG
iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
#endif
- actual_ack_cnt_delta = le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) -
- le32_to_cpu(priv->statistics.tx.actual_ack_cnt);
- expected_ack_cnt_delta = le32_to_cpu(
- pkt->u.stats.tx.expected_ack_cnt) -
- le32_to_cpu(priv->statistics.tx.expected_ack_cnt);
- ba_timeout_delta = le32_to_cpu(
- pkt->u.stats.tx.agg.ba_timeout) -
- le32_to_cpu(priv->statistics.tx.agg.ba_timeout);
- if ((priv->agg_tids_count > 0) &&
- (expected_ack_cnt_delta > 0) &&
- (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) <
- ACK_CNT_RATIO) &&
- (ba_timeout_delta > BA_TIMEOUT_CNT)) {
- IWL_DEBUG_RADIO(priv,
- "actual_ack_cnt delta = %d, expected_ack_cnt = %d\n",
- actual_ack_cnt_delta, expected_ack_cnt_delta);
-
-#ifdef CONFIG_IWLWIFI_DEBUG
- IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n",
- priv->delta_statistics.tx.rx_detected_cnt);
- IWL_DEBUG_RADIO(priv,
- "ack_or_ba_timeout_collision delta = %d\n",
- priv->delta_statistics.tx.ack_or_ba_timeout_collision);
-#endif
- IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n",
- ba_timeout_delta);
- if ((actual_ack_cnt_delta == 0) &&
- (ba_timeout_delta >=
- BA_TIMEOUT_MAX)) {
- IWL_DEBUG_RADIO(priv,
- "call iwl_force_reset(IWL_FW_RESET)\n");
- iwl_force_reset(priv, IWL_FW_RESET);
- } else {
- IWL_DEBUG_RADIO(priv,
- "call iwl_force_reset(IWL_RF_RESET)\n");
- iwl_force_reset(priv, IWL_RF_RESET);
- }
- }
- /*
- * check for plcp_err and trigger radio reset if it exceeds
- * the plcp error threshold plcp_delta.
- */
- plcp_received_jiffies = jiffies;
- plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
- (long) priv->plcp_jiffies);
- priv->plcp_jiffies = plcp_received_jiffies;
- /*
- * check to make sure plcp_msec is not 0 to prevent division
- * by zero.
- */
- if (plcp_msec) {
- combined_plcp_delta =
- (le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) -
- le32_to_cpu(priv->statistics.rx.ofdm.plcp_err)) +
- (le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) -
- le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err));
-
- if ((combined_plcp_delta > 0) &&
- ((combined_plcp_delta * 100) / plcp_msec) >
- priv->cfg->plcp_delta_threshold) {
- /*
- * if plcp_err exceed the threshold, the following
- * data is printed in csv format:
- * Text: plcp_err exceeded %d,
- * Received ofdm.plcp_err,
- * Current ofdm.plcp_err,
- * Received ofdm_ht.plcp_err,
- * Current ofdm_ht.plcp_err,
- * combined_plcp_delta,
- * plcp_msec
- */
- IWL_DEBUG_RADIO(priv, PLCP_MSG,
- priv->cfg->plcp_delta_threshold,
- le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err),
- le32_to_cpu(priv->statistics.rx.ofdm.plcp_err),
- le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err),
- le32_to_cpu(
- priv->statistics.rx.ofdm_ht.plcp_err),
- combined_plcp_delta, plcp_msec);
-
- /*
- * Reset the RF radio due to the high plcp
- * error rate
- */
- iwl_force_reset(priv, IWL_RF_RESET);
- }
- }
-
memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
set_bit(STATUS_STATISTICS, &priv->status);
@@ -762,13 +638,11 @@ void iwl_reply_statistics(struct iwl_priv *priv,
struct iwl_rx_packet *pkt = rxb_addr(rxb);
if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
+ memset(&priv->statistics, 0,
+ sizeof(struct iwl_notif_statistics));
#ifdef CONFIG_IWLWIFI_DEBUG
memset(&priv->accum_statistics, 0,
sizeof(struct iwl_notif_statistics));
- memset(&priv->delta_statistics, 0,
- sizeof(struct iwl_notif_statistics));
- memset(&priv->max_delta, 0,
- sizeof(struct iwl_notif_statistics));
#endif
IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
}
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c b/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c
index dd9ff2ed645a..fa1c89ba6459 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -2,7 +2,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -192,17 +192,19 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
IWL_DEBUG_SCAN(priv, "Scan ch.res: "
"%d [802.11%s] "
"(TSF: 0x%08X:%08X) - %d "
- "elapsed=%lu usec\n",
+ "elapsed=%lu usec (%dms since last)\n",
notif->channel,
notif->band ? "bg" : "a",
le32_to_cpu(notif->tsf_high),
le32_to_cpu(notif->tsf_low),
le32_to_cpu(notif->statistics[0]),
- le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf);
+ le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf,
+ jiffies_to_msecs(elapsed_jiffies
+ (priv->last_scan_jiffies, jiffies)));
#endif
- if (!priv->is_internal_short_scan)
- priv->next_scan_jiffies = 0;
+ priv->last_scan_jiffies = jiffies;
+ priv->next_scan_jiffies = 0;
}
/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
@@ -248,9 +250,8 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
goto reschedule;
}
- if (!priv->is_internal_short_scan)
- priv->next_scan_jiffies = 0;
-
+ priv->last_scan_jiffies = jiffies;
+ priv->next_scan_jiffies = 0;
IWL_DEBUG_INFO(priv, "Setting scan to off\n");
clear_bit(STATUS_SCANNING, &priv->status);
@@ -313,72 +314,6 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
}
EXPORT_SYMBOL(iwl_get_passive_dwell_time);
-static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
- enum ieee80211_band band,
- struct iwl_scan_channel *scan_ch)
-{
- const struct ieee80211_supported_band *sband;
- const struct iwl_channel_info *ch_info;
- u16 passive_dwell = 0;
- u16 active_dwell = 0;
- int i, added = 0;
- u16 channel = 0;
-
- sband = iwl_get_hw_mode(priv, band);
- if (!sband) {
- IWL_ERR(priv, "invalid band\n");
- return added;
- }
-
- active_dwell = iwl_get_active_dwell_time(priv, band, 0);
- passive_dwell = iwl_get_passive_dwell_time(priv, band);
-
- if (passive_dwell <= active_dwell)
- passive_dwell = active_dwell + 1;
-
- /* only scan single channel, good enough to reset the RF */
- /* pick the first valid not in-use channel */
- if (band == IEEE80211_BAND_5GHZ) {
- for (i = 14; i < priv->channel_count; i++) {
- if (priv->channel_info[i].channel !=
- le16_to_cpu(priv->staging_rxon.channel)) {
- channel = priv->channel_info[i].channel;
- ch_info = iwl_get_channel_info(priv,
- band, channel);
- if (is_channel_valid(ch_info))
- break;
- }
- }
- } else {
- for (i = 0; i < 14; i++) {
- if (priv->channel_info[i].channel !=
- le16_to_cpu(priv->staging_rxon.channel)) {
- channel =
- priv->channel_info[i].channel;
- ch_info = iwl_get_channel_info(priv,
- band, channel);
- if (is_channel_valid(ch_info))
- break;
- }
- }
- }
- if (channel) {
- scan_ch->channel = cpu_to_le16(channel);
- scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
- scan_ch->active_dwell = cpu_to_le16(active_dwell);
- scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
- /* Set txpower levels to defaults */
- scan_ch->dsp_atten = 110;
- if (band == IEEE80211_BAND_5GHZ)
- scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
- else
- scan_ch->tx_gain = ((1 << 5) | (5 << 3));
- added++;
- } else
- IWL_ERR(priv, "no valid channel found\n");
- return added;
-}
-
static int iwl_get_channels_for_scan(struct iwl_priv *priv,
enum ieee80211_band band,
u8 is_active, u8 n_probes,
@@ -469,9 +404,23 @@ EXPORT_SYMBOL(iwl_init_scan_params);
static int iwl_scan_initiate(struct iwl_priv *priv)
{
+ if (!iwl_is_ready_rf(priv)) {
+ IWL_DEBUG_SCAN(priv, "Aborting scan due to not ready.\n");
+ return -EIO;
+ }
+
+ if (test_bit(STATUS_SCANNING, &priv->status)) {
+ IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
+ return -EAGAIN;
+ }
+
+ if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+ IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
+ return -EAGAIN;
+ }
+
IWL_DEBUG_INFO(priv, "Starting scan...\n");
set_bit(STATUS_SCANNING, &priv->status);
- priv->is_internal_short_scan = false;
priv->scan_start = jiffies;
priv->scan_pass_start = priv->scan_start;
@@ -500,18 +449,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
goto out_unlock;
}
- if (test_bit(STATUS_SCANNING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
- ret = -EAGAIN;
- goto out_unlock;
- }
-
- if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
- ret = -EAGAIN;
- goto out_unlock;
- }
-
/* We don't schedule scan within next_scan_jiffies period.
* Avoid scanning during possible EAPOL exchange, return
* success immediately.
@@ -524,6 +461,15 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
goto out_unlock;
}
+ /* if we just finished scan ask for delay */
+ if (iwl_is_associated(priv) && priv->last_scan_jiffies &&
+ time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, jiffies)) {
+ IWL_DEBUG_SCAN(priv, "scan rejected: within previous scan period\n");
+ queue_work(priv->workqueue, &priv->scan_completed);
+ ret = 0;
+ goto out_unlock;
+ }
+
priv->scan_bands = 0;
for (i = 0; i < req->n_channels; i++)
priv->scan_bands |= BIT(req->channels[i]->band);
@@ -542,46 +488,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL(iwl_mac_hw_scan);
-/*
- * internal short scan, this function should only been called while associated.
- * It will reset and tune the radio to prevent possible RF related problem
- */
-int iwl_internal_short_hw_scan(struct iwl_priv *priv)
-{
- int ret = 0;
-
- if (!iwl_is_ready_rf(priv)) {
- ret = -EIO;
- IWL_DEBUG_SCAN(priv, "not ready or exit pending\n");
- goto out;
- }
- if (test_bit(STATUS_SCANNING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
- ret = -EAGAIN;
- goto out;
- }
- if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
- ret = -EAGAIN;
- goto out;
- }
-
- priv->scan_bands = 0;
- if (priv->band == IEEE80211_BAND_5GHZ)
- priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ);
- else
- priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ);
-
- IWL_DEBUG_SCAN(priv, "Start internal short scan...\n");
- set_bit(STATUS_SCANNING, &priv->status);
- priv->is_internal_short_scan = true;
- queue_work(priv->workqueue, &priv->request_scan);
-
-out:
- return ret;
-}
-EXPORT_SYMBOL(iwl_internal_short_hw_scan);
-
#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
void iwl_bg_scan_check(struct work_struct *data)
@@ -638,26 +544,14 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
if (left < 0)
return 0;
*pos++ = WLAN_EID_SSID;
- if (!priv->is_internal_short_scan &&
- priv->scan_request->n_ssids) {
- struct cfg80211_ssid *ssid =
- priv->scan_request->ssids;
-
- /* Broadcast if ssid_len is 0 */
- *pos++ = ssid->ssid_len;
- memcpy(pos, ssid->ssid, ssid->ssid_len);
- pos += ssid->ssid_len;
- len += 2 + ssid->ssid_len;
- } else {
- *pos++ = 0;
- len += 2;
- }
+ *pos++ = 0;
+
+ len += 2;
if (WARN_ON(left < ie_len))
return len;
- if (ies)
- memcpy(pos, ies, ie_len);
+ memcpy(pos, ies, ie_len);
len += ie_len;
left -= ie_len;
@@ -760,6 +654,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
unsigned long flags;
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
+
spin_lock_irqsave(&priv->lock, flags);
interval = priv->beacon_int;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -777,29 +672,21 @@ static void iwl_bg_request_scan(struct work_struct *data)
scan_suspend_time, interval);
}
- if (priv->is_internal_short_scan) {
- IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
- } else if (priv->scan_request->n_ssids) {
+ if (priv->scan_request->n_ssids) {
+ int i, p = 0;
IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
- /*
- * The first SSID to scan is stuffed into the probe request
- * template and the remaining ones are handled through the
- * direct_scan array.
- */
- if (priv->scan_request->n_ssids > 1) {
- int i, p = 0;
- for (i = 1; i < priv->scan_request->n_ssids; i++) {
- if (!priv->scan_request->ssids[i].ssid_len)
- continue;
- scan->direct_scan[p].id = WLAN_EID_SSID;
- scan->direct_scan[p].len =
- priv->scan_request->ssids[i].ssid_len;
- memcpy(scan->direct_scan[p].ssid,
- priv->scan_request->ssids[i].ssid,
- priv->scan_request->ssids[i].ssid_len);
- n_probes++;
- p++;
- }
+ for (i = 0; i < priv->scan_request->n_ssids; i++) {
+ /* always does wildcard anyway */
+ if (!priv->scan_request->ssids[i].ssid_len)
+ continue;
+ scan->direct_scan[p].id = WLAN_EID_SSID;
+ scan->direct_scan[p].len =
+ priv->scan_request->ssids[i].ssid_len;
+ memcpy(scan->direct_scan[p].ssid,
+ priv->scan_request->ssids[i].ssid,
+ priv->scan_request->ssids[i].ssid_len);
+ n_probes++;
+ p++;
}
is_active = true;
} else
@@ -866,38 +753,24 @@ static void iwl_bg_request_scan(struct work_struct *data)
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
scan->rx_chain = cpu_to_le16(rx_chain);
- if (!priv->is_internal_short_scan) {
- cmd_len = iwl_fill_probe_req(priv,
- (struct ieee80211_mgmt *)scan->data,
- priv->scan_request->ie,
- priv->scan_request->ie_len,
- IWL_MAX_SCAN_SIZE - sizeof(*scan));
- } else {
- cmd_len = iwl_fill_probe_req(priv,
- (struct ieee80211_mgmt *)scan->data,
- NULL, 0,
- IWL_MAX_SCAN_SIZE - sizeof(*scan));
+ cmd_len = iwl_fill_probe_req(priv,
+ (struct ieee80211_mgmt *)scan->data,
+ priv->scan_request->ie,
+ priv->scan_request->ie_len,
+ IWL_MAX_SCAN_SIZE - sizeof(*scan));
- }
scan->tx_cmd.len = cpu_to_le16(cmd_len);
+
if (iwl_is_monitor_mode(priv))
scan->filter_flags = RXON_FILTER_PROMISC_MSK;
scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
RXON_FILTER_BCON_AWARE_MSK);
- if (priv->is_internal_short_scan) {
- scan->channel_count =
- iwl_get_single_channel_for_scan(priv, band,
- (void *)&scan->data[le16_to_cpu(
- scan->tx_cmd.len)]);
- } else {
- scan->channel_count =
- iwl_get_channels_for_scan(priv, band,
- is_active, n_probes,
- (void *)&scan->data[le16_to_cpu(
- scan->tx_cmd.len)]);
- }
+ scan->channel_count =
+ iwl_get_channels_for_scan(priv, band, is_active, n_probes,
+ (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
+
if (scan->channel_count == 0) {
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
goto done;
@@ -958,12 +831,7 @@ void iwl_bg_scan_completed(struct work_struct *work)
cancel_delayed_work(&priv->scan_check);
- if (!priv->is_internal_short_scan)
- ieee80211_scan_completed(priv->hw, false);
- else {
- priv->is_internal_short_scan = false;
- IWL_DEBUG_SCAN(priv, "internal short scan completed\n");
- }
+ ieee80211_scan_completed(priv->hw, false);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-spectrum.c b/trunk/drivers/net/wireless/iwlwifi/iwl-spectrum.c
new file mode 100644
index 000000000000..1ea5cd345fe8
--- /dev/null
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-spectrum.c
@@ -0,0 +1,198 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * Intel Linux Wireless
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-spectrum.h"
+
+#define BEACON_TIME_MASK_LOW 0x00FFFFFF
+#define BEACON_TIME_MASK_HIGH 0xFF000000
+#define TIME_UNIT 1024
+
+/*
+ * extended beacon time format
+ * time in usec will be changed into a 32-bit value in 8:24 format
+ * the high 1 byte is the beacon counts
+ * the lower 3 bytes is the time in usec within one beacon interval
+ */
+
+/* TOOD: was used in sysfs debug interface need to add to mac */
+#if 0
+static u32 iwl_usecs_to_beacons(u32 usec, u32 beacon_interval)
+{
+ u32 quot;
+ u32 rem;
+ u32 interval = beacon_interval * 1024;
+
+ if (!interval || !usec)
+ return 0;
+
+ quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24);
+ rem = (usec % interval) & BEACON_TIME_MASK_LOW;
+
+ return (quot << 24) + rem;
+}
+
+/* base is usually what we get from ucode with each received frame,
+ * the same as HW timer counter counting down
+ */
+
+static __le32 iwl_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
+{
+ u32 base_low = base & BEACON_TIME_MASK_LOW;
+ u32 addon_low = addon & BEACON_TIME_MASK_LOW;
+ u32 interval = beacon_interval * TIME_UNIT;
+ u32 res = (base & BEACON_TIME_MASK_HIGH) +
+ (addon & BEACON_TIME_MASK_HIGH);
+
+ if (base_low > addon_low)
+ res += base_low - addon_low;
+ else if (base_low < addon_low) {
+ res += interval + base_low - addon_low;
+ res += (1 << 24);
+ } else
+ res += (1 << 24);
+
+ return cpu_to_le32(res);
+}
+static int iwl_get_measurement(struct iwl_priv *priv,
+ struct ieee80211_measurement_params *params,
+ u8 type)
+{
+ struct iwl4965_spectrum_cmd spectrum;
+ struct iwl_rx_packet *res;
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_SPECTRUM_MEASUREMENT_CMD,
+ .data = (void *)&spectrum,
+ .meta.flags = CMD_WANT_SKB,
+ };
+ u32 add_time = le64_to_cpu(params->start_time);
+ int rc;
+ int spectrum_resp_status;
+ int duration = le16_to_cpu(params->duration);
+
+ if (iwl_is_associated(priv))
+ add_time =
+ iwl_usecs_to_beacons(
+ le64_to_cpu(params->start_time) - priv->last_tsf,
+ le16_to_cpu(priv->rxon_timing.beacon_interval));
+
+ memset(&spectrum, 0, sizeof(spectrum));
+
+ spectrum.channel_count = cpu_to_le16(1);
+ spectrum.flags =
+ RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK;
+ spectrum.filter_flags = MEASUREMENT_FILTER_FLAG;
+ cmd.len = sizeof(spectrum);
+ spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
+
+ if (iwl_is_associated(priv))
+ spectrum.start_time =
+ iwl_add_beacon_time(priv->last_beacon_time,
+ add_time,
+ le16_to_cpu(priv->rxon_timing.beacon_interval));
+ else
+ spectrum.start_time = 0;
+
+ spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
+ spectrum.channels[0].channel = params->channel;
+ spectrum.channels[0].type = type;
+ if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)
+ spectrum.flags |= RXON_FLG_BAND_24G_MSK |
+ RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
+
+ rc = iwl_send_cmd_sync(priv, &cmd);
+ if (rc)
+ return rc;
+
+ res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
+ IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
+ rc = -EIO;
+ }
+
+ spectrum_resp_status = le16_to_cpu(res->u.spectrum.status);
+ switch (spectrum_resp_status) {
+ case 0: /* Command will be handled */
+ if (res->u.spectrum.id != 0xff) {
+ IWL_DEBUG_INFO(priv,
+ "Replaced existing measurement: %d\n",
+ res->u.spectrum.id);
+ priv->measurement_status &= ~MEASUREMENT_READY;
+ }
+ priv->measurement_status |= MEASUREMENT_ACTIVE;
+ rc = 0;
+ break;
+
+ case 1: /* Command will not be handled */
+ rc = -EAGAIN;
+ break;
+ }
+
+ dev_kfree_skb_any(cmd.meta.u.skb);
+
+ return rc;
+}
+#endif
+
+static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
+
+ if (!report->state) {
+ IWL_DEBUG_11H(priv,
+ "Spectrum Measure Notification: Start\n");
+ return;
+ }
+
+ memcpy(&priv->measure_report, report, sizeof(*report));
+ priv->measurement_status |= MEASUREMENT_READY;
+}
+
+void iwl_setup_spectrum_handlers(struct iwl_priv *priv)
+{
+ priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
+ iwl_rx_spectrum_measure_notif;
+}
+EXPORT_SYMBOL(iwl_setup_spectrum_handlers);
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-spectrum.h b/trunk/drivers/net/wireless/iwlwifi/iwl-spectrum.h
index af6babee2891..a77c1e619062 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-spectrum.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-spectrum.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* Portions of this file are derived from the ieee80211 subsystem header files.
*
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c
index 4a6686fa6b36..90fbdb25399e 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@@ -80,103 +80,46 @@ int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
}
EXPORT_SYMBOL(iwl_get_ra_sta_id);
-/* priv->sta_lock must be held */
static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE))
- IWL_ERR(priv, "ACTIVATE a non DRIVER active station id %u addr %pM\n",
- sta_id, priv->stations[sta_id].sta.sta.addr);
+ IWL_ERR(priv, "ACTIVATE a non DRIVER active station %d\n",
+ sta_id);
- if (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) {
- IWL_DEBUG_ASSOC(priv,
- "STA id %u addr %pM already present in uCode (according to driver)\n",
- sta_id, priv->stations[sta_id].sta.sta.addr);
- } else {
- priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE;
- IWL_DEBUG_ASSOC(priv, "Added STA id %u addr %pM to uCode\n",
- sta_id, priv->stations[sta_id].sta.sta.addr);
- }
+ priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE;
+ IWL_DEBUG_ASSOC(priv, "Added STA to Ucode: %pM\n",
+ priv->stations[sta_id].sta.sta.addr);
+
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
}
-static void iwl_process_add_sta_resp(struct iwl_priv *priv,
- struct iwl_addsta_cmd *addsta,
- struct iwl_rx_packet *pkt,
- bool sync)
+static void iwl_add_sta_callback(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct iwl_rx_packet *pkt)
{
+ struct iwl_addsta_cmd *addsta =
+ (struct iwl_addsta_cmd *)cmd->cmd.payload;
u8 sta_id = addsta->sta.sta_id;
- unsigned long flags;
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
- pkt->hdr.flags);
+ pkt->hdr.flags);
return;
}
- IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
- sta_id);
-
- spin_lock_irqsave(&priv->sta_lock, flags);
-
switch (pkt->u.add_sta.status) {
case ADD_STA_SUCCESS_MSK:
- IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
iwl_sta_ucode_activate(priv, sta_id);
- break;
- case ADD_STA_NO_ROOM_IN_TABLE:
- IWL_ERR(priv, "Adding station %d failed, no room in table.\n",
- sta_id);
- break;
- case ADD_STA_NO_BLOCK_ACK_RESOURCE:
- IWL_ERR(priv, "Adding station %d failed, no block ack resource.\n",
- sta_id);
- break;
- case ADD_STA_MODIFY_NON_EXIST_STA:
- IWL_ERR(priv, "Attempting to modify non-existing station %d \n",
- sta_id);
- break;
+ /* fall through */
default:
- IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n",
- pkt->u.add_sta.status);
+ IWL_DEBUG_HC(priv, "Received REPLY_ADD_STA:(0x%08X)\n",
+ pkt->u.add_sta.status);
break;
}
-
- IWL_DEBUG_INFO(priv, "%s station id %u addr %pM\n",
- priv->stations[sta_id].sta.mode ==
- STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
- sta_id, priv->stations[sta_id].sta.sta.addr);
-
- /*
- * XXX: The MAC address in the command buffer is often changed from
- * the original sent to the device. That is, the MAC address
- * written to the command buffer often is not the same MAC adress
- * read from the command buffer when the command returns. This
- * issue has not yet been resolved and this debugging is left to
- * observe the problem.
- */
- IWL_DEBUG_INFO(priv, "%s station according to cmd buffer %pM\n",
- priv->stations[sta_id].sta.mode ==
- STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
- addsta->sta.addr);
-
- /*
- * Determine if we wanted to modify or add a station,
- * if adding a station succeeded we have some more initialization
- * to do when using station notification. TODO
- */
-
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-}
-
-static void iwl_add_sta_callback(struct iwl_priv *priv,
- struct iwl_device_cmd *cmd,
- struct iwl_rx_packet *pkt)
-{
- struct iwl_addsta_cmd *addsta =
- (struct iwl_addsta_cmd *)cmd->cmd.payload;
-
- iwl_process_add_sta_resp(priv, addsta, pkt, false);
-
}
int iwl_send_add_sta(struct iwl_priv *priv,
@@ -202,9 +145,24 @@ int iwl_send_add_sta(struct iwl_priv *priv,
if (ret || (flags & CMD_ASYNC))
return ret;
+ pkt = (struct iwl_rx_packet *)cmd.reply_page;
+ if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
+ IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
+ pkt->hdr.flags);
+ ret = -EIO;
+ }
+
if (ret == 0) {
- pkt = (struct iwl_rx_packet *)cmd.reply_page;
- iwl_process_add_sta_resp(priv, sta, pkt, true);
+ switch (pkt->u.add_sta.status) {
+ case ADD_STA_SUCCESS_MSK:
+ iwl_sta_ucode_activate(priv, sta->sta.sta_id);
+ IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
+ break;
+ default:
+ ret = -EIO;
+ IWL_WARN(priv, "REPLY_ADD_STA failed\n");
+ break;
+ }
}
iwl_free_pages(priv, cmd.reply_page);
@@ -1045,19 +1003,24 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap)
struct ieee80211_sta_ht_cap *cur_ht_config = NULL;
u8 sta_id;
+ /* Add station to device's station table */
+
/*
- * Set HT capabilities. It is ok to set this struct even if not using
- * HT config: the priv->current_ht_config.is_ht flag will just be false
+ * XXX: This check is definitely not correct, if we're an AP
+ * it'll always be false which is not what we want, but
+ * it doesn't look like iwlagn is prepared to be an HT
+ * AP anyway.
*/
- rcu_read_lock();
- sta = ieee80211_find_sta(priv->vif, addr);
- if (sta) {
- memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config));
- cur_ht_config = &ht_config;
+ if (priv->current_ht_config.is_ht) {
+ rcu_read_lock();
+ sta = ieee80211_find_sta(priv->vif, addr);
+ if (sta) {
+ memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config));
+ cur_ht_config = &ht_config;
+ }
+ rcu_read_unlock();
}
- rcu_read_unlock();
- /* Add station to device's station table */
sta_id = iwl_add_station(priv, addr, is_ap, CMD_SYNC, cur_ht_config);
/* Set up default rate scaling table in device's station table */
@@ -1122,7 +1085,6 @@ static void iwl_sta_init_bcast_lq(struct iwl_priv *priv)
*/
void iwl_add_bcast_station(struct iwl_priv *priv)
{
- IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n");
iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL);
/* Set up default rate scaling table in device's station table */
@@ -1130,16 +1092,6 @@ void iwl_add_bcast_station(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_add_bcast_station);
-/**
- * iwl3945_add_bcast_station - add broadcast station into station table.
- */
-void iwl3945_add_bcast_station(struct iwl_priv *priv)
-{
- IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n");
- iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL);
-}
-EXPORT_SYMBOL(iwl3945_add_bcast_station);
-
/**
* iwl_get_sta_id - Find station's index within station table
*
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h
index 2dc35fe28f56..8d052de2d405 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@@ -53,7 +53,6 @@ void iwl_update_tkip_key(struct iwl_priv *priv,
int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap);
void iwl_add_bcast_station(struct iwl_priv *priv);
-void iwl3945_add_bcast_station(struct iwl_priv *priv);
int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap);
void iwl_clear_stations_table(struct iwl_priv *priv);
int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c
index 10701b8eef23..066491fc75f2 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@@ -60,8 +60,7 @@ static const u16 default_tid_to_tx_fifo[] = {
static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv,
struct iwl_dma_ptr *ptr, size_t size)
{
- ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma,
- GFP_KERNEL);
+ ptr->addr = pci_alloc_consistent(priv->pci_dev, size, &ptr->dma);
if (!ptr->addr)
return -ENOMEM;
ptr->size = size;
@@ -74,20 +73,21 @@ static inline void iwl_free_dma_ptr(struct iwl_priv *priv,
if (unlikely(!ptr->addr))
return;
- dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma);
+ pci_free_consistent(priv->pci_dev, ptr->size, ptr->addr, ptr->dma);
memset(ptr, 0, sizeof(*ptr));
}
/**
* iwl_txq_update_write_ptr - Send new write index to hardware
*/
-void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
{
u32 reg = 0;
+ int ret = 0;
int txq_id = txq->q.id;
if (txq->need_update == 0)
- return;
+ return ret;
/* if we're trying to save power */
if (test_bit(STATUS_POWER_PMI, &priv->status)) {
@@ -101,7 +101,7 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
txq_id, reg);
iwl_set_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- return;
+ return ret;
}
iwl_write_direct32(priv, HBUS_TARG_WRPTR,
@@ -114,6 +114,8 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
txq->q.write_ptr | (txq_id << 8));
txq->need_update = 0;
+
+ return ret;
}
EXPORT_SYMBOL(iwl_txq_update_write_ptr);
@@ -144,7 +146,7 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
{
struct iwl_tx_queue *txq = &priv->txq[txq_id];
struct iwl_queue *q = &txq->q;
- struct device *dev = &priv->pci_dev->dev;
+ struct pci_dev *dev = priv->pci_dev;
int i;
if (q->n_bd == 0)
@@ -161,8 +163,8 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
/* De-alloc circular buffer of TFDs */
if (txq->q.n_bd)
- dma_free_coherent(dev, priv->hw_params.tfd_size *
- txq->q.n_bd, txq->tfds, txq->q.dma_addr);
+ pci_free_consistent(dev, priv->hw_params.tfd_size *
+ txq->q.n_bd, txq->tfds, txq->q.dma_addr);
/* De-alloc array of per-TFD driver data */
kfree(txq->txb);
@@ -191,7 +193,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
{
struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
struct iwl_queue *q = &txq->q;
- struct device *dev = &priv->pci_dev->dev;
+ struct pci_dev *dev = priv->pci_dev;
int i;
if (q->n_bd == 0)
@@ -203,8 +205,8 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
/* De-alloc circular buffer of TFDs */
if (txq->q.n_bd)
- dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd,
- txq->tfds, txq->q.dma_addr);
+ pci_free_consistent(dev, priv->hw_params.tfd_size *
+ txq->q.n_bd, txq->tfds, txq->q.dma_addr);
/* deallocate arrays */
kfree(txq->cmd);
@@ -295,7 +297,7 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
static int iwl_tx_queue_alloc(struct iwl_priv *priv,
struct iwl_tx_queue *txq, u32 id)
{
- struct device *dev = &priv->pci_dev->dev;
+ struct pci_dev *dev = priv->pci_dev;
size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;
/* Driver private data, only for Tx (not command) queues,
@@ -314,8 +316,8 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv,
/* Circular buffer of transmit frame descriptors (TFDs),
* shared with device */
- txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr,
- GFP_KERNEL);
+ txq->tfds = pci_alloc_consistent(dev, tfd_sz, &txq->q.dma_addr);
+
if (!txq->tfds) {
IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz);
goto error;
@@ -364,7 +366,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
for (i = 0; i < actual_slots; i++) {
/* only happens for cmd queue */
if (i == slots_num)
- len += IWL_MAX_SCAN_SIZE;
+ len = IWL_MAX_CMD_SIZE;
txq->cmd[i] = kmalloc(len, GFP_KERNEL);
if (!txq->cmd[i])
@@ -743,6 +745,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
u8 tid = 0;
u8 *qc = NULL;
unsigned long flags;
+ int ret;
spin_lock_irqsave(&priv->lock, flags);
if (iwl_is_rfkill(priv)) {
@@ -817,10 +820,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
hdr->seq_ctrl |= cpu_to_le16(seq_number);
seq_number += 0x10;
/* aggregation is on for this */
- if (info->flags & IEEE80211_TX_CTL_AMPDU &&
- priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) {
+ if (info->flags & IEEE80211_TX_CTL_AMPDU)
txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
- }
}
txq = &priv->txq[txq_id];
@@ -962,7 +963,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* Tell device the write index *just past* this latest filled TFD */
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
- iwl_txq_update_write_ptr(priv, txq);
+ ret = iwl_txq_update_write_ptr(priv, txq);
spin_unlock_irqrestore(&priv->lock, flags);
/*
@@ -976,6 +977,9 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
if (sta_priv && sta_priv->client)
atomic_inc(&sta_priv->pending_frames);
+ if (ret)
+ return ret;
+
if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) {
if (wait_write_ptr) {
spin_lock_irqsave(&priv->lock, flags);
@@ -1014,7 +1018,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
struct iwl_cmd_meta *out_meta;
dma_addr_t phys_addr;
unsigned long flags;
- int len;
+ int len, ret;
u32 idx;
u16 fix_size;
@@ -1023,9 +1027,12 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
/* If any of the command structures end up being larger than
* the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then
- * we will need to increase the size of the TFD entries */
+ * we will need to increase the size of the TFD entries
+ * Also, check to see if command buffer should not exceed the size
+ * of device_cmd and max_cmd_size. */
BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
!(cmd->flags & CMD_SIZE_HUGE));
+ BUG_ON(fix_size > IWL_MAX_CMD_SIZE);
if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) {
IWL_WARN(priv, "Not sending command - %s KILL\n",
@@ -1069,8 +1076,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
if (cmd->flags & CMD_SIZE_HUGE)
out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
len = sizeof(struct iwl_device_cmd);
- len += (idx == TFD_CMD_SLOTS) ? IWL_MAX_SCAN_SIZE : 0;
-
+ if (idx == TFD_CMD_SLOTS)
+ len = IWL_MAX_CMD_SIZE;
#ifdef CONFIG_IWLWIFI_DEBUG
switch (out_cmd->hdr.cmd) {
@@ -1111,10 +1118,10 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
/* Increment and update queue's write index */
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
- iwl_txq_update_write_ptr(priv, txq);
+ ret = iwl_txq_update_write_ptr(priv, txq);
spin_unlock_irqrestore(&priv->hcmd_lock, flags);
- return idx;
+ return ret ? ret : idx;
}
static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
@@ -1256,8 +1263,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
if (!(meta->flags & CMD_ASYNC)) {
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
- IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n",
- get_cmd_string(cmd->hdr.cmd));
wake_up_interruptible(&priv->wait_command_queue);
}
}
@@ -1344,7 +1349,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
{
int tx_fifo_id, txq_id, sta_id, ssn = -1;
struct iwl_tid_data *tid_data;
- int write_ptr, read_ptr;
+ int ret, write_ptr, read_ptr;
unsigned long flags;
if (!ra) {
@@ -1396,17 +1401,13 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
spin_lock_irqsave(&priv->lock, flags);
- /*
- * the only reason this call can fail is queue number out of range,
- * which can happen if uCode is reloaded and all the station
- * information are lost. if it is outside the range, there is no need
- * to deactivate the uCode queue, just return "success" to allow
- * mac80211 to clean up it own data.
- */
- priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn,
+ ret = priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn,
tx_fifo_id);
spin_unlock_irqrestore(&priv->lock, flags);
+ if (ret)
+ return ret;
+
ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid);
return 0;
diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c b/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 54daa38ecba3..f8e4e4b18d02 100644
--- a/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@@ -53,10 +53,9 @@
#include "iwl-commands.h"
#include "iwl-sta.h"
#include "iwl-3945.h"
-#include "iwl-core.h"
#include "iwl-helpers.h"
+#include "iwl-core.h"
#include "iwl-dev.h"
-#include "iwl-spectrum.h"
/*
* module name, copyright, version, etc.
@@ -71,13 +70,14 @@
#define VD
#endif
-/*
- * add "s" to indicate spectrum measurement included.
- * we add it here to be consistent with previous releases in which
- * this was configurable.
- */
-#define DRV_VERSION IWLWIFI_VERSION VD "s"
-#define DRV_COPYRIGHT "Copyright(c) 2003-2010 Intel Corporation"
+#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
+#define VS "s"
+#else
+#define VS
+#endif
+
+#define DRV_VERSION IWLWIFI_VERSION VD VS
+#define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation"
#define DRV_AUTHOR ""
MODULE_DESCRIPTION(DRV_DESCRIPTION);
@@ -352,10 +352,10 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
static void iwl3945_unset_hw_params(struct iwl_priv *priv)
{
if (priv->shared_virt)
- dma_free_coherent(&priv->pci_dev->dev,
- sizeof(struct iwl3945_shared),
- priv->shared_virt,
- priv->shared_phys);
+ pci_free_consistent(priv->pci_dev,
+ sizeof(struct iwl3945_shared),
+ priv->shared_virt,
+ priv->shared_phys);
}
static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
@@ -478,6 +478,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
u8 wait_write_ptr = 0;
u8 *qc = NULL;
unsigned long flags;
+ int rc;
spin_lock_irqsave(&priv->lock, flags);
if (iwl_is_rfkill(priv)) {
@@ -662,9 +663,12 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* Tell device the write index *just past* this latest filled TFD */
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
- iwl_txq_update_write_ptr(priv, txq);
+ rc = iwl_txq_update_write_ptr(priv, txq);
spin_unlock_irqrestore(&priv->lock, flags);
+ if (rc)
+ return rc;
+
if ((iwl_queue_space(q) < q->high_mark)
&& priv->mac80211_registered) {
if (wait_write_ptr) {
@@ -685,6 +689,10 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
return -1;
}
+#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
+
+#include "iwl-spectrum.h"
+
#define BEACON_TIME_MASK_LOW 0x00FFFFFF
#define BEACON_TIME_MASK_HIGH 0xFF000000
#define TIME_UNIT 1024
@@ -811,6 +819,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
return rc;
}
+#endif
static void iwl3945_rx_reply_alive(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
@@ -953,8 +962,6 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)
priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta;
priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
- priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
- iwl_rx_spectrum_measure_notif;
priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
iwl_rx_pm_debug_statistics_notif;
@@ -968,6 +975,7 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)
priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics;
priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;
+ iwl_setup_spectrum_handlers(priv);
iwl_setup_rx_scan_handlers(priv);
priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
@@ -1059,13 +1067,13 @@ static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv,
* also updates the memory address in the firmware to reference the new
* target buffer.
*/
-static void iwl3945_rx_queue_restock(struct iwl_priv *priv)
+static int iwl3945_rx_queue_restock(struct iwl_priv *priv)
{
struct iwl_rx_queue *rxq = &priv->rxq;
struct list_head *element;
struct iwl_rx_mem_buffer *rxb;
unsigned long flags;
- int write;
+ int write, rc;
spin_lock_irqsave(&rxq->lock, flags);
write = rxq->write & ~0x7;
@@ -1095,8 +1103,12 @@ static void iwl3945_rx_queue_restock(struct iwl_priv *priv)
spin_lock_irqsave(&rxq->lock, flags);
rxq->need_update = 1;
spin_unlock_irqrestore(&rxq->lock, flags);
- iwl_rx_queue_update_write_ptr(priv, rxq);
+ rc = iwl_rx_queue_update_write_ptr(priv, rxq);
+ if (rc)
+ return rc;
}
+
+ return 0;
}
/**
@@ -1241,10 +1253,10 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx
}
}
- dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
- rxq->dma_addr);
- dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
- rxq->rb_stts, rxq->rb_stts_dma);
+ pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+ rxq->dma_addr);
+ pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status),
+ rxq->rb_stts, rxq->rb_stts_dma);
rxq->bd = NULL;
rxq->rb_stts = NULL;
}
@@ -1506,9 +1518,8 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
* iwl3945_print_event_log - Dump error event log to syslog
*
*/
-static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
- u32 num_events, u32 mode,
- int pos, char **buf, size_t bufsz)
+static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
+ u32 num_events, u32 mode)
{
u32 i;
u32 base; /* SRAM byte address of event log header */
@@ -1518,7 +1529,7 @@ static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
unsigned long reg_flags;
if (num_events == 0)
- return pos;
+ return;
base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
@@ -1544,43 +1555,26 @@ static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
if (mode == 0) {
/* data, ev */
- if (bufsz) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- "0x%08x:%04u\n",
- time, ev);
- } else {
- IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
- trace_iwlwifi_dev_ucode_event(priv, 0,
- time, ev);
- }
+ IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
+ trace_iwlwifi_dev_ucode_event(priv, 0, time, ev);
} else {
data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- if (bufsz) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- "%010u:0x%08x:%04u\n",
- time, data, ev);
- } else {
- IWL_ERR(priv, "%010u\t0x%08x\t%04u\n",
- time, data, ev);
- trace_iwlwifi_dev_ucode_event(priv, time,
- data, ev);
- }
+ IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev);
+ trace_iwlwifi_dev_ucode_event(priv, time, data, ev);
}
}
/* Allow device to power down */
iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
- return pos;
}
/**
* iwl3945_print_last_event_logs - Dump the newest # of event log to syslog
*/
-static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
+static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
u32 num_wraps, u32 next_entry,
- u32 size, u32 mode,
- int pos, char **buf, size_t bufsz)
+ u32 size, u32 mode)
{
/*
* display the newest DEFAULT_LOG_ENTRIES entries
@@ -1588,28 +1582,21 @@ static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
*/
if (num_wraps) {
if (next_entry < size) {
- pos = iwl3945_print_event_log(priv,
- capacity - (size - next_entry),
- size - next_entry, mode,
- pos, buf, bufsz);
- pos = iwl3945_print_event_log(priv, 0,
- next_entry, mode,
- pos, buf, bufsz);
+ iwl3945_print_event_log(priv,
+ capacity - (size - next_entry),
+ size - next_entry, mode);
+ iwl3945_print_event_log(priv, 0,
+ next_entry, mode);
} else
- pos = iwl3945_print_event_log(priv, next_entry - size,
- size, mode,
- pos, buf, bufsz);
+ iwl3945_print_event_log(priv, next_entry - size,
+ size, mode);
} else {
if (next_entry < size)
- pos = iwl3945_print_event_log(priv, 0,
- next_entry, mode,
- pos, buf, bufsz);
+ iwl3945_print_event_log(priv, 0, next_entry, mode);
else
- pos = iwl3945_print_event_log(priv, next_entry - size,
- size, mode,
- pos, buf, bufsz);
+ iwl3945_print_event_log(priv, next_entry - size,
+ size, mode);
}
- return pos;
}
/* For sanity check only. Actual size is determined by uCode, typ. 512 */
@@ -1617,8 +1604,7 @@ static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
#define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20)
-int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
- char **buf, bool display)
+void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log)
{
u32 base; /* SRAM byte address of event log header */
u32 capacity; /* event log capacity in # entries */
@@ -1626,13 +1612,11 @@ int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
u32 num_wraps; /* # times uCode wrapped to top of log */
u32 next_entry; /* index of next entry to be written by uCode */
u32 size; /* # entries that we'll print */
- int pos = 0;
- size_t bufsz = 0;
base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
if (!iwl3945_hw_valid_rtc_data_addr(base)) {
IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
- return -EINVAL;
+ return;
}
/* event log header */
@@ -1658,7 +1642,7 @@ int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
/* bail out if nothing in log */
if (size == 0) {
IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
- return pos;
+ return;
}
#ifdef CONFIG_IWLWIFI_DEBUG
@@ -1674,38 +1658,25 @@ int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
size);
#ifdef CONFIG_IWLWIFI_DEBUG
- if (display) {
- if (full_log)
- bufsz = capacity * 48;
- else
- bufsz = size * 48;
- *buf = kmalloc(bufsz, GFP_KERNEL);
- if (!*buf)
- return -ENOMEM;
- }
if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
/* if uCode has wrapped back to top of log,
* start at the oldest entry,
* i.e the next one that uCode would fill.
*/
if (num_wraps)
- pos = iwl3945_print_event_log(priv, next_entry,
- capacity - next_entry, mode,
- pos, buf, bufsz);
+ iwl3945_print_event_log(priv, next_entry,
+ capacity - next_entry, mode);
/* (then/else) start at top of log */
- pos = iwl3945_print_event_log(priv, 0, next_entry, mode,
- pos, buf, bufsz);
+ iwl3945_print_event_log(priv, 0, next_entry, mode);
} else
- pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
+ iwl3945_print_last_event_logs(priv, capacity, num_wraps,
+ next_entry, size, mode);
#else
- pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
+ iwl3945_print_last_event_logs(priv, capacity, num_wraps,
+ next_entry, size, mode);
#endif
- return pos;
+
}
static void iwl3945_irq_tasklet(struct iwl_priv *priv)
@@ -3025,6 +2996,18 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
mutex_unlock(&priv->mutex);
}
+static void iwl3945_bg_up(struct work_struct *data)
+{
+ struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ mutex_lock(&priv->mutex);
+ __iwl3945_up(priv);
+ mutex_unlock(&priv->mutex);
+}
+
static void iwl3945_bg_restart(struct work_struct *data)
{
struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
@@ -3041,13 +3024,7 @@ static void iwl3945_bg_restart(struct work_struct *data)
ieee80211_restart_hw(priv->hw);
} else {
iwl3945_down(priv);
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- mutex_lock(&priv->mutex);
- __iwl3945_up(priv);
- mutex_unlock(&priv->mutex);
+ queue_work(priv->workqueue, &priv->up);
}
}
@@ -3551,6 +3528,8 @@ static ssize_t store_filter_flags(struct device *d,
static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
store_filter_flags);
+#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
+
static ssize_t show_measurement(struct device *d,
struct device_attribute *attr, char *buf)
{
@@ -3620,6 +3599,7 @@ static ssize_t store_measurement(struct device *d,
static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
show_measurement, store_measurement);
+#endif /* CONFIG_IWL3945_SPECTRUM_MEASUREMENT */
static ssize_t store_retry_rate(struct device *d,
struct device_attribute *attr,
@@ -3768,6 +3748,7 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
init_waitqueue_head(&priv->wait_command_queue);
+ INIT_WORK(&priv->up, iwl3945_bg_up);
INIT_WORK(&priv->restart, iwl3945_bg_restart);
INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish);
INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
@@ -3801,7 +3782,9 @@ static struct attribute *iwl3945_sysfs_entries[] = {
&dev_attr_dump_errors.attr,
&dev_attr_flags.attr,
&dev_attr_filter_flags.attr,
+#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
&dev_attr_measurement.attr,
+#endif
&dev_attr_retry_rate.attr,
&dev_attr_statistics.attr,
&dev_attr_status.attr,
@@ -3827,6 +3810,7 @@ static struct ieee80211_ops iwl3945_hw_ops = {
.config = iwl_mac_config,
.configure_filter = iwl_configure_filter,
.set_key = iwl3945_mac_set_key,
+ .get_tx_stats = iwl_mac_get_tx_stats,
.conf_tx = iwl_mac_conf_tx,
.reset_tsf = iwl_mac_reset_tsf,
.bss_info_changed = iwl_bss_info_changed,
@@ -3847,7 +3831,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
INIT_LIST_HEAD(&priv->free_frames);
mutex_init(&priv->mutex);
- mutex_init(&priv->sync_cmd_mutex);
/* Clear the driver's (not device's) station table */
iwl_clear_stations_table(priv);
@@ -3857,7 +3840,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
priv->band = IEEE80211_BAND_2GHZ;
priv->iw_mode = NL80211_IFTYPE_STATION;
- priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
iwl_reset_qos(priv);
@@ -4040,13 +4022,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
spin_lock_init(&priv->reg_lock);
spin_lock_init(&priv->lock);
- /*
- * stop and reset the on-board processor just in case it is in a
- * strange state ... like being left stranded by a primary kernel
- * and this is now the kdump kernel trying to start up
- */
- iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
-
/***********************
* 4. Read EEPROM
* ********************/
diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/iwm.h b/trunk/drivers/net/wireless/iwmc3200wifi/iwm.h
index 79ffa3b98d73..842811142bef 100644
--- a/trunk/drivers/net/wireless/iwmc3200wifi/iwm.h
+++ b/trunk/drivers/net/wireless/iwmc3200wifi/iwm.h
@@ -268,7 +268,7 @@ struct iwm_priv {
struct sk_buff_head rx_list;
struct list_head rx_tickets;
- struct list_head rx_packets[IWM_RX_ID_HASH];
+ struct list_head rx_packets[IWM_RX_ID_HASH + 1];
struct workqueue_struct *rx_wq;
struct work_struct rx_worker;
diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/rx.c b/trunk/drivers/net/wireless/iwmc3200wifi/rx.c
index 6b53ae122680..64d16fe37f9a 100644
--- a/trunk/drivers/net/wireless/iwmc3200wifi/rx.c
+++ b/trunk/drivers/net/wireless/iwmc3200wifi/rx.c
@@ -868,35 +868,36 @@ static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf,
struct iwm_umac_notif_mgt_frame *mgt_frame =
(struct iwm_umac_notif_mgt_frame *)buf;
struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame;
+ u8 *ie;
IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame,
le16_to_cpu(mgt_frame->len));
if (ieee80211_is_assoc_req(mgt->frame_control)) {
- iwm->req_ie_len = le16_to_cpu(mgt_frame->len)
- - offsetof(struct ieee80211_mgmt,
- u.assoc_req.variable);
+ ie = mgt->u.assoc_req.variable;;
+ iwm->req_ie_len =
+ le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt);
kfree(iwm->req_ie);
iwm->req_ie = kmemdup(mgt->u.assoc_req.variable,
iwm->req_ie_len, GFP_KERNEL);
} else if (ieee80211_is_reassoc_req(mgt->frame_control)) {
- iwm->req_ie_len = le16_to_cpu(mgt_frame->len)
- - offsetof(struct ieee80211_mgmt,
- u.reassoc_req.variable);
+ ie = mgt->u.reassoc_req.variable;;
+ iwm->req_ie_len =
+ le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt);
kfree(iwm->req_ie);
iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable,
iwm->req_ie_len, GFP_KERNEL);
} else if (ieee80211_is_assoc_resp(mgt->frame_control)) {
- iwm->resp_ie_len = le16_to_cpu(mgt_frame->len)
- - offsetof(struct ieee80211_mgmt,
- u.assoc_resp.variable);
+ ie = mgt->u.assoc_resp.variable;;
+ iwm->resp_ie_len =
+ le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt);
kfree(iwm->resp_ie);
iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable,
iwm->resp_ie_len, GFP_KERNEL);
} else if (ieee80211_is_reassoc_resp(mgt->frame_control)) {
- iwm->resp_ie_len = le16_to_cpu(mgt_frame->len)
- - offsetof(struct ieee80211_mgmt,
- u.reassoc_resp.variable);
+ ie = mgt->u.reassoc_resp.variable;;
+ iwm->resp_ie_len =
+ le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt);
kfree(iwm->resp_ie);
iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable,
iwm->resp_ie_len, GFP_KERNEL);
@@ -1533,33 +1534,6 @@ static void classify8023(struct sk_buff *skb)
}
}
-static void iwm_rx_process_amsdu(struct iwm_priv *iwm, struct sk_buff *skb)
-{
- struct wireless_dev *wdev = iwm_to_wdev(iwm);
- struct net_device *ndev = iwm_to_ndev(iwm);
- struct sk_buff_head list;
- struct sk_buff *frame;
-
- IWM_HEXDUMP(iwm, DBG, RX, "A-MSDU: ", skb->data, skb->len);
-
- __skb_queue_head_init(&list);
- ieee80211_amsdu_to_8023s(skb, &list, ndev->dev_addr, wdev->iftype, 0);
-
- while ((frame = __skb_dequeue(&list))) {
- ndev->stats.rx_packets++;
- ndev->stats.rx_bytes += frame->len;
-
- frame->protocol = eth_type_trans(frame, ndev);
- frame->ip_summed = CHECKSUM_NONE;
- memset(frame->cb, 0, sizeof(frame->cb));
-
- if (netif_rx_ni(frame) == NET_RX_DROP) {
- IWM_ERR(iwm, "Packet dropped\n");
- ndev->stats.rx_dropped++;
- }
- }
-}
-
static void iwm_rx_process_packet(struct iwm_priv *iwm,
struct iwm_rx_packet *packet,
struct iwm_rx_ticket_node *ticket_node)
@@ -1574,34 +1548,25 @@ static void iwm_rx_process_packet(struct iwm_priv *iwm,
switch (le16_to_cpu(ticket_node->ticket->action)) {
case IWM_RX_TICKET_RELEASE:
IWM_DBG_RX(iwm, DBG, "RELEASE packet\n");
-
- iwm_rx_adjust_packet(iwm, packet, ticket_node);
- skb->dev = iwm_to_ndev(iwm);
classify8023(skb);
-
- if (le16_to_cpu(ticket_node->ticket->flags) &
- IWM_RX_TICKET_AMSDU_MSK) {
- iwm_rx_process_amsdu(iwm, skb);
- break;
- }
-
+ iwm_rx_adjust_packet(iwm, packet, ticket_node);
ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype);
if (ret < 0) {
IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - "
"%d\n", ret);
- kfree_skb(packet->skb);
break;
}
IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len);
- ndev->stats.rx_packets++;
- ndev->stats.rx_bytes += skb->len;
-
+ skb->dev = iwm_to_ndev(iwm);
skb->protocol = eth_type_trans(skb, ndev);
skb->ip_summed = CHECKSUM_NONE;
memset(skb->cb, 0, sizeof(skb->cb));
+ ndev->stats.rx_packets++;
+ ndev->stats.rx_bytes += skb->len;
+
if (netif_rx_ni(skb) == NET_RX_DROP) {
IWM_ERR(iwm, "Packet dropped\n");
ndev->stats.rx_dropped++;
diff --git a/trunk/drivers/net/wireless/libertas/Kconfig b/trunk/drivers/net/wireless/libertas/Kconfig
index 0485c9957575..30aa9d48d67e 100644
--- a/trunk/drivers/net/wireless/libertas/Kconfig
+++ b/trunk/drivers/net/wireless/libertas/Kconfig
@@ -37,9 +37,3 @@ config LIBERTAS_DEBUG
depends on LIBERTAS
---help---
Debugging support.
-
-config LIBERTAS_MESH
- bool "Enable mesh support"
- depends on LIBERTAS
- help
- This enables Libertas' MESH support, used by e.g. the OLPC people.
diff --git a/trunk/drivers/net/wireless/libertas/Makefile b/trunk/drivers/net/wireless/libertas/Makefile
index 45e870e33117..b188cd97a053 100644
--- a/trunk/drivers/net/wireless/libertas/Makefile
+++ b/trunk/drivers/net/wireless/libertas/Makefile
@@ -5,11 +5,11 @@ libertas-y += cmdresp.o
libertas-y += debugfs.o
libertas-y += ethtool.o
libertas-y += main.o
+libertas-y += mesh.o
libertas-y += rx.o
libertas-y += scan.o
libertas-y += tx.o
libertas-y += wext.o
-libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o
usb8xxx-objs += if_usb.o
libertas_cs-objs += if_cs.o
diff --git a/trunk/drivers/net/wireless/libertas/assoc.c b/trunk/drivers/net/wireless/libertas/assoc.c
index f03d5e4e59c3..751067369ba8 100644
--- a/trunk/drivers/net/wireless/libertas/assoc.c
+++ b/trunk/drivers/net/wireless/libertas/assoc.c
@@ -390,8 +390,10 @@ int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
cmd.enablehwauto = cpu_to_le16(priv->enablehwauto);
cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto);
ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd);
- if (!ret && cmd_action == CMD_ACT_GET)
+ if (!ret && cmd_action == CMD_ACT_GET) {
+ priv->ratebitmap = le16_to_cpu(cmd.bitmap);
priv->enablehwauto = le16_to_cpu(cmd.enablehwauto);
+ }
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
@@ -805,7 +807,8 @@ static int lbs_try_associate(struct lbs_private *priv,
}
/* Use short preamble only when both the BSS and firmware support it */
- if (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+ if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
+ (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
preamble = RADIO_PREAMBLE_SHORT;
ret = lbs_set_radio(priv, preamble, 1);
@@ -936,7 +939,8 @@ static int lbs_adhoc_join(struct lbs_private *priv,
}
/* Use short preamble only when both the BSS and firmware support it */
- if (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
+ if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
+ (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
lbs_deb_join("AdhocJoin: Short preamble\n");
preamble = RADIO_PREAMBLE_SHORT;
}
@@ -1045,7 +1049,7 @@ static int lbs_adhoc_start(struct lbs_private *priv,
struct assoc_request *assoc_req)
{
struct cmd_ds_802_11_ad_hoc_start cmd;
- u8 preamble = RADIO_PREAMBLE_SHORT;
+ u8 preamble = RADIO_PREAMBLE_LONG;
size_t ratesize = 0;
u16 tmpcap = 0;
int ret = 0;
@@ -1053,6 +1057,11 @@ static int lbs_adhoc_start(struct lbs_private *priv,
lbs_deb_enter(LBS_DEB_ASSOC);
+ if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
+ lbs_deb_join("ADHOC_START: Will use short preamble\n");
+ preamble = RADIO_PREAMBLE_SHORT;
+ }
+
ret = lbs_set_radio(priv, preamble, 1);
if (ret)
goto out;
@@ -1160,11 +1169,11 @@ int lbs_adhoc_stop(struct lbs_private *priv)
static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
struct bss_descriptor *match_bss)
{
- if (!secinfo->wep_enabled &&
- !secinfo->WPAenabled && !secinfo->WPA2enabled &&
- match_bss->wpa_ie[0] != WLAN_EID_GENERIC &&
- match_bss->rsn_ie[0] != WLAN_EID_RSN &&
- !(match_bss->capability & WLAN_CAPABILITY_PRIVACY))
+ if (!secinfo->wep_enabled && !secinfo->WPAenabled
+ && !secinfo->WPA2enabled
+ && match_bss->wpa_ie[0] != WLAN_EID_GENERIC
+ && match_bss->rsn_ie[0] != WLAN_EID_RSN
+ && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY))
return 1;
else
return 0;
@@ -1173,9 +1182,9 @@ static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
struct bss_descriptor *match_bss)
{
- if (secinfo->wep_enabled &&
- !secinfo->WPAenabled && !secinfo->WPA2enabled &&
- (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
+ if (secinfo->wep_enabled && !secinfo->WPAenabled
+ && !secinfo->WPA2enabled
+ && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
return 1;
else
return 0;
@@ -1184,8 +1193,8 @@ static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
struct bss_descriptor *match_bss)
{
- if (!secinfo->wep_enabled && secinfo->WPAenabled &&
- (match_bss->wpa_ie[0] == WLAN_EID_GENERIC)
+ if (!secinfo->wep_enabled && secinfo->WPAenabled
+ && (match_bss->wpa_ie[0] == WLAN_EID_GENERIC)
/* privacy bit may NOT be set in some APs like LinkSys WRT54G
&& (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
)
@@ -1210,11 +1219,11 @@ static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
struct bss_descriptor *match_bss)
{
- if (!secinfo->wep_enabled &&
- !secinfo->WPAenabled && !secinfo->WPA2enabled &&
- (match_bss->wpa_ie[0] != WLAN_EID_GENERIC) &&
- (match_bss->rsn_ie[0] != WLAN_EID_RSN) &&
- (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
+ if (!secinfo->wep_enabled && !secinfo->WPAenabled
+ && !secinfo->WPA2enabled
+ && (match_bss->wpa_ie[0] != WLAN_EID_GENERIC)
+ && (match_bss->rsn_ie[0] != WLAN_EID_RSN)
+ && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
return 1;
else
return 0;
@@ -1525,8 +1534,8 @@ static int assoc_helper_associate(struct lbs_private *priv,
/* If we're given and 'any' BSSID, try associating based on SSID */
if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
- if (compare_ether_addr(bssid_any, assoc_req->bssid) &&
- compare_ether_addr(bssid_off, assoc_req->bssid)) {
+ if (compare_ether_addr(bssid_any, assoc_req->bssid)
+ && compare_ether_addr(bssid_off, assoc_req->bssid)) {
ret = assoc_helper_bssid(priv, assoc_req);
done = 1;
}
@@ -1612,9 +1621,11 @@ static int assoc_helper_channel(struct lbs_private *priv,
goto restore_mesh;
}
- if (assoc_req->secinfo.wep_enabled &&
- (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len ||
- assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)) {
+ if ( assoc_req->secinfo.wep_enabled
+ && (assoc_req->wep_keys[0].len
+ || assoc_req->wep_keys[1].len
+ || assoc_req->wep_keys[2].len
+ || assoc_req->wep_keys[3].len)) {
/* Make sure WEP keys are re-sent to firmware */
set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
}
@@ -1981,14 +1992,14 @@ void lbs_association_worker(struct work_struct *work)
assoc_req->secinfo.auth_mode);
/* If 'any' SSID was specified, find an SSID to associate with */
- if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) &&
- !assoc_req->ssid_len)
+ if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)
+ && !assoc_req->ssid_len)
find_any_ssid = 1;
/* But don't use 'any' SSID if there's a valid locked BSSID to use */
if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
- if (compare_ether_addr(assoc_req->bssid, bssid_any) &&
- compare_ether_addr(assoc_req->bssid, bssid_off))
+ if (compare_ether_addr(assoc_req->bssid, bssid_any)
+ && compare_ether_addr(assoc_req->bssid, bssid_off))
find_any_ssid = 0;
}
@@ -2050,6 +2061,13 @@ void lbs_association_worker(struct work_struct *work)
goto out;
}
+ if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)
+ || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
+ ret = assoc_helper_wep_keys(priv, assoc_req);
+ if (ret)
+ goto out;
+ }
+
if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
ret = assoc_helper_secinfo(priv, assoc_req);
if (ret)
@@ -2062,31 +2080,18 @@ void lbs_association_worker(struct work_struct *work)
goto out;
}
- /*
- * v10 FW wants WPA keys to be set/cleared before WEP key operations,
- * otherwise it will fail to correctly associate to WEP networks.
- * Other firmware versions don't appear to care.
- */
- if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) ||
- test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
+ if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)
+ || test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
ret = assoc_helper_wpa_keys(priv, assoc_req);
if (ret)
goto out;
}
- if (test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags) ||
- test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
- ret = assoc_helper_wep_keys(priv, assoc_req);
- if (ret)
- goto out;
- }
-
-
/* SSID/BSSID should be the _last_ config option set, because they
* trigger the association attempt.
*/
- if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags) ||
- test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
+ if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)
+ || test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
int success = 1;
ret = assoc_helper_associate(priv, assoc_req);
diff --git a/trunk/drivers/net/wireless/libertas/cmd.c b/trunk/drivers/net/wireless/libertas/cmd.c
index 42051f7cad6d..b9b371bfa30f 100644
--- a/trunk/drivers/net/wireless/libertas/cmd.c
+++ b/trunk/drivers/net/wireless/libertas/cmd.c
@@ -143,6 +143,19 @@ int lbs_update_hw_spec(struct lbs_private *priv)
lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
cmd.hwifversion, cmd.version);
+ /* Determine mesh_fw_ver from fwrelease and fwcapinfo */
+ /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */
+ /* 5.110.22 have mesh command with 0xa3 command id */
+ /* 10.0.0.p0 FW brings in mesh config command with different id */
+ /* Check FW version MSB and initialize mesh_fw_ver */
+ if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5)
+ priv->mesh_fw_ver = MESH_FW_OLD;
+ else if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) &&
+ (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK))
+ priv->mesh_fw_ver = MESH_FW_NEW;
+ else
+ priv->mesh_fw_ver = MESH_NONE;
+
/* Clamp region code to 8-bit since FW spec indicates that it should
* only ever be 8-bit, even though the field size is 16-bit. Some firmware
* returns non-zero high 8 bits here.
@@ -842,6 +855,9 @@ int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on)
if (priv->fwrelease < 0x09000000) {
switch (preamble) {
case RADIO_PREAMBLE_SHORT:
+ if (!(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
+ goto out;
+ /* Fall through */
case RADIO_PREAMBLE_AUTO:
case RADIO_PREAMBLE_LONG:
cmd.control = cpu_to_le16(preamble);
@@ -995,8 +1011,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
ret = 0;
break;
-#ifdef CONFIG_LIBERTAS_MESH
-
case CMD_BT_ACCESS:
ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf);
break;
@@ -1005,8 +1019,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf);
break;
-#endif
-
case CMD_802_11_BEACON_CTRL:
ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
break;
@@ -1305,7 +1317,7 @@ int lbs_execute_next_command(struct lbs_private *priv)
if ((priv->psmode != LBS802_11POWERMODECAM) &&
(priv->psstate == PS_STATE_FULL_POWER) &&
((priv->connect_status == LBS_CONNECTED) ||
- lbs_mesh_connected(priv))) {
+ (priv->mesh_connect_status == LBS_CONNECTED))) {
if (priv->secinfo.WPAenabled ||
priv->secinfo.WPA2enabled) {
/* check for valid WPA group keys */
diff --git a/trunk/drivers/net/wireless/libertas/cmd.h b/trunk/drivers/net/wireless/libertas/cmd.h
index cb4138a55fdf..2862748aef70 100644
--- a/trunk/drivers/net/wireless/libertas/cmd.h
+++ b/trunk/drivers/net/wireless/libertas/cmd.h
@@ -110,6 +110,18 @@ int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val);
int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val);
+/* Mesh related */
+
+int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
+ struct cmd_ds_mesh_access *cmd);
+
+int lbs_mesh_config_send(struct lbs_private *priv,
+ struct cmd_ds_mesh_config *cmd,
+ uint16_t action, uint16_t type);
+
+int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
+
+
/* Commands only used in wext.c, assoc. and scan.c */
int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
diff --git a/trunk/drivers/net/wireless/libertas/cmdresp.c b/trunk/drivers/net/wireless/libertas/cmdresp.c
index e7470442f76b..21d57690c20a 100644
--- a/trunk/drivers/net/wireless/libertas/cmdresp.c
+++ b/trunk/drivers/net/wireless/libertas/cmdresp.c
@@ -240,6 +240,11 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
/* Now we got response from FW, cancel the command timer */
del_timer(&priv->command_timer);
priv->cmd_timed_out = 0;
+ if (priv->nr_retries) {
+ lbs_pr_info("Received result %x to command %x after %d retries\n",
+ result, curcmd, priv->nr_retries);
+ priv->nr_retries = 0;
+ }
/* Store the response code to cur_cmd_retcode. */
priv->cur_cmd_retcode = result;
@@ -480,8 +485,20 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
break;
case MACREG_INT_CODE_MESH_AUTO_STARTED:
- /* Ignore spurious autostart events */
- lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n");
+ /* Ignore spurious autostart events if autostart is disabled */
+ if (!priv->mesh_autostart_enabled) {
+ lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n");
+ break;
+ }
+ lbs_pr_info("EVENT: MESH_AUTO_STARTED\n");
+ priv->mesh_connect_status = LBS_CONNECTED;
+ if (priv->mesh_open) {
+ netif_carrier_on(priv->mesh_dev);
+ if (!priv->tx_pending_len)
+ netif_wake_queue(priv->mesh_dev);
+ }
+ priv->mode = IW_MODE_ADHOC;
+ schedule_work(&priv->sync_channel);
break;
default:
diff --git a/trunk/drivers/net/wireless/libertas/defs.h b/trunk/drivers/net/wireless/libertas/defs.h
index ea3f10ef4e00..6b6ea9f7bf5b 100644
--- a/trunk/drivers/net/wireless/libertas/defs.h
+++ b/trunk/drivers/net/wireless/libertas/defs.h
@@ -397,6 +397,13 @@ enum KEY_INFO_WPA {
KEY_INFO_WPA_ENABLED = 0x04
};
+/** mesh_fw_ver */
+enum _mesh_fw_ver {
+ MESH_NONE = 0, /* MESH is not supported */
+ MESH_FW_OLD, /* MESH is supported in FW V5 */
+ MESH_FW_NEW, /* MESH is supported in FW V10 and newer */
+};
+
/* Default values for fwt commands. */
#define FWT_DEFAULT_METRIC 0
#define FWT_DEFAULT_DIR 1
diff --git a/trunk/drivers/net/wireless/libertas/dev.h b/trunk/drivers/net/wireless/libertas/dev.h
index efb2519d9d74..6a8d2b291d8c 100644
--- a/trunk/drivers/net/wireless/libertas/dev.h
+++ b/trunk/drivers/net/wireless/libertas/dev.h
@@ -39,14 +39,15 @@ struct lbs_private {
/* Mesh */
struct net_device *mesh_dev; /* Virtual device */
-#ifdef CONFIG_LIBERTAS_MESH
u32 mesh_connect_status;
struct lbs_mesh_stats mstats;
int mesh_open;
+ int mesh_fw_ver;
+ int mesh_autostart_enabled;
uint16_t mesh_tlv;
u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1];
u8 mesh_ssid_len;
-#endif
+ struct work_struct sync_channel;
/* Monitor mode */
struct net_device *rtap_net_dev;
@@ -109,6 +110,7 @@ struct lbs_private {
struct list_head cmdpendingq; /* pending command buffers */
wait_queue_head_t cmd_pending;
struct timer_list command_timer;
+ int nr_retries;
int cmd_timed_out;
/* Command responses sent from the hardware to the driver */
@@ -174,7 +176,9 @@ struct lbs_private {
struct bss_descriptor *networks;
struct assoc_request * pending_assoc_req;
struct assoc_request * in_progress_assoc_req;
+ u16 capability;
uint16_t enablehwauto;
+ uint16_t ratebitmap;
/* ADHOC */
u16 beacon_period;
diff --git a/trunk/drivers/net/wireless/libertas/ethtool.c b/trunk/drivers/net/wireless/libertas/ethtool.c
index 3804a58d7f4e..63d020374c2b 100644
--- a/trunk/drivers/net/wireless/libertas/ethtool.c
+++ b/trunk/drivers/net/wireless/libertas/ethtool.c
@@ -114,11 +114,9 @@ const struct ethtool_ops lbs_ethtool_ops = {
.get_drvinfo = lbs_ethtool_get_drvinfo,
.get_eeprom = lbs_ethtool_get_eeprom,
.get_eeprom_len = lbs_ethtool_get_eeprom_len,
-#ifdef CONFIG_LIBERTAS_MESH
.get_sset_count = lbs_mesh_ethtool_get_sset_count,
.get_ethtool_stats = lbs_mesh_ethtool_get_stats,
.get_strings = lbs_mesh_ethtool_get_strings,
-#endif
.get_wol = lbs_ethtool_get_wol,
.set_wol = lbs_ethtool_set_wol,
};
diff --git a/trunk/drivers/net/wireless/libertas/if_spi.c b/trunk/drivers/net/wireless/libertas/if_spi.c
index 3ea03f259ee7..bf4bfbae6227 100644
--- a/trunk/drivers/net/wireless/libertas/if_spi.c
+++ b/trunk/drivers/net/wireless/libertas/if_spi.c
@@ -23,7 +23,6 @@
#include
#include
#include
-#include
#include
#include
diff --git a/trunk/drivers/net/wireless/libertas/main.c b/trunk/drivers/net/wireless/libertas/main.c
index f5d641efd50a..db38a5a719fa 100644
--- a/trunk/drivers/net/wireless/libertas/main.c
+++ b/trunk/drivers/net/wireless/libertas/main.c
@@ -123,7 +123,7 @@ static ssize_t lbs_rtap_set(struct device *dev,
if (priv->monitormode == monitor_mode)
return strlen(buf);
if (!priv->monitormode) {
- if (priv->infra_open || lbs_mesh_open(priv))
+ if (priv->infra_open || priv->mesh_open)
return -EBUSY;
if (priv->mode == IW_MODE_INFRA)
lbs_cmd_80211_deauthenticate(priv,
@@ -533,14 +533,31 @@ static int lbs_thread(void *data)
if (priv->cmd_timed_out && priv->cur_cmd) {
struct cmd_ctrl_node *cmdnode = priv->cur_cmd;
- lbs_pr_info("Timeout submitting command 0x%04x\n",
- le16_to_cpu(cmdnode->cmdbuf->command));
- lbs_complete_command(priv, cmdnode, -ETIMEDOUT);
- if (priv->reset_card)
- priv->reset_card(priv);
+ if (++priv->nr_retries > 3) {
+ lbs_pr_info("Excessive timeouts submitting "
+ "command 0x%04x\n",
+ le16_to_cpu(cmdnode->cmdbuf->command));
+ lbs_complete_command(priv, cmdnode, -ETIMEDOUT);
+ priv->nr_retries = 0;
+ if (priv->reset_card)
+ priv->reset_card(priv);
+ } else {
+ priv->cur_cmd = NULL;
+ priv->dnld_sent = DNLD_RES_RECEIVED;
+ lbs_pr_info("requeueing command 0x%04x due "
+ "to timeout (#%d)\n",
+ le16_to_cpu(cmdnode->cmdbuf->command),
+ priv->nr_retries);
+
+ /* Stick it back at the _top_ of the pending queue
+ for immediate resubmission */
+ list_add(&cmdnode->list, &priv->cmdpendingq);
+ }
}
priv->cmd_timed_out = 0;
+
+
if (!priv->fw_ready)
continue;
@@ -602,7 +619,7 @@ static int lbs_thread(void *data)
if (priv->connect_status == LBS_CONNECTED)
netif_wake_queue(priv->dev);
if (priv->mesh_dev &&
- lbs_mesh_connected(priv))
+ priv->mesh_connect_status == LBS_CONNECTED)
netif_wake_queue(priv->mesh_dev);
}
}
@@ -712,7 +729,7 @@ static int lbs_setup_firmware(struct lbs_private *priv)
* This function handles the timeout of command sending.
* It will re-send the same command again.
*/
-static void lbs_cmd_timeout_handler(unsigned long data)
+static void command_timer_fn(unsigned long data)
{
struct lbs_private *priv = (struct lbs_private *)data;
unsigned long flags;
@@ -789,6 +806,18 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv)
return 0;
}
+static void lbs_sync_channel_worker(struct work_struct *work)
+{
+ struct lbs_private *priv = container_of(work, struct lbs_private,
+ sync_channel);
+
+ lbs_deb_enter(LBS_DEB_MAIN);
+ if (lbs_update_channel(priv))
+ lbs_pr_info("Channel synchronization failed.");
+ lbs_deb_leave(LBS_DEB_MAIN);
+}
+
+
static int lbs_init_adapter(struct lbs_private *priv)
{
size_t bufsize;
@@ -816,12 +845,14 @@ static int lbs_init_adapter(struct lbs_private *priv)
memset(priv->current_addr, 0xff, ETH_ALEN);
priv->connect_status = LBS_DISCONNECTED;
+ priv->mesh_connect_status = LBS_DISCONNECTED;
priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
priv->mode = IW_MODE_INFRA;
priv->channel = DEFAULT_AD_HOC_CHANNEL;
priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
priv->radio_on = 1;
priv->enablehwauto = 1;
+ priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
priv->psmode = LBS802_11POWERMODECAM;
priv->psstate = PS_STATE_FULL_POWER;
priv->is_deep_sleep = 0;
@@ -831,7 +862,7 @@ static int lbs_init_adapter(struct lbs_private *priv)
mutex_init(&priv->lock);
- setup_timer(&priv->command_timer, lbs_cmd_timeout_handler,
+ setup_timer(&priv->command_timer, command_timer_fn,
(unsigned long)priv);
setup_timer(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn,
(unsigned long)priv);
@@ -966,6 +997,11 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker);
INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);
+ INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker);
+
+ priv->mesh_open = 0;
+ sprintf(priv->mesh_ssid, "mesh");
+ priv->mesh_ssid_len = 4;
priv->wol_criteria = 0xffffffff;
priv->wol_gpio = 0xff;
@@ -1039,17 +1075,6 @@ void lbs_remove_card(struct lbs_private *priv)
EXPORT_SYMBOL_GPL(lbs_remove_card);
-static int lbs_rtap_supported(struct lbs_private *priv)
-{
- if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5)
- return 1;
-
- /* newer firmware use a capability mask */
- return ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) &&
- (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK));
-}
-
-
int lbs_start_card(struct lbs_private *priv)
{
struct net_device *dev = priv->dev;
@@ -1069,14 +1094,12 @@ int lbs_start_card(struct lbs_private *priv)
lbs_update_channel(priv);
- lbs_init_mesh(priv);
-
/*
* While rtap isn't related to mesh, only mesh-enabled
* firmware implements the rtap functionality via
* CMD_802_11_MONITOR_MODE.
*/
- if (lbs_rtap_supported(priv)) {
+ if (lbs_init_mesh(priv)) {
if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
lbs_pr_err("cannot register lbs_rtap attribute\n");
}
@@ -1110,9 +1133,7 @@ void lbs_stop_card(struct lbs_private *priv)
netif_carrier_off(dev);
lbs_debugfs_remove_one(priv);
- lbs_deinit_mesh(priv);
-
- if (lbs_rtap_supported(priv))
+ if (lbs_deinit_mesh(priv))
device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
/* Delete the timeout of the currently processing command */
diff --git a/trunk/drivers/net/wireless/libertas/mesh.c b/trunk/drivers/net/wireless/libertas/mesh.c
index 954cd00f7452..2f91c9b808af 100644
--- a/trunk/drivers/net/wireless/libertas/mesh.c
+++ b/trunk/drivers/net/wireless/libertas/mesh.c
@@ -1,3 +1,4 @@
+#include
#include
#include
#include
@@ -195,14 +196,7 @@ int lbs_init_mesh(struct lbs_private *priv)
lbs_deb_enter(LBS_DEB_MESH);
- priv->mesh_connect_status = LBS_DISCONNECTED;
-
- /* Determine mesh_fw_ver from fwrelease and fwcapinfo */
- /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */
- /* 5.110.22 have mesh command with 0xa3 command id */
- /* 10.0.0.p0 FW brings in mesh config command with different id */
- /* Check FW version MSB and initialize mesh_fw_ver */
- if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) {
+ if (priv->mesh_fw_ver == MESH_FW_OLD) {
/* Enable mesh, if supported, and work out which TLV it uses.
0x100 + 291 is an unofficial value used in 5.110.20.pXX
0x100 + 37 is the official value used in 5.110.21.pXX
@@ -224,9 +218,7 @@ int lbs_init_mesh(struct lbs_private *priv)
priv->channel))
priv->mesh_tlv = 0;
}
- } else
- if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) &&
- (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) {
+ } else if (priv->mesh_fw_ver == MESH_FW_NEW) {
/* 10.0.0.pXX new firmwares should succeed with TLV
* 0x100+37; Do not invoke command with old TLV.
*/
@@ -235,12 +227,7 @@ int lbs_init_mesh(struct lbs_private *priv)
priv->channel))
priv->mesh_tlv = 0;
}
-
-
if (priv->mesh_tlv) {
- sprintf(priv->mesh_ssid, "mesh");
- priv->mesh_ssid_len = 4;
-
lbs_add_mesh(priv);
if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
@@ -429,10 +416,10 @@ struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
struct net_device *dev, struct rxpd *rxpd)
{
if (priv->mesh_dev) {
- if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) {
+ if (priv->mesh_fw_ver == MESH_FW_OLD) {
if (rxpd->rx_control & RxPD_MESH_FRAME)
dev = priv->mesh_dev;
- } else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) {
+ } else if (priv->mesh_fw_ver == MESH_FW_NEW) {
if (rxpd->u.bss.bss_num == MESH_IFACE_ID)
dev = priv->mesh_dev;
}
@@ -445,9 +432,9 @@ void lbs_mesh_set_txpd(struct lbs_private *priv,
struct net_device *dev, struct txpd *txpd)
{
if (dev == priv->mesh_dev) {
- if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID)
+ if (priv->mesh_fw_ver == MESH_FW_OLD)
txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
- else if (priv->mesh_tlv == TLV_TYPE_MESH_ID)
+ else if (priv->mesh_fw_ver == MESH_FW_NEW)
txpd->u.bss.bss_num = MESH_IFACE_ID;
}
}
@@ -551,7 +538,7 @@ static int __lbs_mesh_config_send(struct lbs_private *priv,
* Command id is 0xac for v10 FW along with mesh interface
* id in bits 14-13-12.
*/
- if (priv->mesh_tlv == TLV_TYPE_MESH_ID)
+ if (priv->mesh_fw_ver == MESH_FW_NEW)
command = CMD_MESH_CONFIG |
(MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET);
diff --git a/trunk/drivers/net/wireless/libertas/mesh.h b/trunk/drivers/net/wireless/libertas/mesh.h
index e2573303a328..fea9b5d005fc 100644
--- a/trunk/drivers/net/wireless/libertas/mesh.h
+++ b/trunk/drivers/net/wireless/libertas/mesh.h
@@ -9,8 +9,6 @@
#include
-#ifdef CONFIG_LIBERTAS_MESH
-
/* Mesh statistics */
struct lbs_mesh_stats {
u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */
@@ -48,20 +46,11 @@ void lbs_mesh_set_txpd(struct lbs_private *priv,
/* Command handling */
struct cmd_ds_command;
-struct cmd_ds_mesh_access;
-struct cmd_ds_mesh_config;
int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
u16 cmd_action, void *pdata_buf);
int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
u16 cmd_action, void *pdata_buf);
-int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
- struct cmd_ds_mesh_access *cmd);
-int lbs_mesh_config_send(struct lbs_private *priv,
- struct cmd_ds_mesh_config *cmd,
- uint16_t action, uint16_t type);
-int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
-
/* Persistent configuration */
@@ -86,25 +75,4 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev,
uint32_t stringset, uint8_t *s);
-/* Accessors */
-
-#define lbs_mesh_open(priv) (priv->mesh_open)
-#define lbs_mesh_connected(priv) (priv->mesh_connect_status == LBS_CONNECTED)
-
-#else
-
-#define lbs_init_mesh(priv)
-#define lbs_deinit_mesh(priv)
-#define lbs_add_mesh(priv)
-#define lbs_remove_mesh(priv)
-#define lbs_mesh_set_dev(priv, dev, rxpd) (dev)
-#define lbs_mesh_set_txpd(priv, dev, txpd)
-#define lbs_mesh_config(priv, enable, chan)
-#define lbs_mesh_open(priv) (0)
-#define lbs_mesh_connected(priv) (0)
-
-#endif
-
-
-
#endif
diff --git a/trunk/drivers/net/wireless/libertas/scan.c b/trunk/drivers/net/wireless/libertas/scan.c
index 220361e69cd3..b0b1c7841500 100644
--- a/trunk/drivers/net/wireless/libertas/scan.c
+++ b/trunk/drivers/net/wireless/libertas/scan.c
@@ -635,7 +635,7 @@ int lbs_scan_networks(struct lbs_private *priv, int full_scan)
if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len)
netif_wake_queue(priv->dev);
- if (priv->mesh_dev && lbs_mesh_connected(priv) &&
+ if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED) &&
!priv->tx_pending_len)
netif_wake_queue(priv->mesh_dev);
diff --git a/trunk/drivers/net/wireless/libertas/tx.c b/trunk/drivers/net/wireless/libertas/tx.c
index 52d244ea3d97..315d1ce286ca 100644
--- a/trunk/drivers/net/wireless/libertas/tx.c
+++ b/trunk/drivers/net/wireless/libertas/tx.c
@@ -198,7 +198,7 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
if (priv->connect_status == LBS_CONNECTED)
netif_wake_queue(priv->dev);
- if (priv->mesh_dev && lbs_mesh_connected(priv))
+ if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED))
netif_wake_queue(priv->mesh_dev);
}
EXPORT_SYMBOL_GPL(lbs_send_tx_feedback);
diff --git a/trunk/drivers/net/wireless/libertas/wext.c b/trunk/drivers/net/wireless/libertas/wext.c
index 71f88a08e090..4b1aab593a84 100644
--- a/trunk/drivers/net/wireless/libertas/wext.c
+++ b/trunk/drivers/net/wireless/libertas/wext.c
@@ -192,7 +192,7 @@ static void copy_active_data_rates(struct lbs_private *priv, u8 *rates)
lbs_deb_enter(LBS_DEB_WEXT);
if ((priv->connect_status != LBS_CONNECTED) &&
- !lbs_mesh_connected(priv))
+ (priv->mesh_connect_status != LBS_CONNECTED))
memcpy(rates, lbs_bg_rates, MAX_RATES);
else
memcpy(rates, priv->curbssparams.rates, MAX_RATES);
@@ -298,7 +298,6 @@ static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info,
return 0;
}
-#ifdef CONFIG_LIBERTAS_MESH
static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
@@ -308,7 +307,7 @@ static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info,
/* Use nickname to indicate that mesh is on */
- if (lbs_mesh_connected(priv)) {
+ if (priv->mesh_connect_status == LBS_CONNECTED) {
strncpy(extra, "Mesh", 12);
extra[12] = '\0';
dwrq->length = strlen(extra);
@@ -322,7 +321,6 @@ static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info,
lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}
-#endif
static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
@@ -424,7 +422,6 @@ static int lbs_get_mode(struct net_device *dev,
return 0;
}
-#ifdef CONFIG_LIBERTAS_MESH
static int mesh_wlan_get_mode(struct net_device *dev,
struct iw_request_info *info, u32 * uwrq,
char *extra)
@@ -436,7 +433,6 @@ static int mesh_wlan_get_mode(struct net_device *dev,
lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}
-#endif
static int lbs_get_txpow(struct net_device *dev,
struct iw_request_info *info,
@@ -867,7 +863,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
/* If we're not associated, all quality values are meaningless */
if ((priv->connect_status != LBS_CONNECTED) &&
- !lbs_mesh_connected(priv))
+ (priv->mesh_connect_status != LBS_CONNECTED))
goto out;
/* Quality by RSSI */
@@ -1014,7 +1010,6 @@ static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info,
return ret;
}
-#ifdef CONFIG_LIBERTAS_MESH
static int lbs_mesh_set_freq(struct net_device *dev,
struct iw_request_info *info,
struct iw_freq *fwrq, char *extra)
@@ -1066,7 +1061,6 @@ static int lbs_mesh_set_freq(struct net_device *dev,
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
-#endif
static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
@@ -2114,7 +2108,6 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
return ret;
}
-#ifdef CONFIG_LIBERTAS_MESH
static int lbs_mesh_get_essid(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
@@ -2168,7 +2161,6 @@ static int lbs_mesh_set_essid(struct net_device *dev,
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
-#endif
/**
* @brief Connect to the AP or Ad-hoc Network with specific bssid
@@ -2275,13 +2267,7 @@ static const iw_handler lbs_handler[] = {
(iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */
(iw_handler) NULL, /* SIOCSIWPMKSA */
};
-struct iw_handler_def lbs_handler_def = {
- .num_standard = ARRAY_SIZE(lbs_handler),
- .standard = (iw_handler *) lbs_handler,
- .get_wireless_stats = lbs_get_wireless_stats,
-};
-#ifdef CONFIG_LIBERTAS_MESH
static const iw_handler mesh_wlan_handler[] = {
(iw_handler) NULL, /* SIOCSIWCOMMIT */
(iw_handler) lbs_get_name, /* SIOCGIWNAME */
@@ -2339,10 +2325,14 @@ static const iw_handler mesh_wlan_handler[] = {
(iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */
(iw_handler) NULL, /* SIOCSIWPMKSA */
};
+struct iw_handler_def lbs_handler_def = {
+ .num_standard = ARRAY_SIZE(lbs_handler),
+ .standard = (iw_handler *) lbs_handler,
+ .get_wireless_stats = lbs_get_wireless_stats,
+};
struct iw_handler_def mesh_handler_def = {
.num_standard = ARRAY_SIZE(mesh_wlan_handler),
.standard = (iw_handler *) mesh_wlan_handler,
.get_wireless_stats = lbs_get_wireless_stats,
};
-#endif
diff --git a/trunk/drivers/net/wireless/libertas_tf/main.c b/trunk/drivers/net/wireless/libertas_tf/main.c
index 6ab30033c26c..26a1abd5bb03 100644
--- a/trunk/drivers/net/wireless/libertas_tf/main.c
+++ b/trunk/drivers/net/wireless/libertas_tf/main.c
@@ -318,14 +318,14 @@ static void lbtf_op_stop(struct ieee80211_hw *hw)
}
static int lbtf_op_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct lbtf_private *priv = hw->priv;
if (priv->vif != NULL)
return -EOPNOTSUPP;
- priv->vif = vif;
- switch (vif->type) {
+ priv->vif = conf->vif;
+ switch (conf->type) {
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_AP:
lbtf_set_mode(priv, LBTF_AP_MODE);
@@ -337,12 +337,12 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw,
priv->vif = NULL;
return -EOPNOTSUPP;
}
- lbtf_set_mac_address(priv, (u8 *) vif->addr);
+ lbtf_set_mac_address(priv, (u8 *) conf->mac_addr);
return 0;
}
static void lbtf_op_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct lbtf_private *priv = hw->priv;
@@ -555,9 +555,6 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev)
priv->band.n_channels = ARRAY_SIZE(lbtf_channels);
priv->band.channels = priv->channels;
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
- hw->wiphy->interface_modes =
- BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC);
skb_queue_head_init(&priv->bc_ps_buf);
SET_IEEE80211_DEV(hw, dmdev);
diff --git a/trunk/drivers/net/wireless/mac80211_hwsim.c b/trunk/drivers/net/wireless/mac80211_hwsim.c
index 6ea77e95277b..88e41176e7fd 100644
--- a/trunk/drivers/net/wireless/mac80211_hwsim.c
+++ b/trunk/drivers/net/wireless/mac80211_hwsim.c
@@ -32,10 +32,6 @@ static int radios = 2;
module_param(radios, int, 0444);
MODULE_PARM_DESC(radios, "Number of simulated radios");
-static bool fake_hw_scan;
-module_param(fake_hw_scan, bool, 0444);
-MODULE_PARM_DESC(fake_hw_scan, "Install fake (no-op) hw-scan handler");
-
/**
* enum hwsim_regtest - the type of regulatory tests we offer
*
@@ -285,8 +281,6 @@ struct mac80211_hwsim_data {
struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)];
struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)];
- struct mac_address addresses[2];
-
struct ieee80211_channel *channel;
unsigned long beacon_int; /* in jiffies unit */
unsigned int rx_filter;
@@ -442,38 +436,6 @@ static bool hwsim_ps_rx_ok(struct mac80211_hwsim_data *data,
}
-struct mac80211_hwsim_addr_match_data {
- bool ret;
- const u8 *addr;
-};
-
-static void mac80211_hwsim_addr_iter(void *data, u8 *mac,
- struct ieee80211_vif *vif)
-{
- struct mac80211_hwsim_addr_match_data *md = data;
- if (memcmp(mac, md->addr, ETH_ALEN) == 0)
- md->ret = true;
-}
-
-
-static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data,
- const u8 *addr)
-{
- struct mac80211_hwsim_addr_match_data md;
-
- if (memcmp(addr, data->hw->wiphy->perm_addr, ETH_ALEN) == 0)
- return true;
-
- md.ret = false;
- md.addr = addr;
- ieee80211_iterate_active_interfaces_atomic(data->hw,
- mac80211_hwsim_addr_iter,
- &md);
-
- return md.ret;
-}
-
-
static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
struct sk_buff *skb)
{
@@ -526,7 +488,8 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
if (nskb == NULL)
continue;
- if (mac80211_hwsim_addr_match(data2, hdr->addr1))
+ if (memcmp(hdr->addr1, data2->hw->wiphy->perm_addr,
+ ETH_ALEN) == 0)
ack = true;
memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status));
ieee80211_rx_irqsafe(data2->hw, nskb);
@@ -590,24 +553,24 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw)
static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n",
- wiphy_name(hw->wiphy), __func__, vif->type,
- vif->addr);
- hwsim_set_magic(vif);
+ wiphy_name(hw->wiphy), __func__, conf->type,
+ conf->mac_addr);
+ hwsim_set_magic(conf->vif);
return 0;
}
static void mac80211_hwsim_remove_interface(
- struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+ struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf)
{
printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n",
- wiphy_name(hw->wiphy), __func__, vif->type,
- vif->addr);
- hwsim_check_magic(vif);
- hwsim_clear_magic(vif);
+ wiphy_name(hw->wiphy), __func__, conf->type,
+ conf->mac_addr);
+ hwsim_check_magic(conf->vif);
+ hwsim_clear_magic(conf->vif);
}
@@ -655,26 +618,12 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
{
struct mac80211_hwsim_data *data = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
- static const char *chantypes[4] = {
- [NL80211_CHAN_NO_HT] = "noht",
- [NL80211_CHAN_HT20] = "ht20",
- [NL80211_CHAN_HT40MINUS] = "ht40-",
- [NL80211_CHAN_HT40PLUS] = "ht40+",
- };
- static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = {
- [IEEE80211_SMPS_AUTOMATIC] = "auto",
- [IEEE80211_SMPS_OFF] = "off",
- [IEEE80211_SMPS_STATIC] = "static",
- [IEEE80211_SMPS_DYNAMIC] = "dynamic",
- };
-
- printk(KERN_DEBUG "%s:%s (freq=%d/%s idle=%d ps=%d smps=%s)\n",
+
+ printk(KERN_DEBUG "%s:%s (freq=%d idle=%d ps=%d)\n",
wiphy_name(hw->wiphy), __func__,
conf->channel->center_freq,
- chantypes[conf->channel_type],
!!(conf->flags & IEEE80211_CONF_IDLE),
- !!(conf->flags & IEEE80211_CONF_PS),
- smps_modes[conf->smps_mode]);
+ !!(conf->flags & IEEE80211_CONF_PS));
data->idle = !!(conf->flags & IEEE80211_CONF_IDLE);
@@ -771,41 +720,23 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
}
}
-static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
-{
- hwsim_check_magic(vif);
- hwsim_set_sta_magic(sta);
-
- return 0;
-}
-
-static int mac80211_hwsim_sta_remove(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
-{
- hwsim_check_magic(vif);
- hwsim_clear_sta_magic(sta);
-
- return 0;
-}
-
static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum sta_notify_cmd cmd,
struct ieee80211_sta *sta)
{
hwsim_check_magic(vif);
-
switch (cmd) {
+ case STA_NOTIFY_ADD:
+ hwsim_set_sta_magic(sta);
+ break;
+ case STA_NOTIFY_REMOVE:
+ hwsim_clear_sta_magic(sta);
+ break;
case STA_NOTIFY_SLEEP:
case STA_NOTIFY_AWAKE:
/* TODO: make good use of these flags */
break;
- default:
- WARN(1, "Invalid sta notify: %d\n", cmd);
- break;
}
}
@@ -896,77 +827,7 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw,
}
#endif
-static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 *ssn)
-{
- switch (action) {
- case IEEE80211_AMPDU_TX_START:
- ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
- break;
- case IEEE80211_AMPDU_TX_STOP:
- ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
- break;
- case IEEE80211_AMPDU_TX_OPERATIONAL:
- break;
- case IEEE80211_AMPDU_RX_START:
- case IEEE80211_AMPDU_RX_STOP:
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return 0;
-}
-
-static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop)
-{
- /*
- * In this special case, there's nothing we need to
- * do because hwsim does transmission synchronously.
- * In the future, when it does transmissions via
- * userspace, we may need to do something.
- */
-}
-
-struct hw_scan_done {
- struct delayed_work w;
- struct ieee80211_hw *hw;
-};
-
-static void hw_scan_done(struct work_struct *work)
-{
- struct hw_scan_done *hsd =
- container_of(work, struct hw_scan_done, w.work);
-
- ieee80211_scan_completed(hsd->hw, false);
- kfree(hsd);
-}
-
-static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw,
- struct cfg80211_scan_request *req)
-{
- struct hw_scan_done *hsd = kzalloc(sizeof(*hsd), GFP_KERNEL);
- int i;
-
- if (!hsd)
- return -ENOMEM;
-
- hsd->hw = hw;
- INIT_DELAYED_WORK(&hsd->w, hw_scan_done);
-
- printk(KERN_DEBUG "hwsim scan request\n");
- for (i = 0; i < req->n_channels; i++)
- printk(KERN_DEBUG "hwsim scan freq %d\n",
- req->channels[i]->center_freq);
-
- ieee80211_queue_delayed_work(hw, &hsd->w, 2 * HZ);
-
- return 0;
-}
-
-static struct ieee80211_ops mac80211_hwsim_ops =
+static const struct ieee80211_ops mac80211_hwsim_ops =
{
.tx = mac80211_hwsim_tx,
.start = mac80211_hwsim_start,
@@ -976,14 +837,10 @@ static struct ieee80211_ops mac80211_hwsim_ops =
.config = mac80211_hwsim_config,
.configure_filter = mac80211_hwsim_configure_filter,
.bss_info_changed = mac80211_hwsim_bss_info_changed,
- .sta_add = mac80211_hwsim_sta_add,
- .sta_remove = mac80211_hwsim_sta_remove,
.sta_notify = mac80211_hwsim_sta_notify,
.set_tim = mac80211_hwsim_set_tim,
.conf_tx = mac80211_hwsim_conf_tx,
CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)
- .ampdu_action = mac80211_hwsim_ampdu_action,
- .flush = mac80211_hwsim_flush,
};
@@ -1178,9 +1035,6 @@ static int __init init_mac80211_hwsim(void)
if (radios < 1 || radios > 100)
return -EINVAL;
- if (fake_hw_scan)
- mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan;
-
spin_lock_init(&hwsim_radio_lock);
INIT_LIST_HEAD(&hwsim_radios);
@@ -1218,11 +1072,7 @@ static int __init init_mac80211_hwsim(void)
SET_IEEE80211_DEV(hw, data->dev);
addr[3] = i >> 8;
addr[4] = i;
- memcpy(data->addresses[0].addr, addr, ETH_ALEN);
- memcpy(data->addresses[1].addr, addr, ETH_ALEN);
- data->addresses[1].addr[0] |= 0x40;
- hw->wiphy->n_addresses = 2;
- hw->wiphy->addresses = data->addresses;
+ SET_IEEE80211_PERM_ADDR(hw, addr);
hw->channel_change_time = 1;
hw->queues = 4;
@@ -1232,9 +1082,7 @@ static int __init init_mac80211_hwsim(void)
BIT(NL80211_IFTYPE_MESH_POINT);
hw->flags = IEEE80211_HW_MFP_CAPABLE |
- IEEE80211_HW_SIGNAL_DBM |
- IEEE80211_HW_SUPPORTS_STATIC_SMPS |
- IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS;
+ IEEE80211_HW_SIGNAL_DBM;
/* ask mac80211 to reserve space for magic */
hw->vif_data_size = sizeof(struct hwsim_vif_priv);
diff --git a/trunk/drivers/net/wireless/mwl8k.c b/trunk/drivers/net/wireless/mwl8k.c
index ac65e13eb0de..59f92105b0c2 100644
--- a/trunk/drivers/net/wireless/mwl8k.c
+++ b/trunk/drivers/net/wireless/mwl8k.c
@@ -2,7 +2,7 @@
* drivers/net/wireless/mwl8k.c
* Driver for Marvell TOPDOG 802.11 Wireless cards
*
- * Copyright (C) 2008, 2009, 2010 Marvell Semiconductor Inc.
+ * Copyright (C) 2008-2009 Marvell Semiconductor Inc.
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
@@ -26,7 +26,7 @@
#define MWL8K_DESC "Marvell TOPDOG(R) 802.11 Wireless Network Driver"
#define MWL8K_NAME KBUILD_MODNAME
-#define MWL8K_VERSION "0.12"
+#define MWL8K_VERSION "0.10"
/* Register definitions */
#define MWL8K_HIU_GEN_PTR 0x00000c10
@@ -92,7 +92,8 @@ struct mwl8k_device_info {
char *part_name;
char *helper_image;
char *fw_image;
- struct rxd_ops *ap_rxd_ops;
+ struct rxd_ops *rxd_ops;
+ u16 modes;
};
struct mwl8k_rx_queue {
@@ -119,36 +120,34 @@ struct mwl8k_tx_queue {
/* sw appends here */
int tail;
- unsigned int len;
+ struct ieee80211_tx_queue_stats stats;
struct mwl8k_tx_desc *txd;
dma_addr_t txd_dma;
struct sk_buff **skb;
};
-struct mwl8k_priv {
- struct ieee80211_hw *hw;
- struct pci_dev *pdev;
+/* Pointers to the firmware data and meta information about it. */
+struct mwl8k_firmware {
+ /* Boot helper code */
+ struct firmware *helper;
- struct mwl8k_device_info *device_info;
+ /* Microcode */
+ struct firmware *ucode;
+};
+struct mwl8k_priv {
void __iomem *sram;
void __iomem *regs;
+ struct ieee80211_hw *hw;
- /* firmware */
- struct firmware *fw_helper;
- struct firmware *fw_ucode;
+ struct pci_dev *pdev;
- /* hardware/firmware parameters */
+ struct mwl8k_device_info *device_info;
bool ap_fw;
struct rxd_ops *rxd_ops;
- struct ieee80211_supported_band band_24;
- struct ieee80211_channel channels_24[14];
- struct ieee80211_rate rates_24[14];
- struct ieee80211_supported_band band_50;
- struct ieee80211_channel channels_50[4];
- struct ieee80211_rate rates_50[9];
- u32 ap_macids_supported;
- u32 sta_macids_supported;
+
+ /* firmware files and meta data */
+ struct mwl8k_firmware fw;
/* firmware access */
struct mutex fw_mutex;
@@ -162,9 +161,9 @@ struct mwl8k_priv {
/* TX quiesce completion, protected by fw_mutex and tx_lock */
struct completion *tx_wait;
- /* List of interfaces. */
- u32 macids_used;
- struct list_head vif_list;
+ struct ieee80211_vif *vif;
+
+ struct ieee80211_channel *current_channel;
/* power management status cookie from firmware */
u32 *cookie;
@@ -183,6 +182,11 @@ struct mwl8k_priv {
struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES];
struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES];
+ /* PHY parameters */
+ struct ieee80211_supported_band band;
+ struct ieee80211_channel channels[14];
+ struct ieee80211_rate rates[14];
+
bool radio_on;
bool radio_short_preamble;
bool sniffer_enabled;
@@ -201,33 +205,32 @@ struct mwl8k_priv {
*/
struct work_struct finalize_join_worker;
- /* Tasklet to perform TX reclaim. */
- struct tasklet_struct poll_tx_task;
-
- /* Tasklet to perform RX. */
- struct tasklet_struct poll_rx_task;
+ /* Tasklet to reclaim TX descriptors and buffers after tx */
+ struct tasklet_struct tx_reclaim_task;
};
/* Per interface specific private data */
struct mwl8k_vif {
- struct list_head list;
- struct ieee80211_vif *vif;
+ /* backpointer to parent config block */
+ struct mwl8k_priv *priv;
- /* Firmware macid for this vif. */
- int macid;
+ /* BSS config of AP or IBSS from mac80211*/
+ struct ieee80211_bss_conf bss_info;
- /* Non AMPDU sequence number assigned by driver. */
- u16 seqno;
-};
-#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))
+ /* BSSID of AP or IBSS */
+ u8 bssid[ETH_ALEN];
+ u8 mac_addr[ETH_ALEN];
+
+ /* Index into station database.Returned by update_sta_db call */
+ u8 peer_id;
-struct mwl8k_sta {
- /* Index into station database. Returned by UPDATE_STADB. */
- u8 peer_id;
+ /* Non AMPDU sequence number assigned by driver */
+ u16 seqno;
};
-#define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv))
-static const struct ieee80211_channel mwl8k_channels_24[] = {
+#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))
+
+static const struct ieee80211_channel mwl8k_channels[] = {
{ .center_freq = 2412, .hw_value = 1, },
{ .center_freq = 2417, .hw_value = 2, },
{ .center_freq = 2422, .hw_value = 3, },
@@ -239,12 +242,9 @@ static const struct ieee80211_channel mwl8k_channels_24[] = {
{ .center_freq = 2452, .hw_value = 9, },
{ .center_freq = 2457, .hw_value = 10, },
{ .center_freq = 2462, .hw_value = 11, },
- { .center_freq = 2467, .hw_value = 12, },
- { .center_freq = 2472, .hw_value = 13, },
- { .center_freq = 2484, .hw_value = 14, },
};
-static const struct ieee80211_rate mwl8k_rates_24[] = {
+static const struct ieee80211_rate mwl8k_rates[] = {
{ .bitrate = 10, .hw_value = 2, },
{ .bitrate = 20, .hw_value = 4, },
{ .bitrate = 55, .hw_value = 11, },
@@ -261,23 +261,8 @@ static const struct ieee80211_rate mwl8k_rates_24[] = {
{ .bitrate = 720, .hw_value = 144, },
};
-static const struct ieee80211_channel mwl8k_channels_50[] = {
- { .center_freq = 5180, .hw_value = 36, },
- { .center_freq = 5200, .hw_value = 40, },
- { .center_freq = 5220, .hw_value = 44, },
- { .center_freq = 5240, .hw_value = 48, },
-};
-
-static const struct ieee80211_rate mwl8k_rates_50[] = {
- { .bitrate = 60, .hw_value = 12, },
- { .bitrate = 90, .hw_value = 18, },
- { .bitrate = 120, .hw_value = 24, },
- { .bitrate = 180, .hw_value = 36, },
- { .bitrate = 240, .hw_value = 48, },
- { .bitrate = 360, .hw_value = 72, },
- { .bitrate = 480, .hw_value = 96, },
- { .bitrate = 540, .hw_value = 108, },
- { .bitrate = 720, .hw_value = 144, },
+static const u8 mwl8k_rateids[12] = {
+ 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108,
};
/* Set or get info from Firmware */
@@ -293,7 +278,6 @@ static const struct ieee80211_rate mwl8k_rates_50[] = {
#define MWL8K_CMD_RADIO_CONTROL 0x001c
#define MWL8K_CMD_RF_TX_POWER 0x001e
#define MWL8K_CMD_RF_ANTENNA 0x0020
-#define MWL8K_CMD_SET_BEACON 0x0100 /* per-vif */
#define MWL8K_CMD_SET_PRE_SCAN 0x0107
#define MWL8K_CMD_SET_POST_SCAN 0x0108
#define MWL8K_CMD_SET_RF_CHANNEL 0x010a
@@ -307,10 +291,8 @@ static const struct ieee80211_rate mwl8k_rates_50[] = {
#define MWL8K_CMD_MIMO_CONFIG 0x0125
#define MWL8K_CMD_USE_FIXED_RATE 0x0126
#define MWL8K_CMD_ENABLE_SNIFFER 0x0150
-#define MWL8K_CMD_SET_MAC_ADDR 0x0202 /* per-vif */
+#define MWL8K_CMD_SET_MAC_ADDR 0x0202
#define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203
-#define MWL8K_CMD_BSS_START 0x1100 /* per-vif */
-#define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */
#define MWL8K_CMD_UPDATE_STADB 0x1123
static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize)
@@ -328,7 +310,6 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize)
MWL8K_CMDNAME(RADIO_CONTROL);
MWL8K_CMDNAME(RF_TX_POWER);
MWL8K_CMDNAME(RF_ANTENNA);
- MWL8K_CMDNAME(SET_BEACON);
MWL8K_CMDNAME(SET_PRE_SCAN);
MWL8K_CMDNAME(SET_POST_SCAN);
MWL8K_CMDNAME(SET_RF_CHANNEL);
@@ -344,8 +325,6 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize)
MWL8K_CMDNAME(ENABLE_SNIFFER);
MWL8K_CMDNAME(SET_MAC_ADDR);
MWL8K_CMDNAME(SET_RATEADAPT_MODE);
- MWL8K_CMDNAME(BSS_START);
- MWL8K_CMDNAME(SET_NEW_STN);
MWL8K_CMDNAME(UPDATE_STADB);
default:
snprintf(buf, bufsize, "0x%x", cmd);
@@ -376,8 +355,8 @@ static void mwl8k_release_fw(struct firmware **fw)
static void mwl8k_release_firmware(struct mwl8k_priv *priv)
{
- mwl8k_release_fw(&priv->fw_ucode);
- mwl8k_release_fw(&priv->fw_helper);
+ mwl8k_release_fw(&priv->fw.ucode);
+ mwl8k_release_fw(&priv->fw.helper);
}
/* Request fw image */
@@ -398,7 +377,7 @@ static int mwl8k_request_firmware(struct mwl8k_priv *priv)
int rc;
if (di->helper_image != NULL) {
- rc = mwl8k_request_fw(priv, di->helper_image, &priv->fw_helper);
+ rc = mwl8k_request_fw(priv, di->helper_image, &priv->fw.helper);
if (rc) {
printk(KERN_ERR "%s: Error requesting helper "
"firmware file %s\n", pci_name(priv->pdev),
@@ -407,22 +386,24 @@ static int mwl8k_request_firmware(struct mwl8k_priv *priv)
}
}
- rc = mwl8k_request_fw(priv, di->fw_image, &priv->fw_ucode);
+ rc = mwl8k_request_fw(priv, di->fw_image, &priv->fw.ucode);
if (rc) {
printk(KERN_ERR "%s: Error requesting firmware file %s\n",
pci_name(priv->pdev), di->fw_image);
- mwl8k_release_fw(&priv->fw_helper);
+ mwl8k_release_fw(&priv->fw.helper);
return rc;
}
return 0;
}
+MODULE_FIRMWARE("mwl8k/helper_8687.fw");
+MODULE_FIRMWARE("mwl8k/fmimage_8687.fw");
+
struct mwl8k_cmd_pkt {
__le16 code;
__le16 length;
- __u8 seq_num;
- __u8 macid;
+ __le16 seq_num;
__le16 result;
char payload[0];
} __attribute__((packed));
@@ -480,7 +461,6 @@ static int mwl8k_load_fw_image(struct mwl8k_priv *priv,
cmd->code = cpu_to_le16(MWL8K_CMD_CODE_DNLD);
cmd->seq_num = 0;
- cmd->macid = 0;
cmd->result = 0;
done = 0;
@@ -571,12 +551,13 @@ static int mwl8k_feed_fw_image(struct mwl8k_priv *priv,
static int mwl8k_load_firmware(struct ieee80211_hw *hw)
{
struct mwl8k_priv *priv = hw->priv;
- struct firmware *fw = priv->fw_ucode;
+ struct firmware *fw = priv->fw.ucode;
+ struct mwl8k_device_info *di = priv->device_info;
int rc;
int loops;
if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) {
- struct firmware *helper = priv->fw_helper;
+ struct firmware *helper = priv->fw.helper;
if (helper == NULL) {
printk(KERN_ERR "%s: helper image needed but none "
@@ -603,7 +584,10 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw)
return rc;
}
- iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR);
+ if (di->modes & BIT(NL80211_IFTYPE_AP))
+ iowrite32(MWL8K_MODE_AP, priv->regs + MWL8K_HIU_GEN_PTR);
+ else
+ iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR);
loops = 500000;
do {
@@ -626,6 +610,91 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw)
}
+/*
+ * Defines shared between transmission and reception.
+ */
+/* HT control fields for firmware */
+struct ewc_ht_info {
+ __le16 control1;
+ __le16 control2;
+ __le16 control3;
+} __attribute__((packed));
+
+/* Firmware Station database operations */
+#define MWL8K_STA_DB_ADD_ENTRY 0
+#define MWL8K_STA_DB_MODIFY_ENTRY 1
+#define MWL8K_STA_DB_DEL_ENTRY 2
+#define MWL8K_STA_DB_FLUSH 3
+
+/* Peer Entry flags - used to define the type of the peer node */
+#define MWL8K_PEER_TYPE_ACCESSPOINT 2
+
+struct peer_capability_info {
+ /* Peer type - AP vs. STA. */
+ __u8 peer_type;
+
+ /* Basic 802.11 capabilities from assoc resp. */
+ __le16 basic_caps;
+
+ /* Set if peer supports 802.11n high throughput (HT). */
+ __u8 ht_support;
+
+ /* Valid if HT is supported. */
+ __le16 ht_caps;
+ __u8 extended_ht_caps;
+ struct ewc_ht_info ewc_info;
+
+ /* Legacy rate table. Intersection of our rates and peer rates. */
+ __u8 legacy_rates[12];
+
+ /* HT rate table. Intersection of our rates and peer rates. */
+ __u8 ht_rates[16];
+ __u8 pad[16];
+
+ /* If set, interoperability mode, no proprietary extensions. */
+ __u8 interop;
+ __u8 pad2;
+ __u8 station_id;
+ __le16 amsdu_enabled;
+} __attribute__((packed));
+
+/* Inline functions to manipulate QoS field in data descriptor. */
+static inline u16 mwl8k_qos_setbit_eosp(u16 qos)
+{
+ u16 val_mask = 1 << 4;
+
+ /* End of Service Period Bit 4 */
+ return qos | val_mask;
+}
+
+static inline u16 mwl8k_qos_setbit_ack(u16 qos, u8 ack_policy)
+{
+ u16 val_mask = 0x3;
+ u8 shift = 5;
+ u16 qos_mask = ~(val_mask << shift);
+
+ /* Ack Policy Bit 5-6 */
+ return (qos & qos_mask) | ((ack_policy & val_mask) << shift);
+}
+
+static inline u16 mwl8k_qos_setbit_amsdu(u16 qos)
+{
+ u16 val_mask = 1 << 7;
+
+ /* AMSDU present Bit 7 */
+ return qos | val_mask;
+}
+
+static inline u16 mwl8k_qos_setbit_qlen(u16 qos, u8 len)
+{
+ u16 val_mask = 0xff;
+ u8 shift = 8;
+ u16 qos_mask = ~(val_mask << shift);
+
+ /* Queue Length Bits 8-15 */
+ return (qos & qos_mask) | ((len & val_mask) << shift);
+}
+
/* DMA header used by firmware and hardware. */
struct mwl8k_dma_data {
__le16 fwlen;
@@ -692,9 +761,9 @@ static inline void mwl8k_add_dma_header(struct sk_buff *skb)
/*
- * Packet reception for 88w8366 AP firmware.
+ * Packet reception for 88w8366.
*/
-struct mwl8k_rxd_8366_ap {
+struct mwl8k_rxd_8366 {
__le16 pkt_len;
__u8 sq2;
__u8 rate;
@@ -712,23 +781,23 @@ struct mwl8k_rxd_8366_ap {
__u8 rx_ctrl;
} __attribute__((packed));
-#define MWL8K_8366_AP_RATE_INFO_MCS_FORMAT 0x80
-#define MWL8K_8366_AP_RATE_INFO_40MHZ 0x40
-#define MWL8K_8366_AP_RATE_INFO_RATEID(x) ((x) & 0x3f)
+#define MWL8K_8366_RATE_INFO_MCS_FORMAT 0x80
+#define MWL8K_8366_RATE_INFO_40MHZ 0x40
+#define MWL8K_8366_RATE_INFO_RATEID(x) ((x) & 0x3f)
-#define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST 0x80
+#define MWL8K_8366_RX_CTRL_OWNED_BY_HOST 0x80
-static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr)
+static void mwl8k_rxd_8366_init(void *_rxd, dma_addr_t next_dma_addr)
{
- struct mwl8k_rxd_8366_ap *rxd = _rxd;
+ struct mwl8k_rxd_8366 *rxd = _rxd;
rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr);
- rxd->rx_ctrl = MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST;
+ rxd->rx_ctrl = MWL8K_8366_RX_CTRL_OWNED_BY_HOST;
}
-static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len)
+static void mwl8k_rxd_8366_refill(void *_rxd, dma_addr_t addr, int len)
{
- struct mwl8k_rxd_8366_ap *rxd = _rxd;
+ struct mwl8k_rxd_8366 *rxd = _rxd;
rxd->pkt_len = cpu_to_le16(len);
rxd->pkt_phys_addr = cpu_to_le32(addr);
@@ -737,12 +806,12 @@ static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len)
}
static int
-mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
- __le16 *qos)
+mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status,
+ __le16 *qos)
{
- struct mwl8k_rxd_8366_ap *rxd = _rxd;
+ struct mwl8k_rxd_8366 *rxd = _rxd;
- if (!(rxd->rx_ctrl & MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST))
+ if (!(rxd->rx_ctrl & MWL8K_8366_RX_CTRL_OWNED_BY_HOST))
return -1;
rmb();
@@ -751,29 +820,23 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
status->signal = -rxd->rssi;
status->noise = -rxd->noise_floor;
- if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) {
+ if (rxd->rate & MWL8K_8366_RATE_INFO_MCS_FORMAT) {
status->flag |= RX_FLAG_HT;
- if (rxd->rate & MWL8K_8366_AP_RATE_INFO_40MHZ)
+ if (rxd->rate & MWL8K_8366_RATE_INFO_40MHZ)
status->flag |= RX_FLAG_40MHZ;
- status->rate_idx = MWL8K_8366_AP_RATE_INFO_RATEID(rxd->rate);
+ status->rate_idx = MWL8K_8366_RATE_INFO_RATEID(rxd->rate);
} else {
int i;
- for (i = 0; i < ARRAY_SIZE(mwl8k_rates_24); i++) {
- if (mwl8k_rates_24[i].hw_value == rxd->rate) {
+ for (i = 0; i < ARRAY_SIZE(mwl8k_rates); i++) {
+ if (mwl8k_rates[i].hw_value == rxd->rate) {
status->rate_idx = i;
break;
}
}
}
- if (rxd->channel > 14) {
- status->band = IEEE80211_BAND_5GHZ;
- if (!(status->flag & RX_FLAG_HT))
- status->rate_idx -= 5;
- } else {
- status->band = IEEE80211_BAND_2GHZ;
- }
+ status->band = IEEE80211_BAND_2GHZ;
status->freq = ieee80211_channel_to_frequency(rxd->channel);
*qos = rxd->qos_control;
@@ -781,17 +844,17 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
return le16_to_cpu(rxd->pkt_len);
}
-static struct rxd_ops rxd_8366_ap_ops = {
- .rxd_size = sizeof(struct mwl8k_rxd_8366_ap),
- .rxd_init = mwl8k_rxd_8366_ap_init,
- .rxd_refill = mwl8k_rxd_8366_ap_refill,
- .rxd_process = mwl8k_rxd_8366_ap_process,
+static struct rxd_ops rxd_8366_ops = {
+ .rxd_size = sizeof(struct mwl8k_rxd_8366),
+ .rxd_init = mwl8k_rxd_8366_init,
+ .rxd_refill = mwl8k_rxd_8366_refill,
+ .rxd_process = mwl8k_rxd_8366_process,
};
/*
- * Packet reception for STA firmware.
+ * Packet reception for 88w8687.
*/
-struct mwl8k_rxd_sta {
+struct mwl8k_rxd_8687 {
__le16 pkt_len;
__u8 link_quality;
__u8 noise_level;
@@ -808,26 +871,26 @@ struct mwl8k_rxd_sta {
__u8 pad2[2];
} __attribute__((packed));
-#define MWL8K_STA_RATE_INFO_SHORTPRE 0x8000
-#define MWL8K_STA_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3)
-#define MWL8K_STA_RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f)
-#define MWL8K_STA_RATE_INFO_40MHZ 0x0004
-#define MWL8K_STA_RATE_INFO_SHORTGI 0x0002
-#define MWL8K_STA_RATE_INFO_MCS_FORMAT 0x0001
+#define MWL8K_8687_RATE_INFO_SHORTPRE 0x8000
+#define MWL8K_8687_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3)
+#define MWL8K_8687_RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f)
+#define MWL8K_8687_RATE_INFO_40MHZ 0x0004
+#define MWL8K_8687_RATE_INFO_SHORTGI 0x0002
+#define MWL8K_8687_RATE_INFO_MCS_FORMAT 0x0001
-#define MWL8K_STA_RX_CTRL_OWNED_BY_HOST 0x02
+#define MWL8K_8687_RX_CTRL_OWNED_BY_HOST 0x02
-static void mwl8k_rxd_sta_init(void *_rxd, dma_addr_t next_dma_addr)
+static void mwl8k_rxd_8687_init(void *_rxd, dma_addr_t next_dma_addr)
{
- struct mwl8k_rxd_sta *rxd = _rxd;
+ struct mwl8k_rxd_8687 *rxd = _rxd;
rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr);
- rxd->rx_ctrl = MWL8K_STA_RX_CTRL_OWNED_BY_HOST;
+ rxd->rx_ctrl = MWL8K_8687_RX_CTRL_OWNED_BY_HOST;
}
-static void mwl8k_rxd_sta_refill(void *_rxd, dma_addr_t addr, int len)
+static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len)
{
- struct mwl8k_rxd_sta *rxd = _rxd;
+ struct mwl8k_rxd_8687 *rxd = _rxd;
rxd->pkt_len = cpu_to_le16(len);
rxd->pkt_phys_addr = cpu_to_le32(addr);
@@ -836,13 +899,13 @@ static void mwl8k_rxd_sta_refill(void *_rxd, dma_addr_t addr, int len)
}
static int
-mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status,
+mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status,
__le16 *qos)
{
- struct mwl8k_rxd_sta *rxd = _rxd;
+ struct mwl8k_rxd_8687 *rxd = _rxd;
u16 rate_info;
- if (!(rxd->rx_ctrl & MWL8K_STA_RX_CTRL_OWNED_BY_HOST))
+ if (!(rxd->rx_ctrl & MWL8K_8687_RX_CTRL_OWNED_BY_HOST))
return -1;
rmb();
@@ -852,25 +915,19 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status,
status->signal = -rxd->rssi;
status->noise = -rxd->noise_level;
- status->antenna = MWL8K_STA_RATE_INFO_ANTSELECT(rate_info);
- status->rate_idx = MWL8K_STA_RATE_INFO_RATEID(rate_info);
+ status->antenna = MWL8K_8687_RATE_INFO_ANTSELECT(rate_info);
+ status->rate_idx = MWL8K_8687_RATE_INFO_RATEID(rate_info);
- if (rate_info & MWL8K_STA_RATE_INFO_SHORTPRE)
+ if (rate_info & MWL8K_8687_RATE_INFO_SHORTPRE)
status->flag |= RX_FLAG_SHORTPRE;
- if (rate_info & MWL8K_STA_RATE_INFO_40MHZ)
+ if (rate_info & MWL8K_8687_RATE_INFO_40MHZ)
status->flag |= RX_FLAG_40MHZ;
- if (rate_info & MWL8K_STA_RATE_INFO_SHORTGI)
+ if (rate_info & MWL8K_8687_RATE_INFO_SHORTGI)
status->flag |= RX_FLAG_SHORT_GI;
- if (rate_info & MWL8K_STA_RATE_INFO_MCS_FORMAT)
+ if (rate_info & MWL8K_8687_RATE_INFO_MCS_FORMAT)
status->flag |= RX_FLAG_HT;
- if (rxd->channel > 14) {
- status->band = IEEE80211_BAND_5GHZ;
- if (!(status->flag & RX_FLAG_HT))
- status->rate_idx -= 5;
- } else {
- status->band = IEEE80211_BAND_2GHZ;
- }
+ status->band = IEEE80211_BAND_2GHZ;
status->freq = ieee80211_channel_to_frequency(rxd->channel);
*qos = rxd->qos_control;
@@ -878,11 +935,11 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status,
return le16_to_cpu(rxd->pkt_len);
}
-static struct rxd_ops rxd_sta_ops = {
- .rxd_size = sizeof(struct mwl8k_rxd_sta),
- .rxd_init = mwl8k_rxd_sta_init,
- .rxd_refill = mwl8k_rxd_sta_refill,
- .rxd_process = mwl8k_rxd_sta_process,
+static struct rxd_ops rxd_8687_ops = {
+ .rxd_size = sizeof(struct mwl8k_rxd_8687),
+ .rxd_init = mwl8k_rxd_8687_init,
+ .rxd_refill = mwl8k_rxd_8687_refill,
+ .rxd_process = mwl8k_rxd_8687_process,
};
@@ -1096,18 +1153,16 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
* Packet transmission.
*/
+/* Transmit packet ACK policy */
+#define MWL8K_TXD_ACK_POLICY_NORMAL 0
+#define MWL8K_TXD_ACK_POLICY_BLOCKACK 3
+
#define MWL8K_TXD_STATUS_OK 0x00000001
#define MWL8K_TXD_STATUS_OK_RETRY 0x00000002
#define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004
#define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008
#define MWL8K_TXD_STATUS_FW_OWNED 0x80000000
-#define MWL8K_QOS_QLEN_UNSPEC 0xff00
-#define MWL8K_QOS_ACK_POLICY_MASK 0x0060
-#define MWL8K_QOS_ACK_POLICY_NORMAL 0x0000
-#define MWL8K_QOS_ACK_POLICY_BLOCKACK 0x0060
-#define MWL8K_QOS_EOSP 0x0010
-
struct mwl8k_tx_desc {
__le32 status;
__u8 data_rate;
@@ -1132,7 +1187,8 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
int size;
int i;
- txq->len = 0;
+ memset(&txq->stats, 0, sizeof(struct ieee80211_tx_queue_stats));
+ txq->stats.limit = MWL8K_TX_DESCS;
txq->head = 0;
txq->tail = 0;
@@ -1208,7 +1264,7 @@ static void mwl8k_dump_tx_rings(struct ieee80211_hw *hw)
printk(KERN_ERR "%s: txq[%d] len=%d head=%d tail=%d "
"fw_owned=%d drv_owned=%d unused=%d\n",
wiphy_name(hw->wiphy), i,
- txq->len, txq->head, txq->tail,
+ txq->stats.len, txq->head, txq->tail,
fw_owned, drv_owned, unused);
}
}
@@ -1216,7 +1272,7 @@ static void mwl8k_dump_tx_rings(struct ieee80211_hw *hw)
/*
* Must be called with priv->fw_mutex held and tx queues stopped.
*/
-#define MWL8K_TX_WAIT_TIMEOUT_MS 5000
+#define MWL8K_TX_WAIT_TIMEOUT_MS 1000
static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
{
@@ -1260,8 +1316,8 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
}
if (priv->pending_tx_pkts < oldcount) {
- printk(KERN_NOTICE "%s: waiting for tx rings "
- "to drain (%d -> %d pkts)\n",
+ printk(KERN_NOTICE "%s: timeout waiting for tx "
+ "rings to drain (%d -> %d pkts), retrying\n",
wiphy_name(hw->wiphy), oldcount,
priv->pending_tx_pkts);
retry = 1;
@@ -1286,15 +1342,13 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
MWL8K_TXD_STATUS_OK_RETRY | \
MWL8K_TXD_STATUS_OK_MORE_RETRY))
-static int
-mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force)
+static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
{
struct mwl8k_priv *priv = hw->priv;
struct mwl8k_tx_queue *txq = priv->txq + index;
- int processed;
+ int wake = 0;
- processed = 0;
- while (txq->len > 0 && limit--) {
+ while (txq->stats.len > 0) {
int tx;
struct mwl8k_tx_desc *tx_desc;
unsigned long addr;
@@ -1316,8 +1370,8 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force)
}
txq->head = (tx + 1) % MWL8K_TX_DESCS;
- BUG_ON(txq->len == 0);
- txq->len--;
+ BUG_ON(txq->stats.len == 0);
+ txq->stats.len--;
priv->pending_tx_pkts--;
addr = le32_to_cpu(tx_desc->pkt_phys_addr);
@@ -1341,13 +1395,11 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force)
ieee80211_tx_status_irqsafe(hw, skb);
- processed++;
+ wake = 1;
}
- if (processed && priv->radio_on && !mutex_is_locked(&priv->fw_mutex))
+ if (wake && priv->radio_on && !mutex_is_locked(&priv->fw_mutex))
ieee80211_wake_queue(hw, index);
-
- return processed;
}
/* must be called only when the card's transmit is completely halted */
@@ -1356,7 +1408,7 @@ static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index)
struct mwl8k_priv *priv = hw->priv;
struct mwl8k_tx_queue *txq = priv->txq + index;
- mwl8k_txq_reclaim(hw, index, INT_MAX, 1);
+ mwl8k_txq_reclaim(hw, index, 1);
kfree(txq->skb);
txq->skb = NULL;
@@ -1394,9 +1446,11 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
mwl8k_vif = MWL8K_VIF(tx_info->control.vif);
if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+ u16 seqno = mwl8k_vif->seqno;
+
wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
- wh->seq_ctrl |= cpu_to_le16(mwl8k_vif->seqno);
- mwl8k_vif->seqno += 0x10;
+ wh->seq_ctrl |= cpu_to_le16(seqno << 4);
+ mwl8k_vif->seqno = seqno++ % 4096;
}
/* Setup firmware control bit fields for each frame type. */
@@ -1405,17 +1459,24 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
if (ieee80211_is_mgmt(wh->frame_control) ||
ieee80211_is_ctl(wh->frame_control)) {
txdatarate = 0;
- qos |= MWL8K_QOS_QLEN_UNSPEC | MWL8K_QOS_EOSP;
+ qos = mwl8k_qos_setbit_eosp(qos);
+ /* Set Queue size to unspecified */
+ qos = mwl8k_qos_setbit_qlen(qos, 0xff);
} else if (ieee80211_is_data(wh->frame_control)) {
txdatarate = 1;
if (is_multicast_ether_addr(wh->addr1))
txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX;
- qos &= ~MWL8K_QOS_ACK_POLICY_MASK;
+ /* Send pkt in an aggregate if AMPDU frame. */
if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
- qos |= MWL8K_QOS_ACK_POLICY_BLOCKACK;
+ qos = mwl8k_qos_setbit_ack(qos,
+ MWL8K_TXD_ACK_POLICY_BLOCKACK);
else
- qos |= MWL8K_QOS_ACK_POLICY_NORMAL;
+ qos = mwl8k_qos_setbit_ack(qos,
+ MWL8K_TXD_ACK_POLICY_NORMAL);
+
+ if (qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
+ qos = mwl8k_qos_setbit_amsdu(qos);
}
dma = pci_map_single(priv->pdev, skb->data,
@@ -1442,14 +1503,12 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
tx->pkt_phys_addr = cpu_to_le32(dma);
tx->pkt_len = cpu_to_le16(skb->len);
tx->rate_info = 0;
- if (!priv->ap_fw && tx_info->control.sta != NULL)
- tx->peer_id = MWL8K_STA(tx_info->control.sta)->peer_id;
- else
- tx->peer_id = 0;
+ tx->peer_id = mwl8k_vif->peer_id;
wmb();
tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus);
- txq->len++;
+ txq->stats.count++;
+ txq->stats.len++;
priv->pending_tx_pkts++;
txq->tail++;
@@ -1597,56 +1656,6 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
return rc;
}
-static int mwl8k_post_pervif_cmd(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct mwl8k_cmd_pkt *cmd)
-{
- if (vif != NULL)
- cmd->macid = MWL8K_VIF(vif)->macid;
- return mwl8k_post_cmd(hw, cmd);
-}
-
-/*
- * Setup code shared between STA and AP firmware images.
- */
-static void mwl8k_setup_2ghz_band(struct ieee80211_hw *hw)
-{
- struct mwl8k_priv *priv = hw->priv;
-
- BUILD_BUG_ON(sizeof(priv->channels_24) != sizeof(mwl8k_channels_24));
- memcpy(priv->channels_24, mwl8k_channels_24, sizeof(mwl8k_channels_24));
-
- BUILD_BUG_ON(sizeof(priv->rates_24) != sizeof(mwl8k_rates_24));
- memcpy(priv->rates_24, mwl8k_rates_24, sizeof(mwl8k_rates_24));
-
- priv->band_24.band = IEEE80211_BAND_2GHZ;
- priv->band_24.channels = priv->channels_24;
- priv->band_24.n_channels = ARRAY_SIZE(mwl8k_channels_24);
- priv->band_24.bitrates = priv->rates_24;
- priv->band_24.n_bitrates = ARRAY_SIZE(mwl8k_rates_24);
-
- hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band_24;
-}
-
-static void mwl8k_setup_5ghz_band(struct ieee80211_hw *hw)
-{
- struct mwl8k_priv *priv = hw->priv;
-
- BUILD_BUG_ON(sizeof(priv->channels_50) != sizeof(mwl8k_channels_50));
- memcpy(priv->channels_50, mwl8k_channels_50, sizeof(mwl8k_channels_50));
-
- BUILD_BUG_ON(sizeof(priv->rates_50) != sizeof(mwl8k_rates_50));
- memcpy(priv->rates_50, mwl8k_rates_50, sizeof(mwl8k_rates_50));
-
- priv->band_50.band = IEEE80211_BAND_5GHZ;
- priv->band_50.channels = priv->channels_50;
- priv->band_50.n_channels = ARRAY_SIZE(mwl8k_channels_50);
- priv->band_50.bitrates = priv->rates_50;
- priv->band_50.n_bitrates = ARRAY_SIZE(mwl8k_rates_50);
-
- hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->band_50;
-}
-
/*
* CMD_GET_HW_SPEC (STA version).
*/
@@ -1669,89 +1678,6 @@ struct mwl8k_cmd_get_hw_spec_sta {
__le32 total_rxd;
} __attribute__((packed));
-#define MWL8K_CAP_MAX_AMSDU 0x20000000
-#define MWL8K_CAP_GREENFIELD 0x08000000
-#define MWL8K_CAP_AMPDU 0x04000000
-#define MWL8K_CAP_RX_STBC 0x01000000
-#define MWL8K_CAP_TX_STBC 0x00800000
-#define MWL8K_CAP_SHORTGI_40MHZ 0x00400000
-#define MWL8K_CAP_SHORTGI_20MHZ 0x00200000
-#define MWL8K_CAP_RX_ANTENNA_MASK 0x000e0000
-#define MWL8K_CAP_TX_ANTENNA_MASK 0x0001c000
-#define MWL8K_CAP_DELAY_BA 0x00003000
-#define MWL8K_CAP_MIMO 0x00000200
-#define MWL8K_CAP_40MHZ 0x00000100
-#define MWL8K_CAP_BAND_MASK 0x00000007
-#define MWL8K_CAP_5GHZ 0x00000004
-#define MWL8K_CAP_2GHZ4 0x00000001
-
-static void
-mwl8k_set_ht_caps(struct ieee80211_hw *hw,
- struct ieee80211_supported_band *band, u32 cap)
-{
- int rx_streams;
- int tx_streams;
-
- band->ht_cap.ht_supported = 1;
-
- if (cap & MWL8K_CAP_MAX_AMSDU)
- band->ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
- if (cap & MWL8K_CAP_GREENFIELD)
- band->ht_cap.cap |= IEEE80211_HT_CAP_GRN_FLD;
- if (cap & MWL8K_CAP_AMPDU) {
- hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
- band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
- band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
- }
- if (cap & MWL8K_CAP_RX_STBC)
- band->ht_cap.cap |= IEEE80211_HT_CAP_RX_STBC;
- if (cap & MWL8K_CAP_TX_STBC)
- band->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
- if (cap & MWL8K_CAP_SHORTGI_40MHZ)
- band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
- if (cap & MWL8K_CAP_SHORTGI_20MHZ)
- band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
- if (cap & MWL8K_CAP_DELAY_BA)
- band->ht_cap.cap |= IEEE80211_HT_CAP_DELAY_BA;
- if (cap & MWL8K_CAP_40MHZ)
- band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
-
- rx_streams = hweight32(cap & MWL8K_CAP_RX_ANTENNA_MASK);
- tx_streams = hweight32(cap & MWL8K_CAP_TX_ANTENNA_MASK);
-
- band->ht_cap.mcs.rx_mask[0] = 0xff;
- if (rx_streams >= 2)
- band->ht_cap.mcs.rx_mask[1] = 0xff;
- if (rx_streams >= 3)
- band->ht_cap.mcs.rx_mask[2] = 0xff;
- band->ht_cap.mcs.rx_mask[4] = 0x01;
- band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
-
- if (rx_streams != tx_streams) {
- band->ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
- band->ht_cap.mcs.tx_params |= (tx_streams - 1) <<
- IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
- }
-}
-
-static void
-mwl8k_set_caps(struct ieee80211_hw *hw, u32 caps)
-{
- struct mwl8k_priv *priv = hw->priv;
-
- if ((caps & MWL8K_CAP_2GHZ4) || !(caps & MWL8K_CAP_BAND_MASK)) {
- mwl8k_setup_2ghz_band(hw);
- if (caps & MWL8K_CAP_MIMO)
- mwl8k_set_ht_caps(hw, &priv->band_24, caps);
- }
-
- if (caps & MWL8K_CAP_5GHZ) {
- mwl8k_setup_5ghz_band(hw);
- if (caps & MWL8K_CAP_MIMO)
- mwl8k_set_ht_caps(hw, &priv->band_50, caps);
- }
-}
-
static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw)
{
struct mwl8k_priv *priv = hw->priv;
@@ -1782,9 +1708,6 @@ static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw)
priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs);
priv->fw_rev = le32_to_cpu(cmd->fw_rev);
priv->hw_rev = cmd->hw_rev;
- mwl8k_set_caps(hw, le32_to_cpu(cmd->caps));
- priv->ap_macids_supported = 0x00000000;
- priv->sta_macids_supported = 0x00000001;
}
kfree(cmd);
@@ -1838,9 +1761,6 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw)
priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs);
priv->fw_rev = le32_to_cpu(cmd->fw_rev);
priv->hw_rev = cmd->hw_rev;
- mwl8k_setup_2ghz_band(hw);
- priv->ap_macids_supported = 0x000000ff;
- priv->sta_macids_supported = 0x00000000;
off = le32_to_cpu(cmd->wcbbase0) & 0xffff;
iowrite32(cpu_to_le32(priv->txq[0].txd_dma), priv->sram + off);
@@ -1886,9 +1806,7 @@ struct mwl8k_cmd_set_hw_spec {
__le32 total_rxd;
} __attribute__((packed));
-#define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080
-#define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020
-#define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010
+#define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080
static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw)
{
@@ -1909,9 +1827,7 @@ static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw)
cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES);
for (i = 0; i < MWL8K_TX_QUEUES; i++)
cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].txd_dma);
- cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT |
- MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP |
- MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON);
+ cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT);
cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS);
cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS);
@@ -1981,9 +1897,9 @@ __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti,
}
/*
- * CMD_GET_STAT.
+ * CMD_802_11_GET_STAT.
*/
-struct mwl8k_cmd_get_stat {
+struct mwl8k_cmd_802_11_get_stat {
struct mwl8k_cmd_pkt header;
__le32 stats[64];
} __attribute__((packed));
@@ -1993,10 +1909,10 @@ struct mwl8k_cmd_get_stat {
#define MWL8K_STAT_FCS_ERROR 24
#define MWL8K_STAT_RTS_SUCCESS 11
-static int mwl8k_cmd_get_stat(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats)
+static int mwl8k_cmd_802_11_get_stat(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats)
{
- struct mwl8k_cmd_get_stat *cmd;
+ struct mwl8k_cmd_802_11_get_stat *cmd;
int rc;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
@@ -2023,9 +1939,9 @@ static int mwl8k_cmd_get_stat(struct ieee80211_hw *hw,
}
/*
- * CMD_RADIO_CONTROL.
+ * CMD_802_11_RADIO_CONTROL.
*/
-struct mwl8k_cmd_radio_control {
+struct mwl8k_cmd_802_11_radio_control {
struct mwl8k_cmd_pkt header;
__le16 action;
__le16 control;
@@ -2033,10 +1949,10 @@ struct mwl8k_cmd_radio_control {
} __attribute__((packed));
static int
-mwl8k_cmd_radio_control(struct ieee80211_hw *hw, bool enable, bool force)
+mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, bool enable, bool force)
{
struct mwl8k_priv *priv = hw->priv;
- struct mwl8k_cmd_radio_control *cmd;
+ struct mwl8k_cmd_802_11_radio_control *cmd;
int rc;
if (enable == priv->radio_on && !force)
@@ -2061,32 +1977,36 @@ mwl8k_cmd_radio_control(struct ieee80211_hw *hw, bool enable, bool force)
return rc;
}
-static int mwl8k_cmd_radio_disable(struct ieee80211_hw *hw)
+static int mwl8k_cmd_802_11_radio_disable(struct ieee80211_hw *hw)
{
- return mwl8k_cmd_radio_control(hw, 0, 0);
+ return mwl8k_cmd_802_11_radio_control(hw, 0, 0);
}
-static int mwl8k_cmd_radio_enable(struct ieee80211_hw *hw)
+static int mwl8k_cmd_802_11_radio_enable(struct ieee80211_hw *hw)
{
- return mwl8k_cmd_radio_control(hw, 1, 0);
+ return mwl8k_cmd_802_11_radio_control(hw, 1, 0);
}
static int
mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble)
{
- struct mwl8k_priv *priv = hw->priv;
+ struct mwl8k_priv *priv;
+
+ if (hw == NULL || hw->priv == NULL)
+ return -EINVAL;
+ priv = hw->priv;
priv->radio_short_preamble = short_preamble;
- return mwl8k_cmd_radio_control(hw, 1, 1);
+ return mwl8k_cmd_802_11_radio_control(hw, 1, 1);
}
/*
- * CMD_RF_TX_POWER.
+ * CMD_802_11_RF_TX_POWER.
*/
#define MWL8K_TX_POWER_LEVEL_TOTAL 8
-struct mwl8k_cmd_rf_tx_power {
+struct mwl8k_cmd_802_11_rf_tx_power {
struct mwl8k_cmd_pkt header;
__le16 action;
__le16 support_level;
@@ -2095,9 +2015,9 @@ struct mwl8k_cmd_rf_tx_power {
__le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL];
} __attribute__((packed));
-static int mwl8k_cmd_rf_tx_power(struct ieee80211_hw *hw, int dBm)
+static int mwl8k_cmd_802_11_rf_tx_power(struct ieee80211_hw *hw, int dBm)
{
- struct mwl8k_cmd_rf_tx_power *cmd;
+ struct mwl8k_cmd_802_11_rf_tx_power *cmd;
int rc;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
@@ -2148,36 +2068,6 @@ mwl8k_cmd_rf_antenna(struct ieee80211_hw *hw, int antenna, int mask)
return rc;
}
-/*
- * CMD_SET_BEACON.
- */
-struct mwl8k_cmd_set_beacon {
- struct mwl8k_cmd_pkt header;
- __le16 beacon_len;
- __u8 beacon[0];
-};
-
-static int mwl8k_cmd_set_beacon(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, u8 *beacon, int len)
-{
- struct mwl8k_cmd_set_beacon *cmd;
- int rc;
-
- cmd = kzalloc(sizeof(*cmd) + len, GFP_KERNEL);
- if (cmd == NULL)
- return -ENOMEM;
-
- cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_BEACON);
- cmd->header.length = cpu_to_le16(sizeof(*cmd) + len);
- cmd->beacon_len = cpu_to_le16(len);
- memcpy(cmd->beacon, beacon, len);
-
- rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
- kfree(cmd);
-
- return rc;
-}
-
/*
* CMD_SET_PRE_SCAN.
*/
@@ -2213,7 +2103,7 @@ struct mwl8k_cmd_set_post_scan {
} __attribute__((packed));
static int
-mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, const __u8 *mac)
+mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 *mac)
{
struct mwl8k_cmd_set_post_scan *cmd;
int rc;
@@ -2244,9 +2134,8 @@ struct mwl8k_cmd_set_rf_channel {
} __attribute__((packed));
static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw,
- struct ieee80211_conf *conf)
+ struct ieee80211_channel *channel)
{
- struct ieee80211_channel *channel = conf->channel;
struct mwl8k_cmd_set_rf_channel *cmd;
int rc;
@@ -2258,19 +2147,10 @@ static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw,
cmd->header.length = cpu_to_le16(sizeof(*cmd));
cmd->action = cpu_to_le16(MWL8K_CMD_SET);
cmd->current_channel = channel->hw_value;
-
if (channel->band == IEEE80211_BAND_2GHZ)
- cmd->channel_flags |= cpu_to_le32(0x00000001);
- else if (channel->band == IEEE80211_BAND_5GHZ)
- cmd->channel_flags |= cpu_to_le32(0x00000004);
-
- if (conf->channel_type == NL80211_CHAN_NO_HT ||
- conf->channel_type == NL80211_CHAN_HT20)
- cmd->channel_flags |= cpu_to_le32(0x00000080);
- else if (conf->channel_type == NL80211_CHAN_HT40MINUS)
- cmd->channel_flags |= cpu_to_le32(0x000001900);
- else if (conf->channel_type == NL80211_CHAN_HT40PLUS)
- cmd->channel_flags |= cpu_to_le32(0x000000900);
+ cmd->channel_flags = cpu_to_le32(0x00000081);
+ else
+ cmd->channel_flags = cpu_to_le32(0x00000000);
rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
@@ -2279,75 +2159,27 @@ static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw,
}
/*
- * CMD_SET_AID.
+ * CMD_SET_SLOT.
*/
-#define MWL8K_FRAME_PROT_DISABLED 0x00
-#define MWL8K_FRAME_PROT_11G 0x07
-#define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02
-#define MWL8K_FRAME_PROT_11N_HT_ALL 0x06
-
-struct mwl8k_cmd_update_set_aid {
- struct mwl8k_cmd_pkt header;
- __le16 aid;
-
- /* AP's MAC address (BSSID) */
- __u8 bssid[ETH_ALEN];
- __le16 protection_mode;
- __u8 supp_rates[14];
+struct mwl8k_cmd_set_slot {
+ struct mwl8k_cmd_pkt header;
+ __le16 action;
+ __u8 short_slot;
} __attribute__((packed));
-static void legacy_rate_mask_to_array(u8 *rates, u32 mask)
-{
- int i;
- int j;
-
- /*
- * Clear nonstandard rates 4 and 13.
- */
- mask &= 0x1fef;
-
- for (i = 0, j = 0; i < 14; i++) {
- if (mask & (1 << i))
- rates[j++] = mwl8k_rates_24[i].hw_value;
- }
-}
-
-static int
-mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, u32 legacy_rate_mask)
+static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time)
{
- struct mwl8k_cmd_update_set_aid *cmd;
- u16 prot_mode;
+ struct mwl8k_cmd_set_slot *cmd;
int rc;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
- cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID);
+ cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
- cmd->aid = cpu_to_le16(vif->bss_conf.aid);
- memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN);
-
- if (vif->bss_conf.use_cts_prot) {
- prot_mode = MWL8K_FRAME_PROT_11G;
- } else {
- switch (vif->bss_conf.ht_operation_mode &
- IEEE80211_HT_OP_MODE_PROTECTION) {
- case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
- prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY;
- break;
- case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
- prot_mode = MWL8K_FRAME_PROT_11N_HT_ALL;
- break;
- default:
- prot_mode = MWL8K_FRAME_PROT_DISABLED;
- break;
- }
- }
- cmd->protection_mode = cpu_to_le16(prot_mode);
-
- legacy_rate_mask_to_array(cmd->supp_rates, legacy_rate_mask);
+ cmd->action = cpu_to_le16(MWL8K_CMD_SET);
+ cmd->short_slot = short_slot_time;
rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
@@ -2356,32 +2188,29 @@ mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
}
/*
- * CMD_SET_RATE.
+ * CMD_MIMO_CONFIG.
*/
-struct mwl8k_cmd_set_rate {
- struct mwl8k_cmd_pkt header;
- __u8 legacy_rates[14];
-
- /* Bitmap for supported MCS codes. */
- __u8 mcs_set[16];
- __u8 reserved[16];
+struct mwl8k_cmd_mimo_config {
+ struct mwl8k_cmd_pkt header;
+ __le32 action;
+ __u8 rx_antenna_map;
+ __u8 tx_antenna_map;
} __attribute__((packed));
-static int
-mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- u32 legacy_rate_mask, u8 *mcs_rates)
+static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx)
{
- struct mwl8k_cmd_set_rate *cmd;
+ struct mwl8k_cmd_mimo_config *cmd;
int rc;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
- cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE);
+ cmd->header.code = cpu_to_le16(MWL8K_CMD_MIMO_CONFIG);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
- legacy_rate_mask_to_array(cmd->legacy_rates, legacy_rate_mask);
- memcpy(cmd->mcs_set, mcs_rates, 16);
+ cmd->action = cpu_to_le32((u32)MWL8K_CMD_SET);
+ cmd->rx_antenna_map = rx;
+ cmd->tx_antenna_map = tx;
rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
@@ -2390,39 +2219,64 @@ mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
/*
- * CMD_FINALIZE_JOIN.
+ * CMD_ENABLE_SNIFFER.
*/
-#define MWL8K_FJ_BEACON_MAXLEN 128
-
-struct mwl8k_cmd_finalize_join {
+struct mwl8k_cmd_enable_sniffer {
struct mwl8k_cmd_pkt header;
- __le32 sleep_interval; /* Number of beacon periods to sleep */
- __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN];
+ __le32 action;
} __attribute__((packed));
-static int mwl8k_cmd_finalize_join(struct ieee80211_hw *hw, void *frame,
- int framelen, int dtim)
+static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable)
{
- struct mwl8k_cmd_finalize_join *cmd;
- struct ieee80211_mgmt *payload = frame;
- int payload_len;
+ struct mwl8k_cmd_enable_sniffer *cmd;
int rc;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
- cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN);
+ cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
- cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1);
+ cmd->action = cpu_to_le32(!!enable);
- payload_len = framelen - ieee80211_hdrlen(payload->frame_control);
- if (payload_len < 0)
- payload_len = 0;
- else if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
- payload_len = MWL8K_FJ_BEACON_MAXLEN;
+ rc = mwl8k_post_cmd(hw, &cmd->header);
+ kfree(cmd);
- memcpy(cmd->beacon_data, &payload->u.beacon, payload_len);
+ return rc;
+}
+
+/*
+ * CMD_SET_MAC_ADDR.
+ */
+struct mwl8k_cmd_set_mac_addr {
+ struct mwl8k_cmd_pkt header;
+ union {
+ struct {
+ __le16 mac_type;
+ __u8 mac_addr[ETH_ALEN];
+ } mbss;
+ __u8 mac_addr[ETH_ALEN];
+ };
+} __attribute__((packed));
+
+static int mwl8k_set_mac_addr(struct ieee80211_hw *hw, u8 *mac)
+{
+ struct mwl8k_priv *priv = hw->priv;
+ struct mwl8k_cmd_set_mac_addr *cmd;
+ int rc;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (cmd == NULL)
+ return -ENOMEM;
+
+ cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR);
+ cmd->header.length = cpu_to_le16(sizeof(*cmd));
+ if (priv->ap_fw) {
+ cmd->mbss.mac_type = 0;
+ memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN);
+ } else {
+ memcpy(cmd->mac_addr, mac, ETH_ALEN);
+ }
rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
@@ -2430,29 +2284,29 @@ static int mwl8k_cmd_finalize_join(struct ieee80211_hw *hw, void *frame,
return rc;
}
+
/*
- * CMD_SET_RTS_THRESHOLD.
+ * CMD_SET_RATEADAPT_MODE.
*/
-struct mwl8k_cmd_set_rts_threshold {
+struct mwl8k_cmd_set_rate_adapt_mode {
struct mwl8k_cmd_pkt header;
__le16 action;
- __le16 threshold;
+ __le16 mode;
} __attribute__((packed));
-static int
-mwl8k_cmd_set_rts_threshold(struct ieee80211_hw *hw, int rts_thresh)
+static int mwl8k_cmd_setrateadaptmode(struct ieee80211_hw *hw, __u16 mode)
{
- struct mwl8k_cmd_set_rts_threshold *cmd;
+ struct mwl8k_cmd_set_rate_adapt_mode *cmd;
int rc;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
- cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD);
+ cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATEADAPT_MODE);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
cmd->action = cpu_to_le16(MWL8K_CMD_SET);
- cmd->threshold = cpu_to_le16(rts_thresh);
+ cmd->mode = cpu_to_le16(mode);
rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
@@ -2461,27 +2315,59 @@ mwl8k_cmd_set_rts_threshold(struct ieee80211_hw *hw, int rts_thresh)
}
/*
- * CMD_SET_SLOT.
+ * CMD_SET_WMM_MODE.
*/
-struct mwl8k_cmd_set_slot {
+struct mwl8k_cmd_set_wmm {
struct mwl8k_cmd_pkt header;
__le16 action;
- __u8 short_slot;
} __attribute__((packed));
-static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time)
+static int mwl8k_set_wmm(struct ieee80211_hw *hw, bool enable)
{
- struct mwl8k_cmd_set_slot *cmd;
+ struct mwl8k_priv *priv = hw->priv;
+ struct mwl8k_cmd_set_wmm *cmd;
int rc;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
- cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT);
+ cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
- cmd->action = cpu_to_le16(MWL8K_CMD_SET);
- cmd->short_slot = short_slot_time;
+ cmd->action = cpu_to_le16(!!enable);
+
+ rc = mwl8k_post_cmd(hw, &cmd->header);
+ kfree(cmd);
+
+ if (!rc)
+ priv->wmm_enabled = enable;
+
+ return rc;
+}
+
+/*
+ * CMD_SET_RTS_THRESHOLD.
+ */
+struct mwl8k_cmd_rts_threshold {
+ struct mwl8k_cmd_pkt header;
+ __le16 action;
+ __le16 threshold;
+} __attribute__((packed));
+
+static int mwl8k_rts_threshold(struct ieee80211_hw *hw,
+ u16 action, u16 threshold)
+{
+ struct mwl8k_cmd_rts_threshold *cmd;
+ int rc;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (cmd == NULL)
+ return -ENOMEM;
+
+ cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD);
+ cmd->header.length = cpu_to_le16(sizeof(*cmd));
+ cmd->action = cpu_to_le16(action);
+ cmd->threshold = cpu_to_le16(threshold);
rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
@@ -2540,9 +2426,9 @@ struct mwl8k_cmd_set_edca_params {
MWL8K_SET_EDCA_AIFS)
static int
-mwl8k_cmd_set_edca_params(struct ieee80211_hw *hw, __u8 qnum,
- __u16 cw_min, __u16 cw_max,
- __u8 aifs, __u16 txop)
+mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum,
+ __u16 cw_min, __u16 cw_max,
+ __u8 aifs, __u16 txop)
{
struct mwl8k_priv *priv = hw->priv;
struct mwl8k_cmd_set_edca_params *cmd;
@@ -2552,6 +2438,12 @@ mwl8k_cmd_set_edca_params(struct ieee80211_hw *hw, __u8 qnum,
if (cmd == NULL)
return -ENOMEM;
+ /*
+ * Queues 0 (BE) and 1 (BK) are swapped in hardware for
+ * this call.
+ */
+ qnum ^= !(qnum >> 1);
+
cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL);
@@ -2575,102 +2467,39 @@ mwl8k_cmd_set_edca_params(struct ieee80211_hw *hw, __u8 qnum,
}
/*
- * CMD_SET_WMM_MODE.
+ * CMD_FINALIZE_JOIN.
*/
-struct mwl8k_cmd_set_wmm_mode {
- struct mwl8k_cmd_pkt header;
- __le16 action;
-} __attribute__((packed));
-
-static int mwl8k_cmd_set_wmm_mode(struct ieee80211_hw *hw, bool enable)
-{
- struct mwl8k_priv *priv = hw->priv;
- struct mwl8k_cmd_set_wmm_mode *cmd;
- int rc;
-
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
- if (cmd == NULL)
- return -ENOMEM;
-
- cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE);
- cmd->header.length = cpu_to_le16(sizeof(*cmd));
- cmd->action = cpu_to_le16(!!enable);
-
- rc = mwl8k_post_cmd(hw, &cmd->header);
- kfree(cmd);
-
- if (!rc)
- priv->wmm_enabled = enable;
-
- return rc;
-}
+#define MWL8K_FJ_BEACON_MAXLEN 128
-/*
- * CMD_MIMO_CONFIG.
- */
-struct mwl8k_cmd_mimo_config {
+struct mwl8k_cmd_finalize_join {
struct mwl8k_cmd_pkt header;
- __le32 action;
- __u8 rx_antenna_map;
- __u8 tx_antenna_map;
+ __le32 sleep_interval; /* Number of beacon periods to sleep */
+ __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN];
} __attribute__((packed));
-static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx)
+static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame,
+ int framelen, int dtim)
{
- struct mwl8k_cmd_mimo_config *cmd;
+ struct mwl8k_cmd_finalize_join *cmd;
+ struct ieee80211_mgmt *payload = frame;
+ int payload_len;
int rc;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
- cmd->header.code = cpu_to_le16(MWL8K_CMD_MIMO_CONFIG);
+ cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
- cmd->action = cpu_to_le32((u32)MWL8K_CMD_SET);
- cmd->rx_antenna_map = rx;
- cmd->tx_antenna_map = tx;
-
- rc = mwl8k_post_cmd(hw, &cmd->header);
- kfree(cmd);
-
- return rc;
-}
-
-/*
- * CMD_USE_FIXED_RATE (STA version).
- */
-struct mwl8k_cmd_use_fixed_rate_sta {
- struct mwl8k_cmd_pkt header;
- __le32 action;
- __le32 allow_rate_drop;
- __le32 num_rates;
- struct {
- __le32 is_ht_rate;
- __le32 enable_retry;
- __le32 rate;
- __le32 retry_count;
- } rate_entry[8];
- __le32 rate_type;
- __le32 reserved1;
- __le32 reserved2;
-} __attribute__((packed));
-
-#define MWL8K_USE_AUTO_RATE 0x0002
-#define MWL8K_UCAST_RATE 0
-
-static int mwl8k_cmd_use_fixed_rate_sta(struct ieee80211_hw *hw)
-{
- struct mwl8k_cmd_use_fixed_rate_sta *cmd;
- int rc;
+ cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1);
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
- if (cmd == NULL)
- return -ENOMEM;
+ payload_len = framelen - ieee80211_hdrlen(payload->frame_control);
+ if (payload_len < 0)
+ payload_len = 0;
+ else if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
+ payload_len = MWL8K_FJ_BEACON_MAXLEN;
- cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE);
- cmd->header.length = cpu_to_le16(sizeof(*cmd));
- cmd->action = cpu_to_le32(MWL8K_USE_AUTO_RATE);
- cmd->rate_type = cpu_to_le32(MWL8K_UCAST_RATE);
+ memcpy(cmd->beacon_data, &payload->u.beacon, payload_len);
rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
@@ -2679,412 +2508,246 @@ static int mwl8k_cmd_use_fixed_rate_sta(struct ieee80211_hw *hw)
}
/*
- * CMD_USE_FIXED_RATE (AP version).
+ * CMD_UPDATE_STADB.
*/
-struct mwl8k_cmd_use_fixed_rate_ap {
+struct mwl8k_cmd_update_sta_db {
struct mwl8k_cmd_pkt header;
- __le32 action;
- __le32 allow_rate_drop;
- __le32 num_rates;
- struct mwl8k_rate_entry_ap {
- __le32 is_ht_rate;
- __le32 enable_retry;
- __le32 rate;
- __le32 retry_count;
- } rate_entry[4];
- u8 multicast_rate;
- u8 multicast_rate_type;
- u8 management_rate;
-} __attribute__((packed));
-
-static int
-mwl8k_cmd_use_fixed_rate_ap(struct ieee80211_hw *hw, int mcast, int mgmt)
-{
- struct mwl8k_cmd_use_fixed_rate_ap *cmd;
- int rc;
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
- if (cmd == NULL)
- return -ENOMEM;
-
- cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE);
- cmd->header.length = cpu_to_le16(sizeof(*cmd));
- cmd->action = cpu_to_le32(MWL8K_USE_AUTO_RATE);
- cmd->multicast_rate = mcast;
- cmd->management_rate = mgmt;
+ /* See STADB_ACTION_TYPE */
+ __le32 action;
- rc = mwl8k_post_cmd(hw, &cmd->header);
- kfree(cmd);
+ /* Peer MAC address */
+ __u8 peer_addr[ETH_ALEN];
- return rc;
-}
+ __le32 reserved;
-/*
- * CMD_ENABLE_SNIFFER.
- */
-struct mwl8k_cmd_enable_sniffer {
- struct mwl8k_cmd_pkt header;
- __le32 action;
+ /* Peer info - valid during add/update. */
+ struct peer_capability_info peer_info;
} __attribute__((packed));
-static int mwl8k_cmd_enable_sniffer(struct ieee80211_hw *hw, bool enable)
+static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, __u32 action)
{
- struct mwl8k_cmd_enable_sniffer *cmd;
+ struct mwl8k_vif *mv_vif = MWL8K_VIF(vif);
+ struct ieee80211_bss_conf *info = &mv_vif->bss_info;
+ struct mwl8k_cmd_update_sta_db *cmd;
+ struct peer_capability_info *peer_info;
int rc;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
- cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER);
+ cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
- cmd->action = cpu_to_le32(!!enable);
-
- rc = mwl8k_post_cmd(hw, &cmd->header);
- kfree(cmd);
-
- return rc;
-}
-/*
- * CMD_SET_MAC_ADDR.
- */
-struct mwl8k_cmd_set_mac_addr {
- struct mwl8k_cmd_pkt header;
- union {
- struct {
- __le16 mac_type;
- __u8 mac_addr[ETH_ALEN];
- } mbss;
- __u8 mac_addr[ETH_ALEN];
- };
-} __attribute__((packed));
-
-#define MWL8K_MAC_TYPE_PRIMARY_CLIENT 0
-#define MWL8K_MAC_TYPE_SECONDARY_CLIENT 1
-#define MWL8K_MAC_TYPE_PRIMARY_AP 2
-#define MWL8K_MAC_TYPE_SECONDARY_AP 3
-
-static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, u8 *mac)
-{
- struct mwl8k_priv *priv = hw->priv;
- struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
- struct mwl8k_cmd_set_mac_addr *cmd;
- int mac_type;
- int rc;
+ cmd->action = cpu_to_le32(action);
+ peer_info = &cmd->peer_info;
+ memcpy(cmd->peer_addr, mv_vif->bssid, ETH_ALEN);
- mac_type = MWL8K_MAC_TYPE_PRIMARY_AP;
- if (vif != NULL && vif->type == NL80211_IFTYPE_STATION) {
- if (mwl8k_vif->macid + 1 == ffs(priv->sta_macids_supported))
- mac_type = MWL8K_MAC_TYPE_PRIMARY_CLIENT;
- else
- mac_type = MWL8K_MAC_TYPE_SECONDARY_CLIENT;
- } else if (vif != NULL && vif->type == NL80211_IFTYPE_AP) {
- if (mwl8k_vif->macid + 1 == ffs(priv->ap_macids_supported))
- mac_type = MWL8K_MAC_TYPE_PRIMARY_AP;
- else
- mac_type = MWL8K_MAC_TYPE_SECONDARY_AP;
- }
+ switch (action) {
+ case MWL8K_STA_DB_ADD_ENTRY:
+ case MWL8K_STA_DB_MODIFY_ENTRY:
+ /* Build peer_info block */
+ peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT;
+ peer_info->basic_caps = cpu_to_le16(info->assoc_capability);
+ memcpy(peer_info->legacy_rates, mwl8k_rateids,
+ sizeof(mwl8k_rateids));
+ peer_info->interop = 1;
+ peer_info->amsdu_enabled = 0;
+
+ rc = mwl8k_post_cmd(hw, &cmd->header);
+ if (rc == 0)
+ mv_vif->peer_id = peer_info->station_id;
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
- if (cmd == NULL)
- return -ENOMEM;
+ break;
- cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR);
- cmd->header.length = cpu_to_le16(sizeof(*cmd));
- if (priv->ap_fw) {
- cmd->mbss.mac_type = cpu_to_le16(mac_type);
- memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN);
- } else {
- memcpy(cmd->mac_addr, mac, ETH_ALEN);
+ case MWL8K_STA_DB_DEL_ENTRY:
+ case MWL8K_STA_DB_FLUSH:
+ default:
+ rc = mwl8k_post_cmd(hw, &cmd->header);
+ if (rc == 0)
+ mv_vif->peer_id = 0;
+ break;
}
-
- rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
kfree(cmd);
return rc;
}
/*
- * CMD_SET_RATEADAPT_MODE.
+ * CMD_SET_AID.
*/
-struct mwl8k_cmd_set_rate_adapt_mode {
- struct mwl8k_cmd_pkt header;
- __le16 action;
- __le16 mode;
-} __attribute__((packed));
-
-static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode)
-{
- struct mwl8k_cmd_set_rate_adapt_mode *cmd;
- int rc;
-
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
- if (cmd == NULL)
- return -ENOMEM;
-
- cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATEADAPT_MODE);
- cmd->header.length = cpu_to_le16(sizeof(*cmd));
- cmd->action = cpu_to_le16(MWL8K_CMD_SET);
- cmd->mode = cpu_to_le16(mode);
-
- rc = mwl8k_post_cmd(hw, &cmd->header);
- kfree(cmd);
+#define MWL8K_FRAME_PROT_DISABLED 0x00
+#define MWL8K_FRAME_PROT_11G 0x07
+#define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02
+#define MWL8K_FRAME_PROT_11N_HT_ALL 0x06
- return rc;
-}
+struct mwl8k_cmd_update_set_aid {
+ struct mwl8k_cmd_pkt header;
+ __le16 aid;
-/*
- * CMD_BSS_START.
- */
-struct mwl8k_cmd_bss_start {
- struct mwl8k_cmd_pkt header;
- __le32 enable;
+ /* AP's MAC address (BSSID) */
+ __u8 bssid[ETH_ALEN];
+ __le16 protection_mode;
+ __u8 supp_rates[14];
} __attribute__((packed));
-static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, int enable)
+static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
- struct mwl8k_cmd_bss_start *cmd;
+ struct mwl8k_vif *mv_vif = MWL8K_VIF(vif);
+ struct ieee80211_bss_conf *info = &mv_vif->bss_info;
+ struct mwl8k_cmd_update_set_aid *cmd;
+ u16 prot_mode;
int rc;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
- cmd->header.code = cpu_to_le16(MWL8K_CMD_BSS_START);
+ cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
- cmd->enable = cpu_to_le32(enable);
-
- rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
- kfree(cmd);
-
- return rc;
-}
-
-/*
- * CMD_SET_NEW_STN.
- */
-struct mwl8k_cmd_set_new_stn {
- struct mwl8k_cmd_pkt header;
- __le16 aid;
- __u8 mac_addr[6];
- __le16 stn_id;
- __le16 action;
- __le16 rsvd;
- __le32 legacy_rates;
- __u8 ht_rates[4];
- __le16 cap_info;
- __le16 ht_capabilities_info;
- __u8 mac_ht_param_info;
- __u8 rev;
- __u8 control_channel;
- __u8 add_channel;
- __le16 op_mode;
- __le16 stbc;
- __u8 add_qos_info;
- __u8 is_qos_sta;
- __le32 fw_sta_ptr;
-} __attribute__((packed));
+ cmd->aid = cpu_to_le16(info->aid);
-#define MWL8K_STA_ACTION_ADD 0
-#define MWL8K_STA_ACTION_REMOVE 2
-
-static int mwl8k_cmd_set_new_stn_add(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
-{
- struct mwl8k_cmd_set_new_stn *cmd;
- u32 rates;
- int rc;
+ memcpy(cmd->bssid, mv_vif->bssid, ETH_ALEN);
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
- if (cmd == NULL)
- return -ENOMEM;
-
- cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN);
- cmd->header.length = cpu_to_le16(sizeof(*cmd));
- cmd->aid = cpu_to_le16(sta->aid);
- memcpy(cmd->mac_addr, sta->addr, ETH_ALEN);
- cmd->stn_id = cpu_to_le16(sta->aid);
- cmd->action = cpu_to_le16(MWL8K_STA_ACTION_ADD);
- if (hw->conf.channel->band == IEEE80211_BAND_2GHZ)
- rates = sta->supp_rates[IEEE80211_BAND_2GHZ];
- else
- rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5;
- cmd->legacy_rates = cpu_to_le32(rates);
- if (sta->ht_cap.ht_supported) {
- cmd->ht_rates[0] = sta->ht_cap.mcs.rx_mask[0];
- cmd->ht_rates[1] = sta->ht_cap.mcs.rx_mask[1];
- cmd->ht_rates[2] = sta->ht_cap.mcs.rx_mask[2];
- cmd->ht_rates[3] = sta->ht_cap.mcs.rx_mask[3];
- cmd->ht_capabilities_info = cpu_to_le16(sta->ht_cap.cap);
- cmd->mac_ht_param_info = (sta->ht_cap.ampdu_factor & 3) |
- ((sta->ht_cap.ampdu_density & 7) << 2);
- cmd->is_qos_sta = 1;
+ if (info->use_cts_prot) {
+ prot_mode = MWL8K_FRAME_PROT_11G;
+ } else {
+ switch (info->ht_operation_mode &
+ IEEE80211_HT_OP_MODE_PROTECTION) {
+ case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
+ prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY;
+ break;
+ case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
+ prot_mode = MWL8K_FRAME_PROT_11N_HT_ALL;
+ break;
+ default:
+ prot_mode = MWL8K_FRAME_PROT_DISABLED;
+ break;
+ }
}
+ cmd->protection_mode = cpu_to_le16(prot_mode);
- rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
+ memcpy(cmd->supp_rates, mwl8k_rateids, sizeof(mwl8k_rateids));
+
+ rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
return rc;
}
-static int mwl8k_cmd_set_new_stn_add_self(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
-{
- struct mwl8k_cmd_set_new_stn *cmd;
- int rc;
-
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
- if (cmd == NULL)
- return -ENOMEM;
-
- cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN);
- cmd->header.length = cpu_to_le16(sizeof(*cmd));
- memcpy(cmd->mac_addr, vif->addr, ETH_ALEN);
-
- rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
- kfree(cmd);
+/*
+ * CMD_SET_RATE.
+ */
+struct mwl8k_cmd_update_rateset {
+ struct mwl8k_cmd_pkt header;
+ __u8 legacy_rates[14];
- return rc;
-}
+ /* Bitmap for supported MCS codes. */
+ __u8 mcs_set[16];
+ __u8 reserved[16];
+} __attribute__((packed));
-static int mwl8k_cmd_set_new_stn_del(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, u8 *addr)
+static int mwl8k_update_rateset(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
- struct mwl8k_cmd_set_new_stn *cmd;
+ struct mwl8k_cmd_update_rateset *cmd;
int rc;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
- cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN);
+ cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
- memcpy(cmd->mac_addr, addr, ETH_ALEN);
- cmd->action = cpu_to_le16(MWL8K_STA_ACTION_REMOVE);
+ memcpy(cmd->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids));
- rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
+ rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
return rc;
}
/*
- * CMD_UPDATE_STADB.
+ * CMD_USE_FIXED_RATE.
*/
-struct ewc_ht_info {
- __le16 control1;
- __le16 control2;
- __le16 control3;
-} __attribute__((packed));
-
-struct peer_capability_info {
- /* Peer type - AP vs. STA. */
- __u8 peer_type;
-
- /* Basic 802.11 capabilities from assoc resp. */
- __le16 basic_caps;
-
- /* Set if peer supports 802.11n high throughput (HT). */
- __u8 ht_support;
+#define MWL8K_RATE_TABLE_SIZE 8
+#define MWL8K_UCAST_RATE 0
+#define MWL8K_USE_AUTO_RATE 0x0002
- /* Valid if HT is supported. */
- __le16 ht_caps;
- __u8 extended_ht_caps;
- struct ewc_ht_info ewc_info;
+struct mwl8k_rate_entry {
+ /* Set to 1 if HT rate, 0 if legacy. */
+ __le32 is_ht_rate;
- /* Legacy rate table. Intersection of our rates and peer rates. */
- __u8 legacy_rates[12];
+ /* Set to 1 to use retry_count field. */
+ __le32 enable_retry;
- /* HT rate table. Intersection of our rates and peer rates. */
- __u8 ht_rates[16];
- __u8 pad[16];
+ /* Specified legacy rate or MCS. */
+ __le32 rate;
- /* If set, interoperability mode, no proprietary extensions. */
- __u8 interop;
- __u8 pad2;
- __u8 station_id;
- __le16 amsdu_enabled;
+ /* Number of allowed retries. */
+ __le32 retry_count;
} __attribute__((packed));
-struct mwl8k_cmd_update_stadb {
- struct mwl8k_cmd_pkt header;
+struct mwl8k_rate_table {
+ /* 1 to allow specified rate and below */
+ __le32 allow_rate_drop;
+ __le32 num_rates;
+ struct mwl8k_rate_entry rate_entry[MWL8K_RATE_TABLE_SIZE];
+} __attribute__((packed));
- /* See STADB_ACTION_TYPE */
+struct mwl8k_cmd_use_fixed_rate {
+ struct mwl8k_cmd_pkt header;
__le32 action;
+ struct mwl8k_rate_table rate_table;
- /* Peer MAC address */
- __u8 peer_addr[ETH_ALEN];
-
- __le32 reserved;
-
- /* Peer info - valid during add/update. */
- struct peer_capability_info peer_info;
+ /* Unicast, Broadcast or Multicast */
+ __le32 rate_type;
+ __le32 reserved1;
+ __le32 reserved2;
} __attribute__((packed));
-#define MWL8K_STA_DB_MODIFY_ENTRY 1
-#define MWL8K_STA_DB_DEL_ENTRY 2
-
-/* Peer Entry flags - used to define the type of the peer node */
-#define MWL8K_PEER_TYPE_ACCESSPOINT 2
-
-static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+static int mwl8k_cmd_use_fixed_rate(struct ieee80211_hw *hw,
+ u32 action, u32 rate_type, struct mwl8k_rate_table *rate_table)
{
- struct mwl8k_cmd_update_stadb *cmd;
- struct peer_capability_info *p;
- u32 rates;
+ struct mwl8k_cmd_use_fixed_rate *cmd;
+ int count;
int rc;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
- cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB);
+ cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
- cmd->action = cpu_to_le32(MWL8K_STA_DB_MODIFY_ENTRY);
- memcpy(cmd->peer_addr, sta->addr, ETH_ALEN);
-
- p = &cmd->peer_info;
- p->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT;
- p->basic_caps = cpu_to_le16(vif->bss_conf.assoc_capability);
- p->ht_support = sta->ht_cap.ht_supported;
- p->ht_caps = sta->ht_cap.cap;
- p->extended_ht_caps = (sta->ht_cap.ampdu_factor & 3) |
- ((sta->ht_cap.ampdu_density & 7) << 2);
- if (hw->conf.channel->band == IEEE80211_BAND_2GHZ)
- rates = sta->supp_rates[IEEE80211_BAND_2GHZ];
- else
- rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5;
- legacy_rate_mask_to_array(p->legacy_rates, rates);
- memcpy(p->ht_rates, sta->ht_cap.mcs.rx_mask, 16);
- p->interop = 1;
- p->amsdu_enabled = 0;
-
- rc = mwl8k_post_cmd(hw, &cmd->header);
- kfree(cmd);
- return rc ? rc : p->station_id;
-}
+ cmd->action = cpu_to_le32(action);
+ cmd->rate_type = cpu_to_le32(rate_type);
-static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, u8 *addr)
-{
- struct mwl8k_cmd_update_stadb *cmd;
- int rc;
-
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
- if (cmd == NULL)
- return -ENOMEM;
-
- cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB);
- cmd->header.length = cpu_to_le16(sizeof(*cmd));
- cmd->action = cpu_to_le32(MWL8K_STA_DB_DEL_ENTRY);
- memcpy(cmd->peer_addr, addr, ETH_ALEN);
+ if (rate_table != NULL) {
+ /*
+ * Copy over each field manually so that endian
+ * conversion can be done.
+ */
+ cmd->rate_table.allow_rate_drop =
+ cpu_to_le32(rate_table->allow_rate_drop);
+ cmd->rate_table.num_rates =
+ cpu_to_le32(rate_table->num_rates);
+
+ for (count = 0; count < rate_table->num_rates; count++) {
+ struct mwl8k_rate_entry *dst =
+ &cmd->rate_table.rate_entry[count];
+ struct mwl8k_rate_entry *src =
+ &rate_table->rate_entry[count];
+
+ dst->is_ht_rate = cpu_to_le32(src->is_ht_rate);
+ dst->enable_retry = cpu_to_le32(src->enable_retry);
+ dst->rate = cpu_to_le32(src->rate);
+ dst->retry_count = cpu_to_le32(src->retry_count);
+ }
+ }
rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
@@ -3103,22 +2766,19 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id)
u32 status;
status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
+ iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
+
if (!status)
return IRQ_NONE;
- if (status & MWL8K_A2H_INT_TX_DONE) {
- status &= ~MWL8K_A2H_INT_TX_DONE;
- tasklet_schedule(&priv->poll_tx_task);
- }
+ if (status & MWL8K_A2H_INT_TX_DONE)
+ tasklet_schedule(&priv->tx_reclaim_task);
if (status & MWL8K_A2H_INT_RX_READY) {
- status &= ~MWL8K_A2H_INT_RX_READY;
- tasklet_schedule(&priv->poll_rx_task);
+ while (rxq_process(hw, 0, 1))
+ rxq_refill(hw, 0, 1);
}
- if (status)
- iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
-
if (status & MWL8K_A2H_INT_OPC_DONE) {
if (priv->hostcmd_wait != NULL)
complete(priv->hostcmd_wait);
@@ -3133,53 +2793,6 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static void mwl8k_tx_poll(unsigned long data)
-{
- struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
- struct mwl8k_priv *priv = hw->priv;
- int limit;
- int i;
-
- limit = 32;
-
- spin_lock_bh(&priv->tx_lock);
-
- for (i = 0; i < MWL8K_TX_QUEUES; i++)
- limit -= mwl8k_txq_reclaim(hw, i, limit, 0);
-
- if (!priv->pending_tx_pkts && priv->tx_wait != NULL) {
- complete(priv->tx_wait);
- priv->tx_wait = NULL;
- }
-
- spin_unlock_bh(&priv->tx_lock);
-
- if (limit) {
- writel(~MWL8K_A2H_INT_TX_DONE,
- priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
- } else {
- tasklet_schedule(&priv->poll_tx_task);
- }
-}
-
-static void mwl8k_rx_poll(unsigned long data)
-{
- struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
- struct mwl8k_priv *priv = hw->priv;
- int limit;
-
- limit = 32;
- limit -= rxq_process(hw, 0, limit);
- limit -= rxq_refill(hw, 0, limit);
-
- if (limit) {
- writel(~MWL8K_A2H_INT_RX_READY,
- priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
- } else {
- tasklet_schedule(&priv->poll_rx_task);
- }
-}
-
/*
* Core driver operations.
@@ -3190,7 +2803,7 @@ static int mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
int index = skb_get_queue_mapping(skb);
int rc;
- if (!priv->radio_on) {
+ if (priv->current_channel == NULL) {
printk(KERN_DEBUG "%s: dropped TX frame since radio "
"disabled\n", wiphy_name(hw->wiphy));
dev_kfree_skb(skb);
@@ -3215,20 +2828,19 @@ static int mwl8k_start(struct ieee80211_hw *hw)
return -EIO;
}
- /* Enable TX reclaim and RX tasklets. */
- tasklet_enable(&priv->poll_tx_task);
- tasklet_enable(&priv->poll_rx_task);
+ /* Enable tx reclaim tasklet */
+ tasklet_enable(&priv->tx_reclaim_task);
/* Enable interrupts */
iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
rc = mwl8k_fw_lock(hw);
if (!rc) {
- rc = mwl8k_cmd_radio_enable(hw);
+ rc = mwl8k_cmd_802_11_radio_enable(hw);
if (!priv->ap_fw) {
if (!rc)
- rc = mwl8k_cmd_enable_sniffer(hw, 0);
+ rc = mwl8k_enable_sniffer(hw, 0);
if (!rc)
rc = mwl8k_cmd_set_pre_scan(hw);
@@ -3239,10 +2851,10 @@ static int mwl8k_start(struct ieee80211_hw *hw)
}
if (!rc)
- rc = mwl8k_cmd_set_rateadapt_mode(hw, 0);
+ rc = mwl8k_cmd_setrateadaptmode(hw, 0);
if (!rc)
- rc = mwl8k_cmd_set_wmm_mode(hw, 0);
+ rc = mwl8k_set_wmm(hw, 0);
mwl8k_fw_unlock(hw);
}
@@ -3250,8 +2862,7 @@ static int mwl8k_start(struct ieee80211_hw *hw)
if (rc) {
iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
free_irq(priv->pdev->irq, hw);
- tasklet_disable(&priv->poll_tx_task);
- tasklet_disable(&priv->poll_rx_task);
+ tasklet_disable(&priv->tx_reclaim_task);
}
return rc;
@@ -3262,7 +2873,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw)
struct mwl8k_priv *priv = hw->priv;
int i;
- mwl8k_cmd_radio_disable(hw);
+ mwl8k_cmd_802_11_radio_disable(hw);
ieee80211_stop_queues(hw);
@@ -3275,27 +2886,36 @@ static void mwl8k_stop(struct ieee80211_hw *hw)
if (priv->beacon_skb != NULL)
dev_kfree_skb(priv->beacon_skb);
- /* Stop TX reclaim and RX tasklets. */
- tasklet_disable(&priv->poll_tx_task);
- tasklet_disable(&priv->poll_rx_task);
+ /* Stop tx reclaim tasklet */
+ tasklet_disable(&priv->tx_reclaim_task);
/* Return all skbs to mac80211 */
for (i = 0; i < MWL8K_TX_QUEUES; i++)
- mwl8k_txq_reclaim(hw, i, INT_MAX, 1);
+ mwl8k_txq_reclaim(hw, i, 1);
}
static int mwl8k_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct mwl8k_priv *priv = hw->priv;
struct mwl8k_vif *mwl8k_vif;
- u32 macids_supported;
- int macid;
+
+ /*
+ * We only support one active interface at a time.
+ */
+ if (priv->vif != NULL)
+ return -EBUSY;
+
+ /*
+ * We only support managed interfaces for now.
+ */
+ if (conf->type != NL80211_IFTYPE_STATION)
+ return -EINVAL;
/*
* Reject interface creation if sniffer mode is active, as
* STA operation is mutually exclusive with hardware sniffer
- * mode. (Sniffer mode is only used on STA firmware.)
+ * mode.
*/
if (priv->sniffer_enabled) {
printk(KERN_INFO "%s: unable to create STA "
@@ -3304,54 +2924,37 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
return -EINVAL;
}
+ /* Clean out driver private area */
+ mwl8k_vif = MWL8K_VIF(conf->vif);
+ memset(mwl8k_vif, 0, sizeof(*mwl8k_vif));
- switch (vif->type) {
- case NL80211_IFTYPE_AP:
- macids_supported = priv->ap_macids_supported;
- break;
- case NL80211_IFTYPE_STATION:
- macids_supported = priv->sta_macids_supported;
- break;
- default:
- return -EINVAL;
- }
+ /* Set and save the mac address */
+ mwl8k_set_mac_addr(hw, conf->mac_addr);
+ memcpy(mwl8k_vif->mac_addr, conf->mac_addr, ETH_ALEN);
- macid = ffs(macids_supported & ~priv->macids_used);
- if (!macid--)
- return -EBUSY;
+ /* Back pointer to parent config block */
+ mwl8k_vif->priv = priv;
- /* Setup driver private area. */
- mwl8k_vif = MWL8K_VIF(vif);
- memset(mwl8k_vif, 0, sizeof(*mwl8k_vif));
- mwl8k_vif->vif = vif;
- mwl8k_vif->macid = macid;
+ /* Set Initial sequence number to zero */
mwl8k_vif->seqno = 0;
- /* Set the mac address. */
- mwl8k_cmd_set_mac_addr(hw, vif, vif->addr);
-
- if (priv->ap_fw)
- mwl8k_cmd_set_new_stn_add_self(hw, vif);
-
- priv->macids_used |= 1 << mwl8k_vif->macid;
- list_add_tail(&mwl8k_vif->list, &priv->vif_list);
+ priv->vif = conf->vif;
+ priv->current_channel = NULL;
return 0;
}
static void mwl8k_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct mwl8k_priv *priv = hw->priv;
- struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
- if (priv->ap_fw)
- mwl8k_cmd_set_new_stn_del(hw, vif, vif->addr);
+ if (priv->vif == NULL)
+ return;
- mwl8k_cmd_set_mac_addr(hw, vif, "\x00\x00\x00\x00\x00\x00");
+ mwl8k_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00");
- priv->macids_used &= ~(1 << mwl8k_vif->macid);
- list_del(&mwl8k_vif->list);
+ priv->vif = NULL;
}
static int mwl8k_config(struct ieee80211_hw *hw, u32 changed)
@@ -3361,7 +2964,8 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed)
int rc;
if (conf->flags & IEEE80211_CONF_IDLE) {
- mwl8k_cmd_radio_disable(hw);
+ mwl8k_cmd_802_11_radio_disable(hw);
+ priv->current_channel = NULL;
return 0;
}
@@ -3369,17 +2973,19 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed)
if (rc)
return rc;
- rc = mwl8k_cmd_radio_enable(hw);
+ rc = mwl8k_cmd_802_11_radio_enable(hw);
if (rc)
goto out;
- rc = mwl8k_cmd_set_rf_channel(hw, conf);
+ rc = mwl8k_cmd_set_rf_channel(hw, conf->channel);
if (rc)
goto out;
+ priv->current_channel = conf->channel;
+
if (conf->power_level > 18)
conf->power_level = 18;
- rc = mwl8k_cmd_rf_tx_power(hw, conf->power_level);
+ rc = mwl8k_cmd_802_11_rf_tx_power(hw, conf->power_level);
if (rc)
goto out;
@@ -3397,160 +3003,79 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed)
return rc;
}
-static void
-mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *info, u32 changed)
+static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info,
+ u32 changed)
{
struct mwl8k_priv *priv = hw->priv;
- u32 ap_legacy_rates;
- u8 ap_mcs_rates[16];
+ struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
int rc;
- if (mwl8k_fw_lock(hw))
+ if ((changed & BSS_CHANGED_ASSOC) == 0)
return;
- /*
- * No need to capture a beacon if we're no longer associated.
- */
- if ((changed & BSS_CHANGED_ASSOC) && !vif->bss_conf.assoc)
- priv->capture_beacon = false;
-
- /*
- * Get the AP's legacy and MCS rates.
- */
- if (vif->bss_conf.assoc) {
- struct ieee80211_sta *ap;
+ priv->capture_beacon = false;
- rcu_read_lock();
+ rc = mwl8k_fw_lock(hw);
+ if (rc)
+ return;
- ap = ieee80211_find_sta(vif, vif->bss_conf.bssid);
- if (ap == NULL) {
- rcu_read_unlock();
- goto out;
- }
+ if (info->assoc) {
+ memcpy(&mwl8k_vif->bss_info, info,
+ sizeof(struct ieee80211_bss_conf));
- if (hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
- ap_legacy_rates = ap->supp_rates[IEEE80211_BAND_2GHZ];
- } else {
- ap_legacy_rates =
- ap->supp_rates[IEEE80211_BAND_5GHZ] << 5;
- }
- memcpy(ap_mcs_rates, ap->ht_cap.mcs.rx_mask, 16);
+ memcpy(mwl8k_vif->bssid, info->bssid, ETH_ALEN);
- rcu_read_unlock();
- }
+ /* Install rates */
+ rc = mwl8k_update_rateset(hw, vif);
+ if (rc)
+ goto out;
- if ((changed & BSS_CHANGED_ASSOC) && vif->bss_conf.assoc) {
- rc = mwl8k_cmd_set_rate(hw, vif, ap_legacy_rates, ap_mcs_rates);
+ /* Turn on rate adaptation */
+ rc = mwl8k_cmd_use_fixed_rate(hw, MWL8K_USE_AUTO_RATE,
+ MWL8K_UCAST_RATE, NULL);
if (rc)
goto out;
- rc = mwl8k_cmd_use_fixed_rate_sta(hw);
+ /* Set radio preamble */
+ rc = mwl8k_set_radio_preamble(hw, info->use_short_preamble);
if (rc)
goto out;
- }
- if (changed & BSS_CHANGED_ERP_PREAMBLE) {
- rc = mwl8k_set_radio_preamble(hw,
- vif->bss_conf.use_short_preamble);
+ /* Set slot time */
+ rc = mwl8k_cmd_set_slot(hw, info->use_short_slot);
if (rc)
goto out;
- }
- if (changed & BSS_CHANGED_ERP_SLOT) {
- rc = mwl8k_cmd_set_slot(hw, vif->bss_conf.use_short_slot);
+ /* Update peer rate info */
+ rc = mwl8k_cmd_update_sta_db(hw, vif,
+ MWL8K_STA_DB_MODIFY_ENTRY);
if (rc)
goto out;
- }
- if (vif->bss_conf.assoc &&
- (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_ERP_CTS_PROT |
- BSS_CHANGED_HT))) {
- rc = mwl8k_cmd_set_aid(hw, vif, ap_legacy_rates);
+ /* Set AID */
+ rc = mwl8k_cmd_set_aid(hw, vif);
if (rc)
goto out;
- }
- if (vif->bss_conf.assoc &&
- (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INT))) {
/*
* Finalize the join. Tell rx handler to process
* next beacon from our BSSID.
*/
- memcpy(priv->capture_bssid, vif->bss_conf.bssid, ETH_ALEN);
+ memcpy(priv->capture_bssid, mwl8k_vif->bssid, ETH_ALEN);
priv->capture_beacon = true;
+ } else {
+ rc = mwl8k_cmd_update_sta_db(hw, vif, MWL8K_STA_DB_DEL_ENTRY);
+ memset(&mwl8k_vif->bss_info, 0,
+ sizeof(struct ieee80211_bss_conf));
+ memset(mwl8k_vif->bssid, 0, ETH_ALEN);
}
out:
mwl8k_fw_unlock(hw);
}
-static void
-mwl8k_bss_info_changed_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *info, u32 changed)
-{
- int rc;
-
- if (mwl8k_fw_lock(hw))
- return;
-
- if (changed & BSS_CHANGED_ERP_PREAMBLE) {
- rc = mwl8k_set_radio_preamble(hw,
- vif->bss_conf.use_short_preamble);
- if (rc)
- goto out;
- }
-
- if (changed & BSS_CHANGED_BASIC_RATES) {
- int idx;
- int rate;
-
- /*
- * Use lowest supported basic rate for multicasts
- * and management frames (such as probe responses --
- * beacons will always go out at 1 Mb/s).
- */
- idx = ffs(vif->bss_conf.basic_rates);
- if (idx)
- idx--;
-
- if (hw->conf.channel->band == IEEE80211_BAND_2GHZ)
- rate = mwl8k_rates_24[idx].hw_value;
- else
- rate = mwl8k_rates_50[idx].hw_value;
-
- mwl8k_cmd_use_fixed_rate_ap(hw, rate, rate);
- }
-
- if (changed & (BSS_CHANGED_BEACON_INT | BSS_CHANGED_BEACON)) {
- struct sk_buff *skb;
-
- skb = ieee80211_beacon_get(hw, vif);
- if (skb != NULL) {
- mwl8k_cmd_set_beacon(hw, vif, skb->data, skb->len);
- kfree_skb(skb);
- }
- }
-
- if (changed & BSS_CHANGED_BEACON_ENABLED)
- mwl8k_cmd_bss_start(hw, vif, info->enable_beacon);
-
-out:
- mwl8k_fw_unlock(hw);
-}
-
-static void
-mwl8k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *info, u32 changed)
-{
- struct mwl8k_priv *priv = hw->priv;
-
- if (!priv->ap_fw)
- mwl8k_bss_info_changed_sta(hw, vif, info, changed);
- else
- mwl8k_bss_info_changed_ap(hw, vif, info, changed);
-}
-
static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw,
int mc_count, struct dev_addr_list *mclist)
{
@@ -3580,7 +3105,7 @@ mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw,
* operation, so refuse to enable sniffer mode if a STA
* interface is active.
*/
- if (!list_empty(&priv->vif_list)) {
+ if (priv->vif != NULL) {
if (net_ratelimit())
printk(KERN_INFO "%s: not enabling sniffer "
"mode because STA interface is active\n",
@@ -3589,7 +3114,7 @@ mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw,
}
if (!priv->sniffer_enabled) {
- if (mwl8k_cmd_enable_sniffer(hw, 1))
+ if (mwl8k_enable_sniffer(hw, 1))
return 0;
priv->sniffer_enabled = true;
}
@@ -3601,14 +3126,6 @@ mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw,
return 1;
}
-static struct mwl8k_vif *mwl8k_first_vif(struct mwl8k_priv *priv)
-{
- if (!list_empty(&priv->vif_list))
- return list_entry(priv->vif_list.next, struct mwl8k_vif, list);
-
- return NULL;
-}
-
static void mwl8k_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags,
unsigned int *total_flags,
@@ -3646,7 +3163,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw,
}
if (priv->sniffer_enabled) {
- mwl8k_cmd_enable_sniffer(hw, 0);
+ mwl8k_enable_sniffer(hw, 0);
priv->sniffer_enabled = false;
}
@@ -3657,8 +3174,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw,
*/
mwl8k_cmd_set_pre_scan(hw);
} else {
- struct mwl8k_vif *mwl8k_vif;
- const u8 *bssid;
+ u8 *bssid;
/*
* Enable the BSS filter.
@@ -3668,11 +3184,9 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw,
* (where the OUI part needs to be nonzero for
* the BSSID to be accepted by POST_SCAN).
*/
- mwl8k_vif = mwl8k_first_vif(priv);
- if (mwl8k_vif != NULL)
- bssid = mwl8k_vif->vif->bss_conf.bssid;
- else
- bssid = "\x01\x00\x00\x00\x00\x00";
+ bssid = "\x01\x00\x00\x00\x00\x00";
+ if (priv->vif != NULL)
+ bssid = MWL8K_VIF(priv->vif)->bssid;
mwl8k_cmd_set_post_scan(hw, bssid);
}
@@ -3699,39 +3213,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw,
static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
{
- return mwl8k_cmd_set_rts_threshold(hw, value);
-}
-
-static int mwl8k_sta_remove(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
-{
- struct mwl8k_priv *priv = hw->priv;
-
- if (priv->ap_fw)
- return mwl8k_cmd_set_new_stn_del(hw, vif, sta->addr);
- else
- return mwl8k_cmd_update_stadb_del(hw, vif, sta->addr);
-}
-
-static int mwl8k_sta_add(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
-{
- struct mwl8k_priv *priv = hw->priv;
- int ret;
-
- if (!priv->ap_fw) {
- ret = mwl8k_cmd_update_stadb_add(hw, vif, sta);
- if (ret >= 0) {
- MWL8K_STA(sta)->peer_id = ret;
- return 0;
- }
-
- return ret;
- }
-
- return mwl8k_cmd_set_new_stn_add(hw, vif, sta);
+ return mwl8k_rts_threshold(hw, MWL8K_CMD_SET, value);
}
static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue,
@@ -3743,14 +3225,14 @@ static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue,
rc = mwl8k_fw_lock(hw);
if (!rc) {
if (!priv->wmm_enabled)
- rc = mwl8k_cmd_set_wmm_mode(hw, 1);
+ rc = mwl8k_set_wmm(hw, 1);
if (!rc)
- rc = mwl8k_cmd_set_edca_params(hw, queue,
- params->cw_min,
- params->cw_max,
- params->aifs,
- params->txop);
+ rc = mwl8k_set_edca_params(hw, queue,
+ params->cw_min,
+ params->cw_max,
+ params->aifs,
+ params->txop);
mwl8k_fw_unlock(hw);
}
@@ -3758,26 +3240,28 @@ static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue,
return rc;
}
-static int mwl8k_get_stats(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats)
+static int mwl8k_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats)
{
- return mwl8k_cmd_get_stat(hw, stats);
+ struct mwl8k_priv *priv = hw->priv;
+ struct mwl8k_tx_queue *txq;
+ int index;
+
+ spin_lock_bh(&priv->tx_lock);
+ for (index = 0; index < MWL8K_TX_QUEUES; index++) {
+ txq = priv->txq + index;
+ memcpy(&stats[index], &txq->stats,
+ sizeof(struct ieee80211_tx_queue_stats));
+ }
+ spin_unlock_bh(&priv->tx_lock);
+
+ return 0;
}
-static int
-mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+static int mwl8k_get_stats(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats)
{
- switch (action) {
- case IEEE80211_AMPDU_RX_START:
- case IEEE80211_AMPDU_RX_STOP:
- if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION))
- return -ENOTSUPP;
- return 0;
- default:
- return -ENOTSUPP;
- }
+ return mwl8k_cmd_802_11_get_stat(hw, stats);
}
static const struct ieee80211_ops mwl8k_ops = {
@@ -3791,72 +3275,67 @@ static const struct ieee80211_ops mwl8k_ops = {
.prepare_multicast = mwl8k_prepare_multicast,
.configure_filter = mwl8k_configure_filter,
.set_rts_threshold = mwl8k_set_rts_threshold,
- .sta_add = mwl8k_sta_add,
- .sta_remove = mwl8k_sta_remove,
.conf_tx = mwl8k_conf_tx,
+ .get_tx_stats = mwl8k_get_tx_stats,
.get_stats = mwl8k_get_stats,
- .ampdu_action = mwl8k_ampdu_action,
};
+static void mwl8k_tx_reclaim_handler(unsigned long data)
+{
+ int i;
+ struct ieee80211_hw *hw = (struct ieee80211_hw *) data;
+ struct mwl8k_priv *priv = hw->priv;
+
+ spin_lock_bh(&priv->tx_lock);
+ for (i = 0; i < MWL8K_TX_QUEUES; i++)
+ mwl8k_txq_reclaim(hw, i, 0);
+
+ if (priv->tx_wait != NULL && !priv->pending_tx_pkts) {
+ complete(priv->tx_wait);
+ priv->tx_wait = NULL;
+ }
+ spin_unlock_bh(&priv->tx_lock);
+}
+
static void mwl8k_finalize_join_worker(struct work_struct *work)
{
struct mwl8k_priv *priv =
container_of(work, struct mwl8k_priv, finalize_join_worker);
struct sk_buff *skb = priv->beacon_skb;
- struct ieee80211_mgmt *mgmt = (void *)skb->data;
- int len = skb->len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
- const u8 *tim = cfg80211_find_ie(WLAN_EID_TIM,
- mgmt->u.beacon.variable, len);
- int dtim_period = 1;
-
- if (tim && tim[1] >= 2)
- dtim_period = tim[3];
-
- mwl8k_cmd_finalize_join(priv->hw, skb->data, skb->len, dtim_period);
+ u8 dtim = MWL8K_VIF(priv->vif)->bss_info.dtim_period;
+ mwl8k_finalize_join(priv->hw, skb->data, skb->len, dtim);
dev_kfree_skb(skb);
+
priv->beacon_skb = NULL;
}
enum {
- MWL8363 = 0,
- MWL8687,
+ MWL8687 = 0,
MWL8366,
};
static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = {
- [MWL8363] = {
- .part_name = "88w8363",
- .helper_image = "mwl8k/helper_8363.fw",
- .fw_image = "mwl8k/fmimage_8363.fw",
- },
- [MWL8687] = {
+ {
.part_name = "88w8687",
.helper_image = "mwl8k/helper_8687.fw",
.fw_image = "mwl8k/fmimage_8687.fw",
+ .rxd_ops = &rxd_8687_ops,
+ .modes = BIT(NL80211_IFTYPE_STATION),
},
- [MWL8366] = {
+ {
.part_name = "88w8366",
.helper_image = "mwl8k/helper_8366.fw",
.fw_image = "mwl8k/fmimage_8366.fw",
- .ap_rxd_ops = &rxd_8366_ap_ops,
+ .rxd_ops = &rxd_8366_ops,
+ .modes = 0,
},
};
-MODULE_FIRMWARE("mwl8k/helper_8363.fw");
-MODULE_FIRMWARE("mwl8k/fmimage_8363.fw");
-MODULE_FIRMWARE("mwl8k/helper_8687.fw");
-MODULE_FIRMWARE("mwl8k/fmimage_8687.fw");
-MODULE_FIRMWARE("mwl8k/helper_8366.fw");
-MODULE_FIRMWARE("mwl8k/fmimage_8366.fw");
-
static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
- { PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, },
- { PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, },
{ PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = MWL8687, },
{ PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = MWL8687, },
{ PCI_VDEVICE(MARVELL, 0x2a40), .driver_data = MWL8366, },
- { PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, },
{ },
};
MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table);
@@ -3875,7 +3354,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
printed_version = 1;
}
-
rc = pci_enable_device(pdev);
if (rc) {
printk(KERN_ERR "%s: Cannot enable new PCI device\n",
@@ -3892,7 +3370,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
pci_set_master(pdev);
-
hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops);
if (hw == NULL) {
printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME);
@@ -3900,14 +3377,17 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
goto err_free_reg;
}
- SET_IEEE80211_DEV(hw, &pdev->dev);
- pci_set_drvdata(pdev, hw);
-
priv = hw->priv;
priv->hw = hw;
priv->pdev = pdev;
priv->device_info = &mwl8k_info_tbl[id->driver_data];
+ priv->rxd_ops = priv->device_info->rxd_ops;
+ priv->sniffer_enabled = false;
+ priv->wmm_enabled = false;
+ priv->pending_tx_pkts = 0;
+ SET_IEEE80211_DEV(hw, &pdev->dev);
+ pci_set_drvdata(pdev, hw);
priv->sram = pci_iomap(pdev, 0, 0x10000);
if (priv->sram == NULL) {
@@ -3930,46 +3410,16 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
}
}
+ memcpy(priv->channels, mwl8k_channels, sizeof(mwl8k_channels));
+ priv->band.band = IEEE80211_BAND_2GHZ;
+ priv->band.channels = priv->channels;
+ priv->band.n_channels = ARRAY_SIZE(mwl8k_channels);
+ priv->band.bitrates = priv->rates;
+ priv->band.n_bitrates = ARRAY_SIZE(mwl8k_rates);
+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
- /* Reset firmware and hardware */
- mwl8k_hw_reset(priv);
-
- /* Ask userland hotplug daemon for the device firmware */
- rc = mwl8k_request_firmware(priv);
- if (rc) {
- printk(KERN_ERR "%s: Firmware files not found\n",
- wiphy_name(hw->wiphy));
- goto err_stop_firmware;
- }
-
- /* Load firmware into hardware */
- rc = mwl8k_load_firmware(hw);
- if (rc) {
- printk(KERN_ERR "%s: Cannot start firmware\n",
- wiphy_name(hw->wiphy));
- goto err_stop_firmware;
- }
-
- /* Reclaim memory once firmware is successfully loaded */
- mwl8k_release_firmware(priv);
-
-
- if (priv->ap_fw) {
- priv->rxd_ops = priv->device_info->ap_rxd_ops;
- if (priv->rxd_ops == NULL) {
- printk(KERN_ERR "%s: Driver does not have AP "
- "firmware image support for this hardware\n",
- wiphy_name(hw->wiphy));
- goto err_stop_firmware;
- }
- } else {
- priv->rxd_ops = &rxd_sta_ops;
- }
-
- priv->sniffer_enabled = false;
- priv->wmm_enabled = false;
- priv->pending_tx_pkts = 0;
-
+ BUILD_BUG_ON(sizeof(priv->rates) != sizeof(mwl8k_rates));
+ memcpy(priv->rates, mwl8k_rates, sizeof(mwl8k_rates));
/*
* Extra headroom is the size of the required DMA header
@@ -3982,13 +3432,12 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
hw->queues = MWL8K_TX_QUEUES;
+ hw->wiphy->interface_modes = priv->device_info->modes;
+
/* Set rssi and noise values to dBm */
hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM;
hw->vif_data_size = sizeof(struct mwl8k_vif);
- hw->sta_data_size = sizeof(struct mwl8k_sta);
-
- priv->macids_used = 0;
- INIT_LIST_HEAD(&priv->vif_list);
+ priv->vif = NULL;
/* Set default radio state and preamble */
priv->radio_on = 0;
@@ -3997,20 +3446,19 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
/* Finalize join worker */
INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker);
- /* TX reclaim and RX tasklets. */
- tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw);
- tasklet_disable(&priv->poll_tx_task);
- tasklet_init(&priv->poll_rx_task, mwl8k_rx_poll, (unsigned long)hw);
- tasklet_disable(&priv->poll_rx_task);
+ /* TX reclaim tasklet */
+ tasklet_init(&priv->tx_reclaim_task,
+ mwl8k_tx_reclaim_handler, (unsigned long)hw);
+ tasklet_disable(&priv->tx_reclaim_task);
/* Power management cookie */
priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma);
if (priv->cookie == NULL)
- goto err_stop_firmware;
+ goto err_iounmap;
rc = mwl8k_rxq_init(hw, 0);
if (rc)
- goto err_free_cookie;
+ goto err_iounmap;
rxq_refill(hw, 0, INT_MAX);
mutex_init(&priv->fw_mutex);
@@ -4030,8 +3478,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
- iowrite32(MWL8K_A2H_INT_TX_DONE | MWL8K_A2H_INT_RX_READY,
- priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL);
+ iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL);
iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);
rc = request_irq(priv->pdev->irq, mwl8k_interrupt,
@@ -4042,9 +3489,31 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
goto err_free_queues;
}
+ /* Reset firmware and hardware */
+ mwl8k_hw_reset(priv);
+
+ /* Ask userland hotplug daemon for the device firmware */
+ rc = mwl8k_request_firmware(priv);
+ if (rc) {
+ printk(KERN_ERR "%s: Firmware files not found\n",
+ wiphy_name(hw->wiphy));
+ goto err_free_irq;
+ }
+
+ /* Load firmware into hardware */
+ rc = mwl8k_load_firmware(hw);
+ if (rc) {
+ printk(KERN_ERR "%s: Cannot start firmware\n",
+ wiphy_name(hw->wiphy));
+ goto err_stop_firmware;
+ }
+
+ /* Reclaim memory once firmware is successfully loaded */
+ mwl8k_release_firmware(priv);
+
/*
* Temporarily enable interrupts. Initial firmware host
- * commands use interrupts and avoid polling. Disable
+ * commands use interrupts and avoids polling. Disable
* interrupts when done.
*/
iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
@@ -4060,29 +3529,22 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
if (rc) {
printk(KERN_ERR "%s: Cannot initialise firmware\n",
wiphy_name(hw->wiphy));
- goto err_free_irq;
+ goto err_stop_firmware;
}
- hw->wiphy->interface_modes = 0;
- if (priv->ap_macids_supported)
- hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP);
- if (priv->sta_macids_supported)
- hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION);
-
-
/* Turn radio off */
- rc = mwl8k_cmd_radio_disable(hw);
+ rc = mwl8k_cmd_802_11_radio_disable(hw);
if (rc) {
printk(KERN_ERR "%s: Cannot disable\n", wiphy_name(hw->wiphy));
- goto err_free_irq;
+ goto err_stop_firmware;
}
/* Clear MAC address */
- rc = mwl8k_cmd_set_mac_addr(hw, NULL, "\x00\x00\x00\x00\x00\x00");
+ rc = mwl8k_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00");
if (rc) {
printk(KERN_ERR "%s: Cannot clear MAC address\n",
wiphy_name(hw->wiphy));
- goto err_free_irq;
+ goto err_stop_firmware;
}
/* Disable interrupts */
@@ -4093,7 +3555,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
if (rc) {
printk(KERN_ERR "%s: Cannot register device\n",
wiphy_name(hw->wiphy));
- goto err_free_queues;
+ goto err_stop_firmware;
}
printk(KERN_INFO "%s: %s v%d, %pM, %s firmware %u.%u.%u.%u\n",
@@ -4105,6 +3567,10 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
return 0;
+err_stop_firmware:
+ mwl8k_hw_reset(priv);
+ mwl8k_release_firmware(priv);
+
err_free_irq:
iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
free_irq(priv->pdev->irq, hw);
@@ -4114,16 +3580,11 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
mwl8k_txq_deinit(hw, i);
mwl8k_rxq_deinit(hw, 0);
-err_free_cookie:
+err_iounmap:
if (priv->cookie != NULL)
pci_free_consistent(priv->pdev, 4,
priv->cookie, priv->cookie_dma);
-err_stop_firmware:
- mwl8k_hw_reset(priv);
- mwl8k_release_firmware(priv);
-
-err_iounmap:
if (priv->regs != NULL)
pci_iounmap(pdev, priv->regs);
@@ -4161,16 +3622,15 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev)
ieee80211_unregister_hw(hw);
- /* Remove TX reclaim and RX tasklets. */
- tasklet_kill(&priv->poll_tx_task);
- tasklet_kill(&priv->poll_rx_task);
+ /* Remove tx reclaim tasklet */
+ tasklet_kill(&priv->tx_reclaim_task);
/* Stop hardware */
mwl8k_hw_reset(priv);
/* Return all skbs to mac80211 */
for (i = 0; i < MWL8K_TX_QUEUES; i++)
- mwl8k_txq_reclaim(hw, i, INT_MAX, 1);
+ mwl8k_txq_reclaim(hw, i, 1);
for (i = 0; i < MWL8K_TX_QUEUES; i++)
mwl8k_txq_deinit(hw, i);
diff --git a/trunk/drivers/net/wireless/orinoco/orinoco_cs.c b/trunk/drivers/net/wireless/orinoco/orinoco_cs.c
index 1d4ada188eda..f27bb8367c98 100644
--- a/trunk/drivers/net/wireless/orinoco/orinoco_cs.c
+++ b/trunk/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -407,6 +407,7 @@ static struct pcmcia_device_id orinoco_cs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5),
PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2),
+ PCMCIA_DEVICE_PROD_ID123("AIRVAST", "IEEE 802.11b Wireless PCMCIA Card", "HFA3863", 0xea569531, 0x4bcb9645, 0x355cb092),
PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),
PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842),
PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e),
@@ -416,6 +417,7 @@ static struct pcmcia_device_id orinoco_cs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18),
PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b),
+ PCMCIA_DEVICE_PROD_ID123("corega", "WL PCCL-11", "ISL37300P", 0x0a21501a, 0x59868926, 0xc9049a39),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
@@ -430,6 +432,7 @@ static struct pcmcia_device_id orinoco_cs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18),
PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77),
PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf),
+ PCMCIA_DEVICE_PROD_ID123("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", 0x4b801a17, 0xf222ec2d, 0x630d52b2),
PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92),
PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395),
PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
@@ -442,6 +445,7 @@ static struct pcmcia_device_id orinoco_cs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767),
PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6),
PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed),
+ PCMCIA_DEVICE_PROD_ID123("PCMCIA", "11M WLAN Card v2.5", "ISL37300P", 0x281f1c5d, 0x6e440487, 0xc9049a39),
PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264),
PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178),
PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
@@ -450,11 +454,8 @@ static struct pcmcia_device_id orinoco_cs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757),
PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a),
PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
+ PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39),
PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee),
- PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092),
- PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2),
- PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b),
- PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39),
PCMCIA_DEVICE_NULL,
};
MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids);
diff --git a/trunk/drivers/net/wireless/p54/main.c b/trunk/drivers/net/wireless/p54/main.c
index 4f752a21495f..18012dbfb45d 100644
--- a/trunk/drivers/net/wireless/p54/main.c
+++ b/trunk/drivers/net/wireless/p54/main.c
@@ -33,29 +33,21 @@ MODULE_DESCRIPTION("Softmac Prism54 common code");
MODULE_LICENSE("GPL");
MODULE_ALIAS("prism54common");
-static int p54_sta_add_remove(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
-{
- struct p54_common *priv = hw->priv;
-
- /*
- * Notify the firmware that we don't want or we don't
- * need to buffer frames for this station anymore.
- */
-
- p54_sta_unlock(priv, sta->addr);
-
- return 0;
-}
-
static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
enum sta_notify_cmd notify_cmd,
struct ieee80211_sta *sta)
{
struct p54_common *priv = dev->priv;
-
switch (notify_cmd) {
+ case STA_NOTIFY_ADD:
+ case STA_NOTIFY_REMOVE:
+ /*
+ * Notify the firmware that we don't want or we don't
+ * need to buffer frames for this station anymore.
+ */
+
+ p54_sta_unlock(priv, sta->addr);
+ break;
case STA_NOTIFY_AWAKE:
/* update the firmware's filter table */
p54_sta_unlock(priv, sta->addr);
@@ -224,7 +216,7 @@ static void p54_stop(struct ieee80211_hw *dev)
}
static int p54_add_interface(struct ieee80211_hw *dev,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct p54_common *priv = dev->priv;
@@ -234,28 +226,28 @@ static int p54_add_interface(struct ieee80211_hw *dev,
return -EOPNOTSUPP;
}
- priv->vif = vif;
+ priv->vif = conf->vif;
- switch (vif->type) {
+ switch (conf->type) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
- priv->mode = vif->type;
+ priv->mode = conf->type;
break;
default:
mutex_unlock(&priv->conf_mutex);
return -EOPNOTSUPP;
}
- memcpy(priv->mac_addr, vif->addr, ETH_ALEN);
+ memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
p54_setup_mac(priv);
mutex_unlock(&priv->conf_mutex);
return 0;
}
static void p54_remove_interface(struct ieee80211_hw *dev,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct p54_common *priv = dev->priv;
@@ -366,6 +358,16 @@ static int p54_get_stats(struct ieee80211_hw *dev,
return 0;
}
+static int p54_get_tx_stats(struct ieee80211_hw *dev,
+ struct ieee80211_tx_queue_stats *stats)
+{
+ struct p54_common *priv = dev->priv;
+
+ memcpy(stats, &priv->tx_stats[P54_QUEUE_DATA],
+ sizeof(stats[0]) * dev->queues);
+ return 0;
+}
+
static void p54_bss_info_changed(struct ieee80211_hw *dev,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info,
@@ -514,14 +516,13 @@ static const struct ieee80211_ops p54_ops = {
.remove_interface = p54_remove_interface,
.set_tim = p54_set_tim,
.sta_notify = p54_sta_notify,
- .sta_add = p54_sta_add_remove,
- .sta_remove = p54_sta_add_remove,
.set_key = p54_set_key,
.config = p54_config,
.bss_info_changed = p54_bss_info_changed,
.configure_filter = p54_configure_filter,
.conf_tx = p54_conf_tx,
.get_stats = p54_get_stats,
+ .get_tx_stats = p54_get_tx_stats
};
struct ieee80211_hw *p54_init_common(size_t priv_data_len)
diff --git a/trunk/drivers/net/wireless/p54/p54.h b/trunk/drivers/net/wireless/p54/p54.h
index 43a3b2ead81a..1afc39410e85 100644
--- a/trunk/drivers/net/wireless/p54/p54.h
+++ b/trunk/drivers/net/wireless/p54/p54.h
@@ -157,12 +157,6 @@ struct p54_led_dev {
#endif /* CONFIG_P54_LEDS */
-struct p54_tx_queue_stats {
- unsigned int len;
- unsigned int limit;
- unsigned int count;
-};
-
struct p54_common {
struct ieee80211_hw *hw;
struct ieee80211_vif *vif;
@@ -189,7 +183,7 @@ struct p54_common {
/* (e)DCF / QOS state */
bool use_short_slot;
spinlock_t tx_stats_lock;
- struct p54_tx_queue_stats tx_stats[8];
+ struct ieee80211_tx_queue_stats tx_stats[8];
struct p54_edcf_queue_param qos_params[8];
/* Radio data */
diff --git a/trunk/drivers/net/wireless/p54/p54pci.c b/trunk/drivers/net/wireless/p54/p54pci.c
index bda29c00f3ef..a72f7c2577de 100644
--- a/trunk/drivers/net/wireless/p54/p54pci.c
+++ b/trunk/drivers/net/wireless/p54/p54pci.c
@@ -157,14 +157,6 @@ static void p54p_refill_rx_ring(struct ieee80211_hw *dev,
skb_tail_pointer(skb),
priv->common.rx_mtu + 32,
PCI_DMA_FROMDEVICE);
-
- if (pci_dma_mapping_error(priv->pdev, mapping)) {
- dev_kfree_skb_any(skb);
- dev_err(&priv->pdev->dev,
- "RX DMA Mapping error\n");
- break;
- }
-
desc->host_addr = cpu_to_le32(mapping);
desc->device_addr = 0; // FIXME: necessary?
desc->len = cpu_to_le16(priv->common.rx_mtu + 32);
@@ -234,14 +226,14 @@ static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index,
p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf);
}
+/* caller must hold priv->lock */
static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
int ring_index, struct p54p_desc *ring, u32 ring_limit,
- struct sk_buff **tx_buf)
+ void **tx_buf)
{
struct p54p_priv *priv = dev->priv;
struct p54p_ring_control *ring_control = priv->ring_control;
struct p54p_desc *desc;
- struct sk_buff *skb;
u32 idx, i;
i = (*index) % ring_limit;
@@ -250,8 +242,9 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
while (i != idx) {
desc = &ring[i];
-
- skb = tx_buf[i];
+ if (tx_buf[i])
+ if (FREE_AFTER_TX((struct sk_buff *) tx_buf[i]))
+ p54_free_skb(dev, tx_buf[i]);
tx_buf[i] = NULL;
pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
@@ -262,28 +255,17 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
desc->len = 0;
desc->flags = 0;
- if (skb && FREE_AFTER_TX(skb))
- p54_free_skb(dev, skb);
-
i++;
i %= ring_limit;
}
}
-static void p54p_tasklet(unsigned long dev_id)
+static void p54p_rx_tasklet(unsigned long dev_id)
{
struct ieee80211_hw *dev = (struct ieee80211_hw *)dev_id;
struct p54p_priv *priv = dev->priv;
struct p54p_ring_control *ring_control = priv->ring_control;
- p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt,
- ARRAY_SIZE(ring_control->tx_mgmt),
- priv->tx_buf_mgmt);
-
- p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data,
- ARRAY_SIZE(ring_control->tx_data),
- priv->tx_buf_data);
-
p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt,
ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt);
@@ -298,49 +280,59 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id)
{
struct ieee80211_hw *dev = dev_id;
struct p54p_priv *priv = dev->priv;
+ struct p54p_ring_control *ring_control = priv->ring_control;
__le32 reg;
+ spin_lock(&priv->lock);
reg = P54P_READ(int_ident);
if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) {
- goto out;
+ spin_unlock(&priv->lock);
+ return IRQ_HANDLED;
}
+
P54P_WRITE(int_ack, reg);
reg &= P54P_READ(int_enable);
- if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE))
- tasklet_schedule(&priv->tasklet);
- else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
+ if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) {
+ p54p_check_tx_ring(dev, &priv->tx_idx_mgmt,
+ 3, ring_control->tx_mgmt,
+ ARRAY_SIZE(ring_control->tx_mgmt),
+ priv->tx_buf_mgmt);
+
+ p54p_check_tx_ring(dev, &priv->tx_idx_data,
+ 1, ring_control->tx_data,
+ ARRAY_SIZE(ring_control->tx_data),
+ priv->tx_buf_data);
+
+ tasklet_schedule(&priv->rx_tasklet);
+
+ } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
complete(&priv->boot_comp);
-out:
+ spin_unlock(&priv->lock);
+
return reg ? IRQ_HANDLED : IRQ_NONE;
}
static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
{
- unsigned long flags;
struct p54p_priv *priv = dev->priv;
struct p54p_ring_control *ring_control = priv->ring_control;
+ unsigned long flags;
struct p54p_desc *desc;
dma_addr_t mapping;
u32 device_idx, idx, i;
spin_lock_irqsave(&priv->lock, flags);
+
device_idx = le32_to_cpu(ring_control->device_idx[1]);
idx = le32_to_cpu(ring_control->host_idx[1]);
i = idx % ARRAY_SIZE(ring_control->tx_data);
+ priv->tx_buf_data[i] = skb;
mapping = pci_map_single(priv->pdev, skb->data, skb->len,
PCI_DMA_TODEVICE);
- if (pci_dma_mapping_error(priv->pdev, mapping)) {
- spin_unlock_irqrestore(&priv->lock, flags);
- p54_free_skb(dev, skb);
- dev_err(&priv->pdev->dev, "TX DMA mapping error\n");
- return ;
- }
- priv->tx_buf_data[i] = skb;
-
desc = &ring_control->tx_data[i];
desc->host_addr = cpu_to_le32(mapping);
desc->device_addr = ((struct p54_hdr *)skb->data)->req_id;
@@ -362,14 +354,14 @@ static void p54p_stop(struct ieee80211_hw *dev)
unsigned int i;
struct p54p_desc *desc;
+ tasklet_kill(&priv->rx_tasklet);
+
P54P_WRITE(int_enable, cpu_to_le32(0));
P54P_READ(int_enable);
udelay(10);
free_irq(priv->pdev->irq, dev);
- tasklet_kill(&priv->tasklet);
-
P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
for (i = 0; i < ARRAY_SIZE(priv->rx_buf_data); i++) {
@@ -553,7 +545,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
priv->common.tx = p54p_tx;
spin_lock_init(&priv->lock);
- tasklet_init(&priv->tasklet, p54p_tasklet, (unsigned long)dev);
+ tasklet_init(&priv->rx_tasklet, p54p_rx_tasklet, (unsigned long)dev);
err = request_firmware(&priv->firmware, "isl3886pci",
&priv->pdev->dev);
diff --git a/trunk/drivers/net/wireless/p54/p54pci.h b/trunk/drivers/net/wireless/p54/p54pci.h
index 2feead617a3b..fbb683953fb2 100644
--- a/trunk/drivers/net/wireless/p54/p54pci.h
+++ b/trunk/drivers/net/wireless/p54/p54pci.h
@@ -92,7 +92,7 @@ struct p54p_priv {
struct p54_common common;
struct pci_dev *pdev;
struct p54p_csr __iomem *map;
- struct tasklet_struct tasklet;
+ struct tasklet_struct rx_tasklet;
const struct firmware *firmware;
spinlock_t lock;
struct p54p_ring_control *ring_control;
@@ -101,8 +101,8 @@ struct p54p_priv {
u32 rx_idx_mgmt, tx_idx_mgmt;
struct sk_buff *rx_buf_data[8];
struct sk_buff *rx_buf_mgmt[4];
- struct sk_buff *tx_buf_data[32];
- struct sk_buff *tx_buf_mgmt[4];
+ void *tx_buf_data[32];
+ void *tx_buf_mgmt[4];
struct completion boot_comp;
};
diff --git a/trunk/drivers/net/wireless/p54/p54usb.c b/trunk/drivers/net/wireless/p54/p54usb.c
index b3c4fbd80d8d..92af9b96bb7a 100644
--- a/trunk/drivers/net/wireless/p54/p54usb.c
+++ b/trunk/drivers/net/wireless/p54/p54usb.c
@@ -36,7 +36,6 @@ static struct usb_device_id p54u_table[] __devinitdata = {
/* Version 1 devices (pci chip + net2280) */
{USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */
{USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */
- {USB_DEVICE(0x07aa, 0x001c)}, /* Corega CG-WLUSB2GT */
{USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */
{USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */
{USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */
@@ -61,7 +60,6 @@ static struct usb_device_id p54u_table[] __devinitdata = {
{USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */
{USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
{USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
- {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */
{USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
{USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */
{USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */
diff --git a/trunk/drivers/net/wireless/p54/txrx.c b/trunk/drivers/net/wireless/p54/txrx.c
index 66057999a93c..b6dda2b27fb5 100644
--- a/trunk/drivers/net/wireless/p54/txrx.c
+++ b/trunk/drivers/net/wireless/p54/txrx.c
@@ -183,10 +183,10 @@ static int p54_tx_qos_accounting_alloc(struct p54_common *priv,
struct sk_buff *skb,
const u16 p54_queue)
{
- struct p54_tx_queue_stats *queue;
+ struct ieee80211_tx_queue_stats *queue;
unsigned long flags;
- if (WARN_ON(p54_queue >= P54_QUEUE_NUM))
+ if (WARN_ON(p54_queue > P54_QUEUE_NUM))
return -EINVAL;
queue = &priv->tx_stats[p54_queue];
diff --git a/trunk/drivers/net/wireless/rndis_wlan.c b/trunk/drivers/net/wireless/rndis_wlan.c
index 305c106fdc1c..2ecbedb26e15 100644
--- a/trunk/drivers/net/wireless/rndis_wlan.c
+++ b/trunk/drivers/net/wireless/rndis_wlan.c
@@ -2594,9 +2594,23 @@ static void rndis_device_poller(struct work_struct *work)
/*
* driver/device initialization
*/
-static void rndis_copy_module_params(struct usbnet *usbdev)
+static int bcm4320a_early_init(struct usbnet *usbdev)
+{
+ /* bcm4320a doesn't handle configuration parameters well. Try
+ * set any and you get partially zeroed mac and broken device.
+ */
+
+ return 0;
+}
+
+static int bcm4320b_early_init(struct usbnet *usbdev)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
+ char buf[8];
+
+ /* Early initialization settings, setting these won't have effect
+ * if called after generic_rndis_bind().
+ */
priv->param_country[0] = modparam_country[0];
priv->param_country[1] = modparam_country[1];
@@ -2638,32 +2652,6 @@ static void rndis_copy_module_params(struct usbnet *usbdev)
priv->param_workaround_interval = 500;
else
priv->param_workaround_interval = modparam_workaround_interval;
-}
-
-static int bcm4320a_early_init(struct usbnet *usbdev)
-{
- /* copy module parameters for bcm4320a so that iwconfig reports txpower
- * and workaround parameter is copied to private structure correctly.
- */
- rndis_copy_module_params(usbdev);
-
- /* bcm4320a doesn't handle configuration parameters well. Try
- * set any and you get partially zeroed mac and broken device.
- */
-
- return 0;
-}
-
-static int bcm4320b_early_init(struct usbnet *usbdev)
-{
- struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
- char buf[8];
-
- rndis_copy_module_params(usbdev);
-
- /* Early initialization settings, setting these won't have effect
- * if called after generic_rndis_bind().
- */
rndis_set_config_parameter_str(usbdev, "Country", priv->param_country);
rndis_set_config_parameter_str(usbdev, "FrameBursting",
diff --git a/trunk/drivers/net/wireless/rt2x00/Kconfig b/trunk/drivers/net/wireless/rt2x00/Kconfig
index 5239e082cd0f..bf60689aaabb 100644
--- a/trunk/drivers/net/wireless/rt2x00/Kconfig
+++ b/trunk/drivers/net/wireless/rt2x00/Kconfig
@@ -54,17 +54,17 @@ config RT61PCI
When compiled as a module, this driver will be called rt61pci.
config RT2800PCI_PCI
- boolean
+ tristate
depends on PCI
default y
config RT2800PCI_SOC
- boolean
+ tristate
depends on RALINK_RT288X || RALINK_RT305X
default y
config RT2800PCI
- tristate "Ralink rt28xx/rt30xx/rt35xx (PCI/PCIe/PCMCIA) support (EXPERIMENTAL)"
+ tristate "Ralink rt2800 (PCI/PCMCIA) support (VERY EXPERIMENTAL)"
depends on (RT2800PCI_PCI || RT2800PCI_SOC) && EXPERIMENTAL
select RT2800_LIB
select RT2X00_LIB_PCI if RT2800PCI_PCI
@@ -75,7 +75,7 @@ config RT2800PCI
select CRC_CCITT
select EEPROM_93CX6
---help---
- This adds support for rt2800/rt3000/rt3500 wireless chipset family.
+ This adds support for rt2800 wireless chipset family.
Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890 & RT3052
This driver is non-functional at the moment and is intended for
@@ -83,32 +83,6 @@ config RT2800PCI
When compiled as a module, this driver will be called "rt2800pci.ko".
-if RT2800PCI
-
-config RT2800PCI_RT30XX
- bool "rt2800pci - Include support for rt30xx (PCI/PCIe/PCMCIA) devices"
- default n
- ---help---
- This adds support for rt30xx wireless chipset family to the
- rt2800pci driver.
- Supported chips: RT3090, RT3091 & RT3092
-
- Support for these devices is non-functional at the moment and is
- intended for testers and developers.
-
-config RT2800PCI_RT35XX
- bool "rt2800pci - Include support for rt35xx (PCI/PCIe/PCMCIA) devices"
- default n
- ---help---
- This adds support for rt35xx wireless chipset family to the
- rt2800pci driver.
- Supported chips: RT3060, RT3062, RT3562, RT3592
-
- Support for these devices is non-functional at the moment and is
- intended for testers and developers.
-
-endif
-
config RT2500USB
tristate "Ralink rt2500 (USB) support"
depends on USB
@@ -152,43 +126,6 @@ config RT2800USB
When compiled as a module, this driver will be called "rt2800usb.ko".
-if RT2800USB
-
-config RT2800USB_RT30XX
- bool "rt2800usb - Include support for rt30xx (USB) devices"
- default n
- ---help---
- This adds support for rt30xx wireless chipset family to the
- rt2800usb driver.
- Supported chips: RT3070, RT3071 & RT3072
-
- Support for these devices is non-functional at the moment and is
- intended for testers and developers.
-
-config RT2800USB_RT35XX
- bool "rt2800usb - Include support for rt35xx (USB) devices"
- default n
- ---help---
- This adds support for rt35xx wireless chipset family to the
- rt2800usb driver.
- Supported chips: RT3572
-
- Support for these devices is non-functional at the moment and is
- intended for testers and developers.
-
-config RT2800USB_UNKNOWN
- bool "rt2800usb - Include support for unknown (USB) devices"
- default n
- ---help---
- This adds support for rt2800 family devices that are known to
- have a rt2800 family chipset, but for which the exact chipset
- is unknown.
-
- Support status for these devices is unknown, and enabling these
- devices may or may not work.
-
-endif
-
config RT2800_LIB
tristate
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2400pci.c b/trunk/drivers/net/wireless/rt2x00/rt2400pci.c
index 676814d3a81b..e7f46405a418 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/trunk/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -451,7 +451,7 @@ static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,
/*
* RF2420 chipset don't need any additional actions.
*/
- if (rt2x00_rf(rt2x00dev, RF2420))
+ if (rt2x00_rf(&rt2x00dev->chip, RF2420))
return;
/*
@@ -1340,10 +1340,11 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
rt2x00pci_register_read(rt2x00dev, CSR0, ®);
- rt2x00_set_chip(rt2x00dev, RT2460, value,
- rt2x00_get_field32(reg, CSR0_REVISION));
+ rt2x00_set_chip_rf(rt2x00dev, value, reg);
+ rt2x00_print_chip(rt2x00dev);
- if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) {
+ if (!rt2x00_rf(&rt2x00dev->chip, RF2420) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF2421)) {
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
return -ENODEV;
}
@@ -1561,6 +1562,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
.get_stats = rt2x00mac_get_stats,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2400pci_conf_tx,
+ .get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt2400pci_get_tsf,
.tx_last_beacon = rt2400pci_tx_last_beacon,
.rfkill_poll = rt2x00mac_rfkill_poll,
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2400pci.h b/trunk/drivers/net/wireless/rt2x00/rt2400pci.h
index 606137738848..6c21ef66dfe0 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2400pci.h
+++ b/trunk/drivers/net/wireless/rt2x00/rt2400pci.h
@@ -65,7 +65,6 @@
* CSR0: ASIC revision number.
*/
#define CSR0 0x0000
-#define CSR0_REVISION FIELD32(0x0000ffff)
/*
* CSR1: System control register.
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2500pci.c b/trunk/drivers/net/wireless/rt2x00/rt2500pci.c
index c71266142ae9..408fcfc120f5 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/trunk/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -440,7 +440,8 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
/*
* RT2525E and RT5222 need to flip TX I/Q
*/
- if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) {
+ if (rt2x00_rf(&rt2x00dev->chip, RF2525E) ||
+ rt2x00_rf(&rt2x00dev->chip, RF5222)) {
rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1);
rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 1);
rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 1);
@@ -448,7 +449,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
/*
* RT2525E does not need RX I/Q Flip.
*/
- if (rt2x00_rf(rt2x00dev, RF2525E))
+ if (rt2x00_rf(&rt2x00dev->chip, RF2525E))
rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0);
} else {
rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 0);
@@ -474,14 +475,14 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
* Switch on tuning bits.
* For RT2523 devices we do not need to update the R1 register.
*/
- if (!rt2x00_rf(rt2x00dev, RF2523))
+ if (!rt2x00_rf(&rt2x00dev->chip, RF2523))
rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1);
rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1);
/*
* For RT2525 we should first set the channel to half band higher.
*/
- if (rt2x00_rf(rt2x00dev, RF2525)) {
+ if (rt2x00_rf(&rt2x00dev->chip, RF2525)) {
static const u32 vals[] = {
0x00080cbe, 0x00080d02, 0x00080d06, 0x00080d0a,
0x00080d0e, 0x00080d12, 0x00080d16, 0x00080d1a,
@@ -515,7 +516,7 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
* Switch off tuning bits.
* For RT2523 devices we do not need to update the R1 register.
*/
- if (!rt2x00_rf(rt2x00dev, RF2523)) {
+ if (!rt2x00_rf(&rt2x00dev->chip, RF2523)) {
rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0);
rt2500pci_rf_write(rt2x00dev, 1, rf->rf1);
}
@@ -639,7 +640,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev,
* up to version C the link tuning should halt after 20
* seconds while being associated.
*/
- if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D &&
+ if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D &&
rt2x00dev->intf_associated && count > 20)
return;
@@ -649,7 +650,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev,
* should go straight to dynamic CCA tuning when they
* are not associated.
*/
- if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D ||
+ if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D ||
!rt2x00dev->intf_associated)
goto dynamic_cca_tune;
@@ -1503,15 +1504,15 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
rt2x00pci_register_read(rt2x00dev, CSR0, ®);
- rt2x00_set_chip(rt2x00dev, RT2560, value,
- rt2x00_get_field32(reg, CSR0_REVISION));
-
- if (!rt2x00_rf(rt2x00dev, RF2522) &&
- !rt2x00_rf(rt2x00dev, RF2523) &&
- !rt2x00_rf(rt2x00dev, RF2524) &&
- !rt2x00_rf(rt2x00dev, RF2525) &&
- !rt2x00_rf(rt2x00dev, RF2525E) &&
- !rt2x00_rf(rt2x00dev, RF5222)) {
+ rt2x00_set_chip_rf(rt2x00dev, value, reg);
+ rt2x00_print_chip(rt2x00dev);
+
+ if (!rt2x00_rf(&rt2x00dev->chip, RF2522) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF2523) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF2524) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF2525) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF2525E) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF5222)) {
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
return -ENODEV;
}
@@ -1743,22 +1744,22 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
spec->supported_bands = SUPPORT_BAND_2GHZ;
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
- if (rt2x00_rf(rt2x00dev, RF2522)) {
+ if (rt2x00_rf(&rt2x00dev->chip, RF2522)) {
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522);
spec->channels = rf_vals_bg_2522;
- } else if (rt2x00_rf(rt2x00dev, RF2523)) {
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF2523)) {
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523);
spec->channels = rf_vals_bg_2523;
- } else if (rt2x00_rf(rt2x00dev, RF2524)) {
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF2524)) {
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524);
spec->channels = rf_vals_bg_2524;
- } else if (rt2x00_rf(rt2x00dev, RF2525)) {
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF2525)) {
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525);
spec->channels = rf_vals_bg_2525;
- } else if (rt2x00_rf(rt2x00dev, RF2525E)) {
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) {
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
spec->channels = rf_vals_bg_2525e;
- } else if (rt2x00_rf(rt2x00dev, RF5222)) {
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) {
spec->supported_bands |= SUPPORT_BAND_5GHZ;
spec->num_channels = ARRAY_SIZE(rf_vals_5222);
spec->channels = rf_vals_5222;
@@ -1859,6 +1860,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
.get_stats = rt2x00mac_get_stats,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2x00mac_conf_tx,
+ .get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt2500pci_get_tsf,
.tx_last_beacon = rt2500pci_tx_last_beacon,
.rfkill_poll = rt2x00mac_rfkill_poll,
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2500pci.h b/trunk/drivers/net/wireless/rt2x00/rt2500pci.h
index 6471f8e74b35..b0075674c09b 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2500pci.h
+++ b/trunk/drivers/net/wireless/rt2x00/rt2500pci.h
@@ -76,7 +76,6 @@
* CSR0: ASIC revision number.
*/
#define CSR0 0x0000
-#define CSR0_REVISION FIELD32(0x0000ffff)
/*
* CSR1: System control register.
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2500usb.c b/trunk/drivers/net/wireless/rt2x00/rt2500usb.c
index ee34c137e7cd..83f2592c59de 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/trunk/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -565,7 +565,8 @@ static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev,
/*
* RT2525E and RT5222 need to flip TX I/Q
*/
- if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) {
+ if (rt2x00_rf(&rt2x00dev->chip, RF2525E) ||
+ rt2x00_rf(&rt2x00dev->chip, RF5222)) {
rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1);
rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 1);
rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 1);
@@ -573,7 +574,7 @@ static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev,
/*
* RT2525E does not need RX I/Q Flip.
*/
- if (rt2x00_rf(rt2x00dev, RF2525E))
+ if (rt2x00_rf(&rt2x00dev->chip, RF2525E))
rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0);
} else {
rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 0);
@@ -597,7 +598,7 @@ static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev,
/*
* For RT2525E we should first set the channel to half band higher.
*/
- if (rt2x00_rf(rt2x00dev, RF2525E)) {
+ if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) {
static const u32 vals[] = {
0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2,
0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba,
@@ -792,7 +793,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 1);
rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
- if (rt2x00_rev(rt2x00dev) >= RT2570_VERSION_C) {
+ if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) {
rt2500usb_register_read(rt2x00dev, PHY_CSR2, ®);
rt2x00_set_field16(®, PHY_CSR2_LNA, 0);
} else {
@@ -1408,18 +1409,21 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
rt2500usb_register_read(rt2x00dev, MAC_CSR0, ®);
rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
+ rt2x00_print_chip(rt2x00dev);
+
+ if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0) ||
+ rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) {
- if (((reg & 0xfff0) != 0) || ((reg & 0x0000000f) == 0)) {
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
return -ENODEV;
}
- if (!rt2x00_rf(rt2x00dev, RF2522) &&
- !rt2x00_rf(rt2x00dev, RF2523) &&
- !rt2x00_rf(rt2x00dev, RF2524) &&
- !rt2x00_rf(rt2x00dev, RF2525) &&
- !rt2x00_rf(rt2x00dev, RF2525E) &&
- !rt2x00_rf(rt2x00dev, RF5222)) {
+ if (!rt2x00_rf(&rt2x00dev->chip, RF2522) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF2523) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF2524) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF2525) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF2525E) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF5222)) {
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
return -ENODEV;
}
@@ -1663,22 +1667,22 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
spec->supported_bands = SUPPORT_BAND_2GHZ;
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
- if (rt2x00_rf(rt2x00dev, RF2522)) {
+ if (rt2x00_rf(&rt2x00dev->chip, RF2522)) {
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522);
spec->channels = rf_vals_bg_2522;
- } else if (rt2x00_rf(rt2x00dev, RF2523)) {
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF2523)) {
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523);
spec->channels = rf_vals_bg_2523;
- } else if (rt2x00_rf(rt2x00dev, RF2524)) {
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF2524)) {
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524);
spec->channels = rf_vals_bg_2524;
- } else if (rt2x00_rf(rt2x00dev, RF2525)) {
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF2525)) {
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525);
spec->channels = rf_vals_bg_2525;
- } else if (rt2x00_rf(rt2x00dev, RF2525E)) {
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) {
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
spec->channels = rf_vals_bg_2525e;
- } else if (rt2x00_rf(rt2x00dev, RF5222)) {
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) {
spec->supported_bands |= SUPPORT_BAND_5GHZ;
spec->num_channels = ARRAY_SIZE(rf_vals_5222);
spec->channels = rf_vals_5222;
@@ -1759,6 +1763,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
.get_stats = rt2x00mac_get_stats,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2x00mac_conf_tx,
+ .get_tx_stats = rt2x00mac_get_tx_stats,
.rfkill_poll = rt2x00mac_rfkill_poll,
};
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800.h b/trunk/drivers/net/wireless/rt2x00/rt2800.h
index 74c0433dba37..1a7eae357fef 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2800.h
+++ b/trunk/drivers/net/wireless/rt2x00/rt2800.h
@@ -60,11 +60,11 @@
/*
* Chipset version.
*/
-#define RT2860C_VERSION 0x0100
-#define RT2860D_VERSION 0x0101
-#define RT2880E_VERSION 0x0200
-#define RT2883_VERSION 0x0300
-#define RT3070_VERSION 0x0200
+#define RT2860C_VERSION 0x28600100
+#define RT2860D_VERSION 0x28600101
+#define RT2880E_VERSION 0x28720200
+#define RT2883_VERSION 0x28830300
+#define RT3070_VERSION 0x30700200
/*
* Signal information.
@@ -408,8 +408,8 @@
* ASIC_VER: 2860 or 2870
*/
#define MAC_CSR0 0x1000
-#define MAC_CSR0_REVISION FIELD32(0x0000ffff)
-#define MAC_CSR0_CHIPSET FIELD32(0xffff0000)
+#define MAC_CSR0_ASIC_REV FIELD32(0x0000ffff)
+#define MAC_CSR0_ASIC_VER FIELD32(0xffff0000)
/*
* MAC_SYS_CTRL:
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c
index 18d4d8e4ae6b..9deae41cb784 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -37,12 +37,9 @@
#include
#include "rt2x00.h"
-#if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE)
+#if defined(CONFIG_RT2800USB) || defined(CONFIG_RT2800USB_MODULE)
#include "rt2x00usb.h"
#endif
-#if defined(CONFIG_RT2X00_LIB_PCI) || defined(CONFIG_RT2X00_LIB_PCI_MODULE)
-#include "rt2x00pci.h"
-#endif
#include "rt2800lib.h"
#include "rt2800.h"
#include "rt2800usb.h"
@@ -92,7 +89,7 @@ static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word);
rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1);
rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0);
- if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
+ if (rt2x00_intf_is_pci(rt2x00dev))
rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1);
rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
@@ -121,7 +118,7 @@ static void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word);
rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1);
rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1);
- if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
+ if (rt2x00_intf_is_pci(rt2x00dev))
rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1);
rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
@@ -221,9 +218,10 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
u32 reg;
/*
- * SOC devices don't support MCU requests.
+ * RT2880 and RT3052 don't support MCU requests.
*/
- if (rt2x00_is_soc(rt2x00dev))
+ if (rt2x00_rt(&rt2x00dev->chip, RT2880) ||
+ rt2x00_rt(&rt2x00dev->chip, RT3052))
return;
mutex_lock(&rt2x00dev->csr_mutex);
@@ -248,25 +246,6 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
}
EXPORT_SYMBOL_GPL(rt2800_mcu_request);
-int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
-{
- unsigned int i;
- u32 reg;
-
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®);
- if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
- !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY))
- return 0;
-
- msleep(1);
- }
-
- ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n");
- return -EACCES;
-}
-EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready);
-
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
const struct rt2x00debug rt2800_rt2x00debug = {
.owner = THIS_MODULE,
@@ -369,7 +348,7 @@ static int rt2800_blink_set(struct led_classdev *led_cdev,
return 0;
}
-static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,
+void rt2800_init_led(struct rt2x00_dev *rt2x00dev,
struct rt2x00_led *led, enum led_type type)
{
led->rt2x00dev = rt2x00dev;
@@ -378,6 +357,7 @@ static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,
led->led_dev.blink_set = rt2800_blink_set;
led->flags = LED_INITIALIZED;
}
+EXPORT_SYMBOL_GPL(rt2800_init_led);
#endif /* CONFIG_RT2X00_LIB_LEDS */
/*
@@ -663,7 +643,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
switch ((int)ant->tx) {
case 1:
rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
- if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
+ if (rt2x00_intf_is_pci(rt2x00dev))
rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
break;
case 2:
@@ -826,12 +806,12 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
unsigned int tx_pin;
u8 bbp;
- if ((rt2x00_rt(rt2x00dev, RT3070) ||
- rt2x00_rt(rt2x00dev, RT3090)) &&
- (rt2x00_rf(rt2x00dev, RF2020) ||
- rt2x00_rf(rt2x00dev, RF3020) ||
- rt2x00_rf(rt2x00dev, RF3021) ||
- rt2x00_rf(rt2x00dev, RF3022)))
+ if ((rt2x00_rt(&rt2x00dev->chip, RT3070) ||
+ rt2x00_rt(&rt2x00dev->chip, RT3090)) &&
+ (rt2x00_rf(&rt2x00dev->chip, RF2020) ||
+ rt2x00_rf(&rt2x00dev->chip, RF3020) ||
+ rt2x00_rf(&rt2x00dev->chip, RF3021) ||
+ rt2x00_rf(&rt2x00dev->chip, RF3022)))
rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info);
else
rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info);
@@ -898,8 +878,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf));
rt2800_bbp_write(rt2x00dev, 3, bbp);
- if (rt2x00_rt(rt2x00dev, RT2860) &&
- (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) {
+ if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) {
if (conf_is_ht40(conf)) {
rt2800_bbp_write(rt2x00dev, 69, 0x1a);
rt2800_bbp_write(rt2x00dev, 70, 0x0a);
@@ -1061,9 +1040,8 @@ EXPORT_SYMBOL_GPL(rt2800_link_stats);
static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
{
if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
- if (rt2x00_is_usb(rt2x00dev) &&
- rt2x00_rt(rt2x00dev, RT3070) &&
- (rt2x00_rev(rt2x00dev) == RT3070_VERSION))
+ if (rt2x00_intf_is_usb(rt2x00dev) &&
+ rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION)
return 0x1c + (2 * rt2x00dev->lna_gain);
else
return 0x2e + rt2x00dev->lna_gain;
@@ -1094,8 +1072,7 @@ EXPORT_SYMBOL_GPL(rt2800_reset_tuner);
void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
const u32 count)
{
- if (rt2x00_rt(rt2x00dev, RT2860) &&
- (rt2x00_rev(rt2x00dev) == RT2860C_VERSION))
+ if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION)
return;
/*
@@ -1115,7 +1092,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
u32 reg;
unsigned int i;
- if (rt2x00_is_usb(rt2x00dev)) {
+ if (rt2x00_intf_is_usb(rt2x00dev)) {
/*
* Wait until BBP and RF are ready.
*/
@@ -1134,7 +1111,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®);
rt2800_register_write(rt2x00dev, PBF_SYS_CTRL,
reg & ~0x00002000);
- } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
+ } else if (rt2x00_intf_is_pci(rt2x00dev))
rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®);
@@ -1142,9 +1119,9 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1);
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
- if (rt2x00_is_usb(rt2x00dev)) {
+ if (rt2x00_intf_is_usb(rt2x00dev)) {
rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
-#if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE)
+#if defined(CONFIG_RT2800USB) || defined(CONFIG_RT2800USB_MODULE)
rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
USB_MODE_RESET, REGISTER_TIMEOUT);
#endif
@@ -1180,9 +1157,8 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0);
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
- if (rt2x00_is_usb(rt2x00dev) &&
- rt2x00_rt(rt2x00dev, RT3070) &&
- (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) {
+ if (rt2x00_intf_is_usb(rt2x00dev) &&
+ rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) {
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
@@ -1209,14 +1185,8 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®);
rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
- if ((rt2x00_rt(rt2x00dev, RT2872) &&
- (rt2x00_rev(rt2x00dev) >= RT2880E_VERSION)) ||
- rt2x00_rt(rt2x00dev, RT2880) ||
- rt2x00_rt(rt2x00dev, RT2883) ||
- rt2x00_rt(rt2x00dev, RT2890) ||
- rt2x00_rt(rt2x00dev, RT3052) ||
- (rt2x00_rt(rt2x00dev, RT3070) &&
- (rt2x00_rev(rt2x00dev) < RT3070_VERSION)))
+ if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION &&
+ rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION)
rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2);
else
rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1);
@@ -1306,7 +1276,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
- if (rt2x00_is_usb(rt2x00dev)) {
+ if (rt2x00_intf_is_usb(rt2x00dev)) {
rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®);
@@ -1366,7 +1336,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_write(rt2x00dev, HW_BEACON_BASE6, 0);
rt2800_register_write(rt2x00dev, HW_BEACON_BASE7, 0);
- if (rt2x00_is_usb(rt2x00dev)) {
+ if (rt2x00_intf_is_usb(rt2x00dev)) {
rt2800_register_read(rt2x00dev, USB_CYC_CFG, ®);
rt2x00_set_field32(®, USB_CYC_CFG_CLOCK_CYCLE, 30);
rt2800_register_write(rt2x00dev, USB_CYC_CFG, reg);
@@ -1495,25 +1465,22 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 103, 0x00);
rt2800_bbp_write(rt2x00dev, 105, 0x05);
- if (rt2x00_rt(rt2x00dev, RT2860) &&
- (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) {
+ if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) {
rt2800_bbp_write(rt2x00dev, 69, 0x16);
rt2800_bbp_write(rt2x00dev, 73, 0x12);
}
- if (rt2x00_rt(rt2x00dev, RT2860) &&
- (rt2x00_rev(rt2x00dev) > RT2860D_VERSION))
+ if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION)
rt2800_bbp_write(rt2x00dev, 84, 0x19);
- if (rt2x00_is_usb(rt2x00dev) &&
- rt2x00_rt(rt2x00dev, RT3070) &&
- (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) {
+ if (rt2x00_intf_is_usb(rt2x00dev) &&
+ rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) {
rt2800_bbp_write(rt2x00dev, 70, 0x0a);
rt2800_bbp_write(rt2x00dev, 84, 0x99);
rt2800_bbp_write(rt2x00dev, 105, 0x05);
}
- if (rt2x00_rt(rt2x00dev, RT3052)) {
+ if (rt2x00_rt(&rt2x00dev->chip, RT3052)) {
rt2800_bbp_write(rt2x00dev, 31, 0x08);
rt2800_bbp_write(rt2x00dev, 78, 0x0e);
rt2800_bbp_write(rt2x00dev, 80, 0x08);
@@ -1598,15 +1565,14 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
u8 rfcsr;
u8 bbp;
- if (rt2x00_is_usb(rt2x00dev) &&
- rt2x00_rt(rt2x00dev, RT3070) &&
- (rt2x00_rev(rt2x00dev) != RT3070_VERSION))
+ if (rt2x00_intf_is_usb(rt2x00dev) &&
+ rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION)
return 0;
- if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) {
- if (!rt2x00_rf(rt2x00dev, RF3020) &&
- !rt2x00_rf(rt2x00dev, RF3021) &&
- !rt2x00_rf(rt2x00dev, RF3022))
+ if (rt2x00_intf_is_pci(rt2x00dev)) {
+ if (!rt2x00_rf(&rt2x00dev->chip, RF3020) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF3021) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF3022))
return 0;
}
@@ -1620,7 +1586,7 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);
rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
- if (rt2x00_is_usb(rt2x00dev)) {
+ if (rt2x00_intf_is_usb(rt2x00dev)) {
rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
rt2800_rfcsr_write(rt2x00dev, 5, 0x03);
rt2800_rfcsr_write(rt2x00dev, 6, 0x02);
@@ -1641,7 +1607,7 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
rt2800_rfcsr_write(rt2x00dev, 29, 0x1f);
- } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) {
+ } else if (rt2x00_intf_is_pci(rt2x00dev)) {
rt2800_rfcsr_write(rt2x00dev, 0, 0x50);
rt2800_rfcsr_write(rt2x00dev, 1, 0x01);
rt2800_rfcsr_write(rt2x00dev, 2, 0xf7);
@@ -1771,12 +1737,7 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820);
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
- } else if (rt2x00_rt(rt2x00dev, RT2860) ||
- rt2x00_rt(rt2x00dev, RT2870) ||
- rt2x00_rt(rt2x00dev, RT2872) ||
- rt2x00_rt(rt2x00dev, RT2880) ||
- (rt2x00_rt(rt2x00dev, RT2883) &&
- (rt2x00_rev(rt2x00dev) < RT2883_VERSION))) {
+ } else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) {
/*
* There is a max of 2 RX streams for RT28x0 series
*/
@@ -1875,34 +1836,36 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
rt2800_register_read(rt2x00dev, MAC_CSR0, ®);
- rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
- value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
-
- if (!rt2x00_rt(rt2x00dev, RT2860) &&
- !rt2x00_rt(rt2x00dev, RT2870) &&
- !rt2x00_rt(rt2x00dev, RT2872) &&
- !rt2x00_rt(rt2x00dev, RT2880) &&
- !rt2x00_rt(rt2x00dev, RT2883) &&
- !rt2x00_rt(rt2x00dev, RT2890) &&
- !rt2x00_rt(rt2x00dev, RT3052) &&
- !rt2x00_rt(rt2x00dev, RT3070) &&
- !rt2x00_rt(rt2x00dev, RT3071) &&
- !rt2x00_rt(rt2x00dev, RT3090) &&
- !rt2x00_rt(rt2x00dev, RT3390) &&
- !rt2x00_rt(rt2x00dev, RT3572)) {
- ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
- return -ENODEV;
- }
+ rt2x00_set_chip_rf(rt2x00dev, value, reg);
+
+ if (rt2x00_intf_is_usb(rt2x00dev)) {
+ struct rt2x00_chip *chip = &rt2x00dev->chip;
- if (!rt2x00_rf(rt2x00dev, RF2820) &&
- !rt2x00_rf(rt2x00dev, RF2850) &&
- !rt2x00_rf(rt2x00dev, RF2720) &&
- !rt2x00_rf(rt2x00dev, RF2750) &&
- !rt2x00_rf(rt2x00dev, RF3020) &&
- !rt2x00_rf(rt2x00dev, RF2020) &&
- !rt2x00_rf(rt2x00dev, RF3021) &&
- !rt2x00_rf(rt2x00dev, RF3022) &&
- !rt2x00_rf(rt2x00dev, RF3052)) {
+ /*
+ * The check for rt2860 is not a typo, some rt2870 hardware
+ * identifies itself as rt2860 in the CSR register.
+ */
+ if (rt2x00_check_rev(chip, 0xfff00000, 0x28600000) ||
+ rt2x00_check_rev(chip, 0xfff00000, 0x28700000) ||
+ rt2x00_check_rev(chip, 0xfff00000, 0x28800000)) {
+ rt2x00_set_chip_rt(rt2x00dev, RT2870);
+ } else if (rt2x00_check_rev(chip, 0xffff0000, 0x30700000)) {
+ rt2x00_set_chip_rt(rt2x00dev, RT3070);
+ } else {
+ ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
+ return -ENODEV;
+ }
+ }
+ rt2x00_print_chip(rt2x00dev);
+
+ if (!rt2x00_rf(&rt2x00dev->chip, RF2820) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF2850) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF2720) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF2750) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF3020) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF2020) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF3021) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF3022)) {
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
return -ENODEV;
}
@@ -2050,6 +2013,7 @@ static const struct rf_channel rf_vals_302x[] = {
int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
{
+ struct rt2x00_chip *chip = &rt2x00dev->chip;
struct hw_mode_spec *spec = &rt2x00dev->spec;
struct channel_info *info;
char *tx_power1;
@@ -2060,7 +2024,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
/*
* Disable powersaving as default on PCI devices.
*/
- if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
+ if (rt2x00_intf_is_pci(rt2x00dev))
rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
/*
@@ -2085,19 +2049,19 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
spec->supported_bands = SUPPORT_BAND_2GHZ;
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
- if (rt2x00_rf(rt2x00dev, RF2820) ||
- rt2x00_rf(rt2x00dev, RF2720) ||
- rt2x00_rf(rt2x00dev, RF3052)) {
+ if (rt2x00_rf(chip, RF2820) ||
+ rt2x00_rf(chip, RF2720) ||
+ (rt2x00_intf_is_pci(rt2x00dev) && rt2x00_rf(chip, RF3052))) {
spec->num_channels = 14;
spec->channels = rf_vals;
- } else if (rt2x00_rf(rt2x00dev, RF2850) || rt2x00_rf(rt2x00dev, RF2750)) {
+ } else if (rt2x00_rf(chip, RF2850) || rt2x00_rf(chip, RF2750)) {
spec->supported_bands |= SUPPORT_BAND_5GHZ;
spec->num_channels = ARRAY_SIZE(rf_vals);
spec->channels = rf_vals;
- } else if (rt2x00_rf(rt2x00dev, RF3020) ||
- rt2x00_rf(rt2x00dev, RF2020) ||
- rt2x00_rf(rt2x00dev, RF3021) ||
- rt2x00_rf(rt2x00dev, RF3022)) {
+ } else if (rt2x00_rf(chip, RF3020) ||
+ rt2x00_rf(chip, RF2020) ||
+ rt2x00_rf(chip, RF3021) ||
+ rt2x00_rf(chip, RF3022)) {
spec->num_channels = ARRAY_SIZE(rf_vals_302x);
spec->channels = rf_vals_302x;
}
@@ -2105,7 +2069,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
/*
* Initialize HT information.
*/
- if (!rt2x00_rf(rt2x00dev, RF2020))
+ if (!rt2x00_rf(chip, RF2020))
spec->ht.ht_supported = true;
else
spec->ht.ht_supported = false;
@@ -2318,6 +2282,7 @@ const struct ieee80211_ops rt2800_mac80211_ops = {
.set_rts_threshold = rt2800_set_rts_threshold,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2800_conf_tx,
+ .get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt2800_get_tsf,
.rfkill_poll = rt2x00mac_rfkill_poll,
};
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800lib.h b/trunk/drivers/net/wireless/rt2x00/rt2800lib.h
index ebabeae62d1b..535ce22f2ac8 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/trunk/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -114,6 +114,8 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
extern const struct rt2x00debug rt2800_rt2x00debug;
int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev);
+void rt2800_init_led(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00_led *led, enum led_type type);
int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_crypto *crypto,
struct ieee80211_key_conf *key);
@@ -137,7 +139,6 @@ void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
int rt2800_init_registers(struct rt2x00_dev *rt2x00dev);
int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev);
int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev);
-int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev);
int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev);
void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev);
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800pci.c b/trunk/drivers/net/wireless/rt2x00/rt2800pci.c
index 0e4c41766edc..dfc886fcb44d 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/trunk/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -48,6 +48,14 @@
#include "rt2800.h"
#include "rt2800pci.h"
+#ifdef CONFIG_RT2800PCI_PCI_MODULE
+#define CONFIG_RT2800PCI_PCI
+#endif
+
+#ifdef CONFIG_RT2800PCI_WISOC_MODULE
+#define CONFIG_RT2800PCI_WISOC
+#endif
+
/*
* Allow hardware encryption to be disabled.
*/
@@ -79,7 +87,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
}
-#ifdef CONFIG_RT2800PCI_SOC
+#ifdef CONFIG_RT2800PCI_WISOC
static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
{
u32 *base_addr = (u32 *) KSEG1ADDR(0x1F040000); /* XXX for RT3052 */
@@ -90,7 +98,7 @@ static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
{
}
-#endif /* CONFIG_RT2800PCI_SOC */
+#endif /* CONFIG_RT2800PCI_WISOC */
#ifdef CONFIG_RT2800PCI_PCI
static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
@@ -453,6 +461,24 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
}
+static int rt2800pci_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
+{
+ unsigned int i;
+ u32 reg;
+
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®);
+ if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
+ !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY))
+ return 0;
+
+ msleep(1);
+ }
+
+ ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n");
+ return -EACCES;
+}
+
static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
@@ -461,10 +487,10 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Initialize all registers.
*/
- if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) ||
+ if (unlikely(rt2800pci_wait_wpdma_ready(rt2x00dev) ||
rt2800pci_init_queues(rt2x00dev) ||
rt2800_init_registers(rt2x00dev) ||
- rt2800_wait_wpdma_ready(rt2x00dev) ||
+ rt2800pci_wait_wpdma_ready(rt2x00dev) ||
rt2800_init_bbp(rt2x00dev) ||
rt2800_init_rfcsr(rt2x00dev)))
return -EIO;
@@ -544,7 +570,7 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
/* Wait for DMA, ignore error */
- rt2800_wait_wpdma_ready(rt2x00dev);
+ rt2800pci_wait_wpdma_ready(rt2x00dev);
}
static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
@@ -809,6 +835,7 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
__le32 *rxd = entry_priv->desc;
__le32 *rxwi = (__le32 *)entry->skb->data;
@@ -856,8 +883,10 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
if (rt2x00_get_field32(rxd3, RXD_W3_MY_BSS))
rxdesc->dev_flags |= RXDONE_MY_BSS;
- if (rt2x00_get_field32(rxd3, RXD_W3_L2PAD))
+ if (rt2x00_get_field32(rxd3, RXD_W3_L2PAD)) {
rxdesc->dev_flags |= RXDONE_L2PAD;
+ skbdesc->flags |= SKBDESC_L2_PADDED;
+ }
if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI))
rxdesc->flags |= RX_FLAG_SHORT_GI;
@@ -898,6 +927,7 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
* Remove TXWI descriptor from start of buffer.
*/
skb_pull(entry->skb, RXWI_DESC_SIZE);
+ skb_trim(entry->skb, rxdesc->size);
}
/*
@@ -1041,12 +1071,18 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Read EEPROM into buffer
*/
- if (rt2x00_is_soc(rt2x00dev))
+ switch (rt2x00dev->chip.rt) {
+ case RT2880:
+ case RT3052:
rt2800pci_read_eeprom_soc(rt2x00dev);
- else if (rt2800pci_efuse_detect(rt2x00dev))
- rt2800pci_read_eeprom_efuse(rt2x00dev);
- else
- rt2800pci_read_eeprom_pci(rt2x00dev);
+ break;
+ default:
+ if (rt2800pci_efuse_detect(rt2x00dev))
+ rt2800pci_read_eeprom_efuse(rt2x00dev);
+ else
+ rt2800pci_read_eeprom_pci(rt2x00dev);
+ break;
+ }
return rt2800_validate_eeprom(rt2x00dev);
}
@@ -1097,7 +1133,8 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* This device requires firmware.
*/
- if (!rt2x00_is_soc(rt2x00dev))
+ if (!rt2x00_rt(&rt2x00dev->chip, RT2880) &&
+ !rt2x00_rt(&rt2x00dev->chip, RT3052))
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
@@ -1185,10 +1222,7 @@ static const struct rt2x00_ops rt2800pci_ops = {
* RT2800pci module information.
*/
static struct pci_device_id rt2800pci_device_table[] = {
- { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) },
+ { PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) },
@@ -1196,19 +1230,18 @@ static struct pci_device_id rt2800pci_device_table[] = {
{ PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) },
-#ifdef CONFIG_RT2800PCI_RT30XX
+ { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) },
+ { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) },
+ { PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) },
+ { PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) },
+ { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) },
+ { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) },
-#endif
-#ifdef CONFIG_RT2800PCI_RT35XX
- { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) },
-#endif
+ { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ 0, }
};
@@ -1222,11 +1255,12 @@ MODULE_DEVICE_TABLE(pci, rt2800pci_device_table);
#endif /* CONFIG_RT2800PCI_PCI */
MODULE_LICENSE("GPL");
-#ifdef CONFIG_RT2800PCI_SOC
-static int rt2800soc_probe(struct platform_device *pdev)
-{
- return rt2x00soc_probe(pdev, rt2800pci_ops);
-}
+#ifdef CONFIG_RT2800PCI_WISOC
+#if defined(CONFIG_RALINK_RT288X)
+__rt2x00soc_probe(RT2880, &rt2800pci_ops);
+#elif defined(CONFIG_RALINK_RT305X)
+__rt2x00soc_probe(RT3052, &rt2800pci_ops);
+#endif
static struct platform_driver rt2800soc_driver = {
.driver = {
@@ -1234,12 +1268,12 @@ static struct platform_driver rt2800soc_driver = {
.owner = THIS_MODULE,
.mod_name = KBUILD_MODNAME,
},
- .probe = rt2800soc_probe,
+ .probe = __rt2x00soc_probe,
.remove = __devexit_p(rt2x00soc_remove),
.suspend = rt2x00soc_suspend,
.resume = rt2x00soc_resume,
};
-#endif /* CONFIG_RT2800PCI_SOC */
+#endif /* CONFIG_RT2800PCI_WISOC */
#ifdef CONFIG_RT2800PCI_PCI
static struct pci_driver rt2800pci_driver = {
@@ -1256,7 +1290,7 @@ static int __init rt2800pci_init(void)
{
int ret = 0;
-#ifdef CONFIG_RT2800PCI_SOC
+#ifdef CONFIG_RT2800PCI_WISOC
ret = platform_driver_register(&rt2800soc_driver);
if (ret)
return ret;
@@ -1264,7 +1298,7 @@ static int __init rt2800pci_init(void)
#ifdef CONFIG_RT2800PCI_PCI
ret = pci_register_driver(&rt2800pci_driver);
if (ret) {
-#ifdef CONFIG_RT2800PCI_SOC
+#ifdef CONFIG_RT2800PCI_WISOC
platform_driver_unregister(&rt2800soc_driver);
#endif
return ret;
@@ -1279,7 +1313,7 @@ static void __exit rt2800pci_exit(void)
#ifdef CONFIG_RT2800PCI_PCI
pci_unregister_driver(&rt2800pci_driver);
#endif
-#ifdef CONFIG_RT2800PCI_SOC
+#ifdef CONFIG_RT2800PCI_WISOC
platform_driver_unregister(&rt2800soc_driver);
#endif
}
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800usb.c b/trunk/drivers/net/wireless/rt2x00/rt2800usb.c
index 5e4ee2023fcf..ab95346cf6a3 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/trunk/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -92,6 +92,7 @@ static bool rt2800usb_check_crc(const u8 *data, const size_t len)
static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev,
const u8 *data, const size_t len)
{
+ u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff;
size_t offset = 0;
/*
@@ -110,9 +111,9 @@ static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev,
* Check if we need the upper 4kb firmware data or not.
*/
if ((len == 4096) &&
- !rt2x00_rt(rt2x00dev, RT2860) &&
- !rt2x00_rt(rt2x00dev, RT2872) &&
- !rt2x00_rt(rt2x00dev, RT3070))
+ (chipset != 0x2860) &&
+ (chipset != 0x2872) &&
+ (chipset != 0x3070))
return FW_BAD_VERSION;
/*
@@ -137,13 +138,14 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
u32 reg;
u32 offset;
u32 length;
+ u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff;
/*
* Check which section of the firmware we need.
*/
- if (rt2x00_rt(rt2x00dev, RT2860) ||
- rt2x00_rt(rt2x00dev, RT2872) ||
- rt2x00_rt(rt2x00dev, RT3070)) {
+ if ((chipset == 0x2860) ||
+ (chipset == 0x2872) ||
+ (chipset == 0x3070)) {
offset = 0;
length = 4096;
} else {
@@ -198,9 +200,9 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
*/
rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0);
- if (rt2x00_rt(rt2x00dev, RT3070) ||
- rt2x00_rt(rt2x00dev, RT3071) ||
- rt2x00_rt(rt2x00dev, RT3572)) {
+ if ((chipset == 0x3070) ||
+ (chipset == 0x3071) ||
+ (chipset == 0x3572)) {
udelay(200);
rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0);
udelay(10);
@@ -246,6 +248,24 @@ static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev,
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
}
+static int rt2800usb_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
+{
+ unsigned int i;
+ u32 reg;
+
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®);
+ if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
+ !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY))
+ return 0;
+
+ msleep(1);
+ }
+
+ ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n");
+ return -EACCES;
+}
+
static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
@@ -254,7 +274,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Initialize all registers.
*/
- if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) ||
+ if (unlikely(rt2800usb_wait_wpdma_ready(rt2x00dev) ||
rt2800_init_registers(rt2x00dev) ||
rt2800_init_bbp(rt2x00dev) ||
rt2800_init_rfcsr(rt2x00dev)))
@@ -275,7 +295,9 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
rt2800_register_read(rt2x00dev, USB_DMA_CFG, ®);
rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0);
- rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, 0);
+ /* Don't use bulk in aggregation when working with USB 1.1 */
+ rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN,
+ (rt2x00dev->rx->usb_maxpacket == 512));
rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128);
/*
* Total room for RX frames in kilobytes, PBF might still exceed
@@ -324,7 +346,7 @@ static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev)
rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
/* Wait for DMA, ignore error */
- rt2800_wait_wpdma_ready(rt2x00dev);
+ rt2800usb_wait_wpdma_ready(rt2x00dev);
rt2x00usb_disable_radio(rt2x00dev);
}
@@ -551,57 +573,41 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
- __le32 *rxi = (__le32 *)entry->skb->data;
+ __le32 *rxd = (__le32 *)entry->skb->data;
__le32 *rxwi;
- __le32 *rxd;
- u32 rxi0;
+ u32 rxd0;
u32 rxwi0;
u32 rxwi1;
u32 rxwi2;
u32 rxwi3;
- u32 rxd0;
- int rx_pkt_len;
-
- /*
- * RX frame format is :
- * | RXINFO | RXWI | header | L2 pad | payload | pad | RXD | USB pad |
- * |<------------ rx_pkt_len -------------->|
- */
- rt2x00_desc_read(rxi, 0, &rxi0);
- rx_pkt_len = rt2x00_get_field32(rxi0, RXINFO_W0_USB_DMA_RX_PKT_LEN);
-
- rxwi = (__le32 *)(entry->skb->data + RXINFO_DESC_SIZE);
-
- /*
- * FIXME : we need to check for rx_pkt_len validity
- */
- rxd = (__le32 *)(entry->skb->data + RXINFO_DESC_SIZE + rx_pkt_len);
/*
* Copy descriptor to the skbdesc->desc buffer, making it safe from
* moving of frame data in rt2x00usb.
*/
- memcpy(skbdesc->desc, rxi, skbdesc->desc_len);
+ memcpy(skbdesc->desc, rxd, skbdesc->desc_len);
+ rxd = (__le32 *)skbdesc->desc;
+ rxwi = &rxd[RXINFO_DESC_SIZE / sizeof(__le32)];
/*
* It is now safe to read the descriptor on all architectures.
*/
+ rt2x00_desc_read(rxd, 0, &rxd0);
rt2x00_desc_read(rxwi, 0, &rxwi0);
rt2x00_desc_read(rxwi, 1, &rxwi1);
rt2x00_desc_read(rxwi, 2, &rxwi2);
rt2x00_desc_read(rxwi, 3, &rxwi3);
- rt2x00_desc_read(rxd, 0, &rxd0);
- if (rt2x00_get_field32(rxd0, RXD_W0_CRC_ERROR))
+ if (rt2x00_get_field32(rxd0, RXINFO_W0_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF);
rxdesc->cipher_status =
- rt2x00_get_field32(rxd0, RXD_W0_CIPHER_ERROR);
+ rt2x00_get_field32(rxd0, RXINFO_W0_CIPHER_ERROR);
}
- if (rt2x00_get_field32(rxd0, RXD_W0_DECRYPTED)) {
+ if (rt2x00_get_field32(rxd0, RXINFO_W0_DECRYPTED)) {
/*
* Hardware has stripped IV/EIV data from 802.11 frame during
* decryption. Unfortunately the descriptor doesn't contain
@@ -616,11 +622,13 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
rxdesc->flags |= RX_FLAG_MMIC_ERROR;
}
- if (rt2x00_get_field32(rxd0, RXD_W0_MY_BSS))
+ if (rt2x00_get_field32(rxd0, RXINFO_W0_MY_BSS))
rxdesc->dev_flags |= RXDONE_MY_BSS;
- if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD))
+ if (rt2x00_get_field32(rxd0, RXINFO_W0_L2PAD)) {
rxdesc->dev_flags |= RXDONE_L2PAD;
+ skbdesc->flags |= SKBDESC_L2_PADDED;
+ }
if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI))
rxdesc->flags |= RX_FLAG_SHORT_GI;
@@ -655,6 +663,7 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
* Remove RXWI descriptor from start of buffer.
*/
skb_pull(entry->skb, skbdesc->desc_len);
+ skb_trim(entry->skb, rxdesc->size);
}
/*
@@ -805,27 +814,51 @@ static struct usb_device_id rt2800usb_device_table[] = {
/* Abocom */
{ USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
+ /* AirTies */
+ { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) },
+ /* Amigo */
+ { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Amit */
{ USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Askey */
{ USB_DEVICE(0x1690, 0x0740), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) },
/* ASUS */
{ USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) },
/* AzureWave */
{ USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Belkin */
{ USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Buffalo */
{ USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) },
+ /* Cisco */
+ { USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Conceptronic */
{ USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) },
@@ -834,257 +867,157 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* D-Link */
- { USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Edimax */
- { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* EnGenius */
- { USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Gigabyte */
- { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Hawking */
- { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Linksys */
- { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Logitec */
- { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Motorola */
- { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* MSI */
- { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Philips */
- { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Planex */
- { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Ralink */
- { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Samsung */
- { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Siemens */
- { USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Sitecom */
- { USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* SMC */
- { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Sparklan */
- { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Sweex */
- { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* U-Media*/
- { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* ZCOM */
- { USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Zinwell */
- { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Zyxel */
- { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) },
-#ifdef CONFIG_RT2800USB_RT30XX
- /* Abocom */
- { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* AirTies */
- { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* AzureWave */
- { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Conceptronic */
- { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Corega */
+ { USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) },
/* D-Link */
+ { USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Edimax */
{ USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Encore */
{ USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) },
/* EnGenius */
+ { USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Gigabyte */
- { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* I-O DATA */
- { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* MSI */
- { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Pegatron */
- { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Planex */
- { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Quanta */
- { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Ralink */
- { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Sitecom */
- { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* SMC */
- { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Zinwell */
- { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) },
-#endif
-#ifdef CONFIG_RT2800USB_RT35XX
- /* Askey */
- { USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Cisco */
- { USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* EnGenius */
- { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* I-O DATA */
- { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Ralink */
- { USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Sitecom */
- { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Zinwell */
- { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) },
-#endif
-#ifdef CONFIG_RT2800USB_UNKNOWN
- /*
- * Unclear what kind of devices these are (they aren't supported by the
- * vendor driver).
- */
- /* Allwin */
- { USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Amigo */
- { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Askey */
- { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* ASUS */
- { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* AzureWave */
- { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Belkin */
- { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Buffalo */
- { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0411, 0x0148), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0411, 0x0150), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0411, 0x015d), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Conceptronic */
- { USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Corega */
- { USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* D-Link */
- { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* Encore */
- { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) },
- /* EnGenius */
{ USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Gemtek */
{ USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Gigabyte */
+ { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Hawking */
+ { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) },
/* I-O DATA */
+ { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) },
/* LevelOne */
{ USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Linksys */
+ { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1737, 0x0078), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) },
+ /* Logitec */
+ { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Motorola */
+ { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) },
/* MSI */
+ { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Ovislink */
{ USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Para */
{ USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Pegatron */
- { USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) },
+ /* Philips */
+ { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Planex */
+ { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Qcom */
{ USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) },
+ /* Quanta */
+ { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) },
+ /* Ralink */
+ { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
+ /* Samsung */
+ { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) },
+ /* Siemens */
+ { USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Sitecom */
+ { USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0df6, 0x004a), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0df6, 0x004d), USB_DEVICE_DATA(&rt2800usb_ops) },
/* SMC */
+ { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) },
+ /* Sparklan */
+ { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Sweex */
{ USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) },
+ /* U-Media*/
+ { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) },
+ /* ZCOM */
+ { USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) },
+ /* Zinwell */
+ { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Zyxel */
+ { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) },
-#endif
{ 0, }
};
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800usb.h b/trunk/drivers/net/wireless/rt2x00/rt2800usb.h
index d1d8ae94b4d4..1e4340a182ef 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2800usb.h
+++ b/trunk/drivers/net/wireless/rt2x00/rt2800usb.h
@@ -79,8 +79,6 @@
*/
#define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) )
#define RXINFO_DESC_SIZE ( 1 * sizeof(__le32) )
-#define RXWI_DESC_SIZE ( 4 * sizeof(__le32) )
-#define RXD_DESC_SIZE ( 1 * sizeof(__le32) )
/*
* TX Info structure
@@ -102,54 +100,6 @@
#define TXINFO_W0_USB_DMA_NEXT_VALID FIELD32(0x40000000)
#define TXINFO_W0_USB_DMA_TX_BURST FIELD32(0x80000000)
-/*
- * RX Info structure
- */
-
-/*
- * Word 0
- */
-
-#define RXINFO_W0_USB_DMA_RX_PKT_LEN FIELD32(0x0000ffff)
-
-/*
- * RX WI structure
- */
-
-/*
- * Word0
- */
-#define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff)
-#define RXWI_W0_KEY_INDEX FIELD32(0x00000300)
-#define RXWI_W0_BSSID FIELD32(0x00001c00)
-#define RXWI_W0_UDF FIELD32(0x0000e000)
-#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000)
-#define RXWI_W0_TID FIELD32(0xf0000000)
-
-/*
- * Word1
- */
-#define RXWI_W1_FRAG FIELD32(0x0000000f)
-#define RXWI_W1_SEQUENCE FIELD32(0x0000fff0)
-#define RXWI_W1_MCS FIELD32(0x007f0000)
-#define RXWI_W1_BW FIELD32(0x00800000)
-#define RXWI_W1_SHORT_GI FIELD32(0x01000000)
-#define RXWI_W1_STBC FIELD32(0x06000000)
-#define RXWI_W1_PHYMODE FIELD32(0xc0000000)
-
-/*
- * Word2
- */
-#define RXWI_W2_RSSI0 FIELD32(0x000000ff)
-#define RXWI_W2_RSSI1 FIELD32(0x0000ff00)
-#define RXWI_W2_RSSI2 FIELD32(0x00ff0000)
-
-/*
- * Word3
- */
-#define RXWI_W3_SNR0 FIELD32(0x000000ff)
-#define RXWI_W3_SNR1 FIELD32(0x0000ff00)
-
/*
* RX descriptor format for RX Ring.
*/
@@ -165,25 +115,25 @@
* AMSDU: rx with 802.3 header, not 802.11 header.
*/
-#define RXD_W0_BA FIELD32(0x00000001)
-#define RXD_W0_DATA FIELD32(0x00000002)
-#define RXD_W0_NULLDATA FIELD32(0x00000004)
-#define RXD_W0_FRAG FIELD32(0x00000008)
-#define RXD_W0_UNICAST_TO_ME FIELD32(0x00000010)
-#define RXD_W0_MULTICAST FIELD32(0x00000020)
-#define RXD_W0_BROADCAST FIELD32(0x00000040)
-#define RXD_W0_MY_BSS FIELD32(0x00000080)
-#define RXD_W0_CRC_ERROR FIELD32(0x00000100)
-#define RXD_W0_CIPHER_ERROR FIELD32(0x00000600)
-#define RXD_W0_AMSDU FIELD32(0x00000800)
-#define RXD_W0_HTC FIELD32(0x00001000)
-#define RXD_W0_RSSI FIELD32(0x00002000)
-#define RXD_W0_L2PAD FIELD32(0x00004000)
-#define RXD_W0_AMPDU FIELD32(0x00008000)
-#define RXD_W0_DECRYPTED FIELD32(0x00010000)
-#define RXD_W0_PLCP_RSSI FIELD32(0x00020000)
-#define RXD_W0_CIPHER_ALG FIELD32(0x00040000)
-#define RXD_W0_LAST_AMSDU FIELD32(0x00080000)
-#define RXD_W0_PLCP_SIGNAL FIELD32(0xfff00000)
+#define RXINFO_W0_BA FIELD32(0x00000001)
+#define RXINFO_W0_DATA FIELD32(0x00000002)
+#define RXINFO_W0_NULLDATA FIELD32(0x00000004)
+#define RXINFO_W0_FRAG FIELD32(0x00000008)
+#define RXINFO_W0_UNICAST_TO_ME FIELD32(0x00000010)
+#define RXINFO_W0_MULTICAST FIELD32(0x00000020)
+#define RXINFO_W0_BROADCAST FIELD32(0x00000040)
+#define RXINFO_W0_MY_BSS FIELD32(0x00000080)
+#define RXINFO_W0_CRC_ERROR FIELD32(0x00000100)
+#define RXINFO_W0_CIPHER_ERROR FIELD32(0x00000600)
+#define RXINFO_W0_AMSDU FIELD32(0x00000800)
+#define RXINFO_W0_HTC FIELD32(0x00001000)
+#define RXINFO_W0_RSSI FIELD32(0x00002000)
+#define RXINFO_W0_L2PAD FIELD32(0x00004000)
+#define RXINFO_W0_AMPDU FIELD32(0x00008000)
+#define RXINFO_W0_DECRYPTED FIELD32(0x00010000)
+#define RXINFO_W0_PLCP_RSSI FIELD32(0x00020000)
+#define RXINFO_W0_CIPHER_ALG FIELD32(0x00040000)
+#define RXINFO_W0_LAST_AMSDU FIELD32(0x00080000)
+#define RXINFO_W0_PLCP_SIGNAL FIELD32(0xfff00000)
#endif /* RT2800USB_H */
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00.h b/trunk/drivers/net/wireless/rt2x00/rt2x00.h
index d9daa9c406fa..dcfc8c25d1a7 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/trunk/drivers/net/wireless/rt2x00/rt2x00.h
@@ -103,12 +103,6 @@
#define GET_DURATION(__size, __rate) (((__size) * 8 * 10) / (__rate))
#define GET_DURATION_RES(__size, __rate)(((__size) * 8 * 10) % (__rate))
-/*
- * Determine the number of L2 padding bytes required between the header and
- * the payload.
- */
-#define L2PAD_SIZE(__hdrlen) (-(__hdrlen) & 3)
-
/*
* Determine the alignment requirement,
* to make sure the 802.11 payload is padded to a 4-byte boundrary
@@ -160,7 +154,6 @@ struct avg_val {
enum rt2x00_chip_intf {
RT2X00_CHIP_INTF_PCI,
RT2X00_CHIP_INTF_USB,
- RT2X00_CHIP_INTF_SOC,
};
/*
@@ -170,26 +163,25 @@ enum rt2x00_chip_intf {
*/
struct rt2x00_chip {
u16 rt;
-#define RT2460 0x2460
-#define RT2560 0x2560
-#define RT2570 0x2570
-#define RT2661 0x2661
-#define RT2573 0x2573
-#define RT2860 0x2860 /* 2.4GHz PCI/CB */
-#define RT2870 0x2870
-#define RT2872 0x2872
+#define RT2460 0x0101
+#define RT2560 0x0201
+#define RT2570 0x1201
+#define RT2561s 0x0301 /* Turbo */
+#define RT2561 0x0302
+#define RT2661 0x0401
+#define RT2571 0x1300
+#define RT2860 0x0601 /* 2.4GHz PCI/CB */
+#define RT2860D 0x0681 /* 2.4GHz, 5GHz PCI/CB */
+#define RT2890 0x0701 /* 2.4GHz PCIe */
+#define RT2890D 0x0781 /* 2.4GHz, 5GHz PCIe */
#define RT2880 0x2880 /* WSOC */
-#define RT2883 0x2883 /* WSOC */
-#define RT2890 0x2890 /* 2.4GHz PCIe */
#define RT3052 0x3052 /* WSOC */
-#define RT3070 0x3070
-#define RT3071 0x3071
#define RT3090 0x3090 /* 2.4GHz PCIe */
-#define RT3390 0x3390
-#define RT3572 0x3572
+#define RT2870 0x1600
+#define RT3070 0x1800
u16 rf;
- u16 rev;
+ u32 rev;
enum rt2x00_chip_intf intf;
};
@@ -919,30 +911,51 @@ static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev,
* Chipset handlers
*/
static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev,
- const u16 rt, const u16 rf, const u16 rev)
+ const u16 rt, const u16 rf, const u32 rev)
{
rt2x00dev->chip.rt = rt;
rt2x00dev->chip.rf = rf;
rt2x00dev->chip.rev = rev;
+}
+
+static inline void rt2x00_set_chip_rt(struct rt2x00_dev *rt2x00dev,
+ const u16 rt)
+{
+ rt2x00dev->chip.rt = rt;
+}
+
+static inline void rt2x00_set_chip_rf(struct rt2x00_dev *rt2x00dev,
+ const u16 rf, const u32 rev)
+{
+ rt2x00_set_chip(rt2x00dev, rt2x00dev->chip.rt, rf, rev);
+}
+static inline void rt2x00_print_chip(struct rt2x00_dev *rt2x00dev)
+{
INFO(rt2x00dev,
- "Chipset detected - rt: %04x, rf: %04x, rev: %04x.\n",
+ "Chipset detected - rt: %04x, rf: %04x, rev: %08x.\n",
rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev);
}
-static inline char rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt)
+static inline char rt2x00_rt(const struct rt2x00_chip *chipset, const u16 chip)
{
- return (rt2x00dev->chip.rt == rt);
+ return (chipset->rt == chip);
}
-static inline char rt2x00_rf(struct rt2x00_dev *rt2x00dev, const u16 rf)
+static inline char rt2x00_rf(const struct rt2x00_chip *chipset, const u16 chip)
{
- return (rt2x00dev->chip.rf == rf);
+ return (chipset->rf == chip);
}
-static inline u16 rt2x00_rev(struct rt2x00_dev *rt2x00dev)
+static inline u32 rt2x00_rev(const struct rt2x00_chip *chipset)
{
- return rt2x00dev->chip.rev;
+ return chipset->rev;
+}
+
+static inline bool rt2x00_check_rev(const struct rt2x00_chip *chipset,
+ const u32 mask, const u32 rev)
+{
+ return ((chipset->rev & mask) == rev);
}
static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev,
@@ -951,25 +964,20 @@ static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev,
rt2x00dev->chip.intf = intf;
}
-static inline bool rt2x00_intf(struct rt2x00_dev *rt2x00dev,
+static inline bool rt2x00_intf(const struct rt2x00_chip *chipset,
enum rt2x00_chip_intf intf)
{
- return (rt2x00dev->chip.intf == intf);
-}
-
-static inline bool rt2x00_is_pci(struct rt2x00_dev *rt2x00dev)
-{
- return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI);
+ return (chipset->intf == intf);
}
-static inline bool rt2x00_is_usb(struct rt2x00_dev *rt2x00dev)
+static inline bool rt2x00_intf_is_pci(struct rt2x00_dev *rt2x00dev)
{
- return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_USB);
+ return rt2x00_intf(&rt2x00dev->chip, RT2X00_CHIP_INTF_PCI);
}
-static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev)
+static inline bool rt2x00_intf_is_usb(struct rt2x00_dev *rt2x00dev)
{
- return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
+ return rt2x00_intf(&rt2x00dev->chip, RT2X00_CHIP_INTF_USB);
}
/**
@@ -1011,9 +1019,9 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
int rt2x00mac_start(struct ieee80211_hw *hw);
void rt2x00mac_stop(struct ieee80211_hw *hw);
int rt2x00mac_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
+ struct ieee80211_if_init_conf *conf);
void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
+ struct ieee80211_if_init_conf *conf);
int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed);
void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags,
@@ -1030,6 +1038,8 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
#endif /* CONFIG_RT2X00_LIB_CRYPTO */
int rt2x00mac_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats);
+int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats);
void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00debug.c b/trunk/drivers/net/wireless/rt2x00/rt2x00debug.c
index 70c04c282efc..7d323a763b54 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/trunk/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -184,7 +184,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
dump_hdr->data_length = cpu_to_le32(skb->len);
dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt);
dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
- dump_hdr->chip_rev = cpu_to_le16(rt2x00dev->chip.rev);
+ dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev);
dump_hdr->type = cpu_to_le16(type);
dump_hdr->queue_index = desc->entry->queue->qid;
dump_hdr->entry_index = desc->entry->entry_idx;
@@ -573,7 +573,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,
blob->data = data;
data += sprintf(data, "rt chip:\t%04x\n", intf->rt2x00dev->chip.rt);
data += sprintf(data, "rf chip:\t%04x\n", intf->rt2x00dev->chip.rf);
- data += sprintf(data, "revision:\t%04x\n", intf->rt2x00dev->chip.rev);
+ data += sprintf(data, "revision:\t%08x\n", intf->rt2x00dev->chip.rev);
data += sprintf(data, "\n");
data += sprintf(data, "register\tbase\twords\twordsize\n");
data += sprintf(data, "csr\t%d\t%d\t%d\n",
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c
index b93731b79903..265e66dba552 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -385,6 +385,9 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
memset(&rxdesc, 0, sizeof(rxdesc));
rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
+ /* Trim buffer to correct size */
+ skb_trim(entry->skb, rxdesc.size);
+
/*
* The data behind the ieee80211 header must be
* aligned on a 4 byte boundary.
@@ -401,16 +404,11 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
(rxdesc.flags & RX_FLAG_IV_STRIPPED))
rt2x00crypto_rx_insert_iv(entry->skb, header_length,
&rxdesc);
- else if (header_length &&
- (rxdesc.size > header_length) &&
- (rxdesc.dev_flags & RXDONE_L2PAD))
+ else if (rxdesc.dev_flags & RXDONE_L2PAD)
rt2x00queue_remove_l2pad(entry->skb, header_length);
else
rt2x00queue_align_payload(entry->skb, header_length);
- /* Trim buffer to correct size */
- skb_trim(entry->skb, rxdesc.size);
-
/*
* Check if the frame was received using HT. In that case,
* the rate is the MCS index and should be passed to mac80211
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c
index abbd857ec759..de549c244ed8 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -187,10 +187,10 @@ void rt2x00mac_stop(struct ieee80211_hw *hw)
EXPORT_SYMBOL_GPL(rt2x00mac_stop);
int rt2x00mac_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct rt2x00_intf *intf = vif_to_intf(vif);
+ struct rt2x00_intf *intf = vif_to_intf(conf->vif);
struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON);
struct queue_entry *entry = NULL;
unsigned int i;
@@ -203,7 +203,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
return -ENODEV;
- switch (vif->type) {
+ switch (conf->type) {
case NL80211_IFTYPE_AP:
/*
* We don't support mixed combinations of
@@ -263,7 +263,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
* increase interface count and start initialization.
*/
- if (vif->type == NL80211_IFTYPE_AP)
+ if (conf->type == NL80211_IFTYPE_AP)
rt2x00dev->intf_ap_count++;
else
rt2x00dev->intf_sta_count++;
@@ -273,16 +273,16 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
mutex_init(&intf->beacon_skb_mutex);
intf->beacon = entry;
- if (vif->type == NL80211_IFTYPE_AP)
- memcpy(&intf->bssid, vif->addr, ETH_ALEN);
- memcpy(&intf->mac, vif->addr, ETH_ALEN);
+ if (conf->type == NL80211_IFTYPE_AP)
+ memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
+ memcpy(&intf->mac, conf->mac_addr, ETH_ALEN);
/*
* The MAC adddress must be configured after the device
* has been initialized. Otherwise the device can reset
* the MAC registers.
*/
- rt2x00lib_config_intf(rt2x00dev, intf, vif->type, intf->mac, NULL);
+ rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL);
/*
* Some filters depend on the current working mode. We can force
@@ -296,10 +296,10 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
EXPORT_SYMBOL_GPL(rt2x00mac_add_interface);
void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct rt2x00_intf *intf = vif_to_intf(vif);
+ struct rt2x00_intf *intf = vif_to_intf(conf->vif);
/*
* Don't allow interfaces to be remove while
@@ -307,11 +307,11 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
* no interface is present.
*/
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
- (vif->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) ||
- (vif->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count))
+ (conf->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) ||
+ (conf->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count))
return;
- if (vif->type == NL80211_IFTYPE_AP)
+ if (conf->type == NL80211_IFTYPE_AP)
rt2x00dev->intf_ap_count--;
else
rt2x00dev->intf_sta_count--;
@@ -555,6 +555,22 @@ int rt2x00mac_get_stats(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL_GPL(rt2x00mac_get_stats);
+int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ unsigned int i;
+
+ for (i = 0; i < rt2x00dev->ops->tx_queues; i++) {
+ stats[i].len = rt2x00dev->tx[i].length;
+ stats[i].limit = rt2x00dev->tx[i].limit;
+ stats[i].count = rt2x00dev->tx[i].count;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_get_tx_stats);
+
void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00pci.c b/trunk/drivers/net/wireless/rt2x00/rt2x00pci.c
index 047123b766fc..0feb4d0e4668 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/trunk/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -41,9 +41,6 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
{
unsigned int i;
- if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
- return 0;
-
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
rt2x00pci_register_read(rt2x00dev, offset, reg);
if (!rt2x00_get_field32(*reg, field))
@@ -272,6 +269,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
struct ieee80211_hw *hw;
struct rt2x00_dev *rt2x00dev;
int retval;
+ u16 chip;
retval = pci_request_regions(pci_dev, pci_name(pci_dev));
if (retval) {
@@ -314,6 +312,12 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI);
+ /*
+ * Determine RT chipset by reading PCI header.
+ */
+ pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip);
+ rt2x00_set_chip_rt(rt2x00dev, chip);
+
retval = rt2x00pci_alloc_reg(rt2x00dev);
if (retval)
goto exit_free_device;
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00pci.h b/trunk/drivers/net/wireless/rt2x00/rt2x00pci.h
index 8149ff68410a..d4f9449ab0a4 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2x00pci.h
+++ b/trunk/drivers/net/wireless/rt2x00/rt2x00pci.h
@@ -27,7 +27,6 @@
#define RT2X00PCI_H
#include
-#include
/*
* This variable should be used with the
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c
index 0b4801a14601..9915a09141ef 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -177,45 +177,55 @@ void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length)
void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length)
{
- unsigned int payload_length = skb->len - header_length;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ unsigned int frame_length = skb->len;
unsigned int header_align = ALIGN_SIZE(skb, 0);
unsigned int payload_align = ALIGN_SIZE(skb, header_length);
- unsigned int l2pad = payload_length ? L2PAD_SIZE(header_length) : 0;
-
- /*
- * Adjust the header alignment if the payload needs to be moved more
- * than the header.
- */
- if (payload_align > header_align)
- header_align += 4;
+ unsigned int l2pad = 4 - (payload_align - header_align);
- /* There is nothing to do if no alignment is needed */
- if (!header_align)
- return;
-
- /* Reserve the amount of space needed in front of the frame */
- skb_push(skb, header_align);
-
- /*
- * Move the header.
- */
- memmove(skb->data, skb->data + header_align, header_length);
+ if (header_align == payload_align) {
+ /*
+ * Both header and payload must be moved the same
+ * amount of bytes to align them properly. This means
+ * we don't use the L2 padding but just move the entire
+ * frame.
+ */
+ rt2x00queue_align_frame(skb);
+ } else if (!payload_align) {
+ /*
+ * Simple L2 padding, only the header needs to be moved,
+ * the payload is already properly aligned.
+ */
+ skb_push(skb, header_align);
+ memmove(skb->data, skb->data + header_align, frame_length);
+ skbdesc->flags |= SKBDESC_L2_PADDED;
+ } else {
+ /*
+ *
+ * Complicated L2 padding, both header and payload need
+ * to be moved. By default we only move to the start
+ * of the buffer, so our header alignment needs to be
+ * increased if there is not enough room for the header
+ * to be moved.
+ */
+ if (payload_align > header_align)
+ header_align += 4;
- /* Move the payload, if present and if required */
- if (payload_length && payload_align)
+ skb_push(skb, header_align);
+ memmove(skb->data, skb->data + header_align, header_length);
memmove(skb->data + header_length + l2pad,
skb->data + header_length + l2pad + payload_align,
- payload_length);
-
- /* Trim the skb to the correct size */
- skb_trim(skb, header_length + l2pad + payload_length);
+ frame_length - header_length);
+ skbdesc->flags |= SKBDESC_L2_PADDED;
+ }
}
void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length)
{
- unsigned int l2pad = L2PAD_SIZE(header_length);
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ unsigned int l2pad = 4 - (header_length & 3);
- if (!l2pad)
+ if (!l2pad || (skbdesc->flags & SKBDESC_L2_PADDED))
return;
memmove(skb->data + l2pad, skb->data, header_length);
@@ -336,9 +346,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
* Header and alignment information.
*/
txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
- if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags) &&
- (entry->skb->len > txdesc->header_length))
- txdesc->l2pad = L2PAD_SIZE(txdesc->header_length);
+ txdesc->l2pad = ALIGN_SIZE(entry->skb, txdesc->header_length);
/*
* Check whether this frame is to be acked.
@@ -379,13 +387,10 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
/*
* Beacons and probe responses require the tsf timestamp
- * to be inserted into the frame, except for a frame that has been injected
- * through a monitor interface. This latter is needed for testing a
- * monitor interface.
+ * to be inserted into the frame.
*/
- if ((ieee80211_is_beacon(hdr->frame_control) ||
- ieee80211_is_probe_resp(hdr->frame_control)) &&
- (!(tx_info->flags & IEEE80211_TX_CTL_INJECTED)))
+ if (ieee80211_is_beacon(hdr->frame_control) ||
+ ieee80211_is_probe_resp(hdr->frame_control))
__set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags);
/*
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h
index c1e482bb37b3..70775e5ba1ac 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -92,6 +92,8 @@ enum data_queue_qid {
* @SKBDESC_DMA_MAPPED_TX: &skb_dma field has been mapped for TX
* @SKBDESC_IV_STRIPPED: Frame contained a IV/EIV provided by
* mac80211 but was stripped for processing by the driver.
+ * @SKBDESC_L2_PADDED: Payload has been padded for 4-byte alignment,
+ * the padded bytes are located between header and payload.
* @SKBDESC_NOT_MAC80211: Frame didn't originate from mac80211,
* don't try to pass it back.
*/
@@ -99,7 +101,8 @@ enum skb_frame_desc_flags {
SKBDESC_DMA_MAPPED_RX = 1 << 0,
SKBDESC_DMA_MAPPED_TX = 1 << 1,
SKBDESC_IV_STRIPPED = 1 << 2,
- SKBDESC_NOT_MAC80211 = 1 << 3,
+ SKBDESC_L2_PADDED = 1 << 3,
+ SKBDESC_NOT_MAC80211 = 1 << 4,
};
/**
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00soc.c b/trunk/drivers/net/wireless/rt2x00/rt2x00soc.c
index 4efdc96010f6..19e684f8ffa1 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2x00soc.c
+++ b/trunk/drivers/net/wireless/rt2x00/rt2x00soc.c
@@ -71,7 +71,9 @@ static int rt2x00soc_alloc_reg(struct rt2x00_dev *rt2x00dev)
return -ENOMEM;
}
-int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops)
+int rt2x00soc_probe(struct platform_device *pdev,
+ const unsigned short chipset,
+ const struct rt2x00_ops *ops)
{
struct ieee80211_hw *hw;
struct rt2x00_dev *rt2x00dev;
@@ -92,7 +94,12 @@ int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops)
rt2x00dev->irq = platform_get_irq(pdev, 0);
rt2x00dev->name = pdev->dev.driver->name;
- rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
+ /*
+ * SoC devices mimic PCI behavior.
+ */
+ rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI);
+
+ rt2x00_set_chip_rt(rt2x00dev, chipset);
retval = rt2x00soc_alloc_reg(rt2x00dev);
if (retval)
diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00soc.h b/trunk/drivers/net/wireless/rt2x00/rt2x00soc.h
index 4739edfe2f00..8a3416624af5 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt2x00soc.h
+++ b/trunk/drivers/net/wireless/rt2x00/rt2x00soc.h
@@ -28,10 +28,18 @@
#define KSEG1ADDR(__ptr) __ptr
+#define __rt2x00soc_probe(__chipset, __ops) \
+static int __rt2x00soc_probe(struct platform_device *pdev) \
+{ \
+ return rt2x00soc_probe(pdev, (__chipset), (__ops)); \
+}
+
/*
* SoC driver handlers.
*/
-int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops);
+int rt2x00soc_probe(struct platform_device *pdev,
+ const unsigned short chipset,
+ const struct rt2x00_ops *ops);
int rt2x00soc_remove(struct platform_device *pdev);
#ifdef CONFIG_PM
int rt2x00soc_suspend(struct platform_device *pdev, pm_message_t state);
diff --git a/trunk/drivers/net/wireless/rt2x00/rt61pci.c b/trunk/drivers/net/wireless/rt2x00/rt61pci.c
index ee9c696fe1d4..0ca589306d71 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/trunk/drivers/net/wireless/rt2x00/rt61pci.c
@@ -637,7 +637,8 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
rt61pci_bbp_read(rt2x00dev, 4, &r4);
rt61pci_bbp_read(rt2x00dev, 77, &r77);
- rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF5325));
+ rt2x00_set_field8(&r3, BBP_R3_SMART_MODE,
+ rt2x00_rf(&rt2x00dev->chip, RF5325));
/*
* Configure the RX antenna.
@@ -683,7 +684,8 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
rt61pci_bbp_read(rt2x00dev, 4, &r4);
rt61pci_bbp_read(rt2x00dev, 77, &r77);
- rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529));
+ rt2x00_set_field8(&r3, BBP_R3_SMART_MODE,
+ rt2x00_rf(&rt2x00dev->chip, RF2529));
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
!test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags));
@@ -831,11 +833,12 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg);
- if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325))
+ if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
+ rt2x00_rf(&rt2x00dev->chip, RF5325))
rt61pci_config_antenna_5x(rt2x00dev, ant);
- else if (rt2x00_rf(rt2x00dev, RF2527))
+ else if (rt2x00_rf(&rt2x00dev->chip, RF2527))
rt61pci_config_antenna_2x(rt2x00dev, ant);
- else if (rt2x00_rf(rt2x00dev, RF2529)) {
+ else if (rt2x00_rf(&rt2x00dev->chip, RF2529)) {
if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags))
rt61pci_config_antenna_2x(rt2x00dev, ant);
else
@@ -876,7 +879,8 @@ static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
- smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527));
+ smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) ||
+ rt2x00_rf(&rt2x00dev->chip, RF2527));
rt61pci_bbp_read(rt2x00dev, 3, &r3);
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
@@ -1131,18 +1135,16 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev,
*/
static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
{
- u16 chip;
char *fw_name;
- pci_read_config_word(to_pci_dev(rt2x00dev->dev), PCI_DEVICE_ID, &chip);
- switch (chip) {
- case RT2561_PCI_ID:
+ switch (rt2x00dev->chip.rt) {
+ case RT2561:
fw_name = FIRMWARE_RT2561;
break;
- case RT2561s_PCI_ID:
+ case RT2561s:
fw_name = FIRMWARE_RT2561s;
break;
- case RT2661_PCI_ID:
+ case RT2661:
fw_name = FIRMWARE_RT2661;
break;
default:
@@ -2297,13 +2299,13 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®);
- rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
- value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
+ rt2x00_set_chip_rf(rt2x00dev, value, reg);
+ rt2x00_print_chip(rt2x00dev);
- if (!rt2x00_rf(rt2x00dev, RF5225) &&
- !rt2x00_rf(rt2x00dev, RF5325) &&
- !rt2x00_rf(rt2x00dev, RF2527) &&
- !rt2x00_rf(rt2x00dev, RF2529)) {
+ if (!rt2x00_rf(&rt2x00dev->chip, RF5225) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF5325) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF2527) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF2529)) {
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
return -ENODEV;
}
@@ -2358,7 +2360,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* the antenna settings should be gathered from the NIC
* eeprom word.
*/
- if (rt2x00_rf(rt2x00dev, RF2529) &&
+ if (rt2x00_rf(&rt2x00dev->chip, RF2529) &&
!test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) {
rt2x00dev->default_ant.rx =
ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED);
@@ -2569,7 +2571,8 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
spec->channels = rf_vals_seq;
}
- if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325)) {
+ if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
+ rt2x00_rf(&rt2x00dev->chip, RF5325)) {
spec->supported_bands |= SUPPORT_BAND_5GHZ;
spec->num_channels = ARRAY_SIZE(rf_vals_seq);
}
@@ -2732,6 +2735,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
.get_stats = rt2x00mac_get_stats,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt61pci_conf_tx,
+ .get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt61pci_get_tsf,
.rfkill_poll = rt2x00mac_rfkill_poll,
};
diff --git a/trunk/drivers/net/wireless/rt2x00/rt61pci.h b/trunk/drivers/net/wireless/rt2x00/rt61pci.h
index ab20c7758824..6f33f7f5668c 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt61pci.h
+++ b/trunk/drivers/net/wireless/rt2x00/rt61pci.h
@@ -27,13 +27,6 @@
#ifndef RT61PCI_H
#define RT61PCI_H
-/*
- * RT chip PCI IDs.
- */
-#define RT2561s_PCI_ID 0x0301
-#define RT2561_PCI_ID 0x0302
-#define RT2661_PCI_ID 0x0401
-
/*
* RF chip defines.
*/
@@ -232,8 +225,6 @@ struct hw_pairwise_ta_entry {
* MAC_CSR0: ASIC revision number.
*/
#define MAC_CSR0 0x3000
-#define MAC_CSR0_REVISION FIELD32(0x0000000f)
-#define MAC_CSR0_CHIPSET FIELD32(0x000ffff0)
/*
* MAC_CSR1: System control register.
diff --git a/trunk/drivers/net/wireless/rt2x00/rt73usb.c b/trunk/drivers/net/wireless/rt2x00/rt73usb.c
index f39a8ed17841..ced3b6ab5e16 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/trunk/drivers/net/wireless/rt2x00/rt73usb.c
@@ -136,8 +136,8 @@ static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
* all others contain 20 bits.
*/
rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS,
- 20 + (rt2x00_rf(rt2x00dev, RF5225) ||
- rt2x00_rf(rt2x00dev, RF2527)));
+ 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
+ rt2x00_rf(&rt2x00dev->chip, RF2527)));
rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0);
rt2x00_set_field32(®, PHY_CSR4_BUSY, 1);
@@ -741,9 +741,11 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev,
rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg);
- if (rt2x00_rf(rt2x00dev, RF5226) || rt2x00_rf(rt2x00dev, RF5225))
+ if (rt2x00_rf(&rt2x00dev->chip, RF5226) ||
+ rt2x00_rf(&rt2x00dev->chip, RF5225))
rt73usb_config_antenna_5x(rt2x00dev, ant);
- else if (rt2x00_rf(rt2x00dev, RF2528) || rt2x00_rf(rt2x00dev, RF2527))
+ else if (rt2x00_rf(&rt2x00dev->chip, RF2528) ||
+ rt2x00_rf(&rt2x00dev->chip, RF2527))
rt73usb_config_antenna_2x(rt2x00dev, ant);
}
@@ -777,7 +779,8 @@ static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
- smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527));
+ smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) ||
+ rt2x00_rf(&rt2x00dev->chip, RF2527));
rt73usb_bbp_read(rt2x00dev, 3, &r3);
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
@@ -1207,7 +1210,8 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000);
reg = 0x000023b0;
- if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527))
+ if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
+ rt2x00_rf(&rt2x00dev->chip, RF2527))
rt2x00_set_field32(®, PHY_CSR1_RF_RPI, 1);
rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg);
@@ -1820,18 +1824,19 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®);
- rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
- value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
+ rt2x00_set_chip(rt2x00dev, RT2571, value, reg);
+ rt2x00_print_chip(rt2x00dev);
- if (!rt2x00_rt(rt2x00dev, RT2573) || (rt2x00_rev(rt2x00dev) == 0)) {
+ if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0x25730) ||
+ rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) {
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
return -ENODEV;
}
- if (!rt2x00_rf(rt2x00dev, RF5226) &&
- !rt2x00_rf(rt2x00dev, RF2528) &&
- !rt2x00_rf(rt2x00dev, RF5225) &&
- !rt2x00_rf(rt2x00dev, RF2527)) {
+ if (!rt2x00_rf(&rt2x00dev->chip, RF5226) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF2528) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF5225) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF2527)) {
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
return -ENODEV;
}
@@ -2076,17 +2081,17 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
spec->supported_bands = SUPPORT_BAND_2GHZ;
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
- if (rt2x00_rf(rt2x00dev, RF2528)) {
+ if (rt2x00_rf(&rt2x00dev->chip, RF2528)) {
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528);
spec->channels = rf_vals_bg_2528;
- } else if (rt2x00_rf(rt2x00dev, RF5226)) {
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF5226)) {
spec->supported_bands |= SUPPORT_BAND_5GHZ;
spec->num_channels = ARRAY_SIZE(rf_vals_5226);
spec->channels = rf_vals_5226;
- } else if (rt2x00_rf(rt2x00dev, RF2527)) {
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) {
spec->num_channels = 14;
spec->channels = rf_vals_5225_2527;
- } else if (rt2x00_rf(rt2x00dev, RF5225)) {
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF5225)) {
spec->supported_bands |= SUPPORT_BAND_5GHZ;
spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527);
spec->channels = rf_vals_5225_2527;
@@ -2244,6 +2249,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
.get_stats = rt2x00mac_get_stats,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt73usb_conf_tx,
+ .get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt73usb_get_tsf,
.rfkill_poll = rt2x00mac_rfkill_poll,
};
@@ -2348,7 +2354,6 @@ static struct usb_device_id rt73usb_device_table[] = {
{ USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) },
/* Buffalo */
{ USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x0411, 0x00d9), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) },
diff --git a/trunk/drivers/net/wireless/rt2x00/rt73usb.h b/trunk/drivers/net/wireless/rt2x00/rt73usb.h
index b4e3ddda06cf..e783a099a8f1 100644
--- a/trunk/drivers/net/wireless/rt2x00/rt73usb.h
+++ b/trunk/drivers/net/wireless/rt2x00/rt73usb.h
@@ -142,8 +142,6 @@ struct hw_pairwise_ta_entry {
* MAC_CSR0: ASIC revision number.
*/
#define MAC_CSR0 0x3000
-#define MAC_CSR0_REVISION FIELD32(0x0000000f)
-#define MAC_CSR0_CHIPSET FIELD32(0x000ffff0)
/*
* MAC_CSR1: System control register.
diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8180.h b/trunk/drivers/net/wireless/rtl818x/rtl8180.h
index de3844fe06d8..8721282a8185 100644
--- a/trunk/drivers/net/wireless/rtl818x/rtl8180.h
+++ b/trunk/drivers/net/wireless/rtl818x/rtl8180.h
@@ -60,6 +60,7 @@ struct rtl8180_priv {
struct rtl818x_csr __iomem *map;
const struct rtl818x_rf_ops *rf;
struct ieee80211_vif *vif;
+ int mode;
/* rtl8180 driver specific */
spinlock_t lock;
diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8180_dev.c b/trunk/drivers/net/wireless/rtl818x/rtl8180_dev.c
index 109ab1baf625..8a40a1439984 100644
--- a/trunk/drivers/net/wireless/rtl818x/rtl8180_dev.c
+++ b/trunk/drivers/net/wireless/rtl818x/rtl8180_dev.c
@@ -82,6 +82,8 @@ static const struct ieee80211_channel rtl818x_channels[] = {
};
+
+
void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
{
struct rtl8180_priv *priv = dev->priv;
@@ -613,6 +615,7 @@ static int rtl8180_start(struct ieee80211_hw *dev)
reg |= RTL818X_CMD_TX_ENABLE;
rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+ priv->mode = NL80211_IFTYPE_MONITOR;
return 0;
err_free_rings:
@@ -630,6 +633,8 @@ static void rtl8180_stop(struct ieee80211_hw *dev)
u8 reg;
int i;
+ priv->mode = NL80211_IFTYPE_UNSPECIFIED;
+
rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
reg = rtl818x_ioread8(priv, &priv->map->CMD);
@@ -652,39 +657,38 @@ static void rtl8180_stop(struct ieee80211_hw *dev)
}
static int rtl8180_add_interface(struct ieee80211_hw *dev,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
- /*
- * We only support one active interface at a time.
- */
- if (priv->vif)
- return -EBUSY;
+ if (priv->mode != NL80211_IFTYPE_MONITOR)
+ return -EOPNOTSUPP;
- switch (vif->type) {
+ switch (conf->type) {
case NL80211_IFTYPE_STATION:
+ priv->mode = conf->type;
break;
default:
return -EOPNOTSUPP;
}
- priv->vif = vif;
+ priv->vif = conf->vif;
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0],
- le32_to_cpu(*(__le32 *)vif->addr));
+ le32_to_cpu(*(__le32 *)conf->mac_addr));
rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4],
- le16_to_cpu(*(__le16 *)(vif->addr + 4)));
+ le16_to_cpu(*(__le16 *)(conf->mac_addr + 4)));
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
return 0;
}
static void rtl8180_remove_interface(struct ieee80211_hw *dev,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
+ priv->mode = NL80211_IFTYPE_MONITOR;
priv->vif = NULL;
}
@@ -761,14 +765,6 @@ static void rtl8180_configure_filter(struct ieee80211_hw *dev,
rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf);
}
-static u64 rtl8180_get_tsf(struct ieee80211_hw *dev)
-{
- struct rtl8180_priv *priv = dev->priv;
-
- return rtl818x_ioread32(priv, &priv->map->TSFT[0]) |
- (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32;
-}
-
static const struct ieee80211_ops rtl8180_ops = {
.tx = rtl8180_tx,
.start = rtl8180_start,
@@ -779,7 +775,6 @@ static const struct ieee80211_ops rtl8180_ops = {
.bss_info_changed = rtl8180_bss_info_changed,
.prepare_multicast = rtl8180_prepare_multicast,
.configure_filter = rtl8180_configure_filter,
- .get_tsf = rtl8180_get_tsf,
};
static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom)
diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8187.h b/trunk/drivers/net/wireless/rtl818x/rtl8187.h
index 6bb32112e65c..6af0f3f71f3a 100644
--- a/trunk/drivers/net/wireless/rtl818x/rtl8187.h
+++ b/trunk/drivers/net/wireless/rtl818x/rtl8187.h
@@ -92,7 +92,7 @@ struct rtl8187_priv {
struct rtl818x_csr *map;
const struct rtl818x_rf_ops *rf;
struct ieee80211_vif *vif;
-
+ int mode;
/* The mutex protects the TX loopback state.
* Any attempt to set channels concurrently locks the device.
*/
diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8187_dev.c b/trunk/drivers/net/wireless/rtl818x/rtl8187_dev.c
index 0fb850e0c656..7ba3052b0708 100644
--- a/trunk/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/trunk/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -1019,30 +1019,31 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
}
static int rtl8187_add_interface(struct ieee80211_hw *dev,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct rtl8187_priv *priv = dev->priv;
int i;
int ret = -EOPNOTSUPP;
mutex_lock(&priv->conf_mutex);
- if (priv->vif)
+ if (priv->mode != NL80211_IFTYPE_MONITOR)
goto exit;
- switch (vif->type) {
+ switch (conf->type) {
case NL80211_IFTYPE_STATION:
+ priv->mode = conf->type;
break;
default:
goto exit;
}
ret = 0;
- priv->vif = vif;
+ priv->vif = conf->vif;
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
for (i = 0; i < ETH_ALEN; i++)
rtl818x_iowrite8(priv, &priv->map->MAC[i],
- ((u8 *)vif->addr)[i]);
+ ((u8 *)conf->mac_addr)[i]);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
exit:
@@ -1051,10 +1052,11 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev,
}
static void rtl8187_remove_interface(struct ieee80211_hw *dev,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct rtl8187_priv *priv = dev->priv;
mutex_lock(&priv->conf_mutex);
+ priv->mode = NL80211_IFTYPE_MONITOR;
priv->vif = NULL;
mutex_unlock(&priv->conf_mutex);
}
@@ -1266,14 +1268,6 @@ static int rtl8187_conf_tx(struct ieee80211_hw *dev, u16 queue,
return 0;
}
-static u64 rtl8187_get_tsf(struct ieee80211_hw *dev)
-{
- struct rtl8187_priv *priv = dev->priv;
-
- return rtl818x_ioread32(priv, &priv->map->TSFT[0]) |
- (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32;
-}
-
static const struct ieee80211_ops rtl8187_ops = {
.tx = rtl8187_tx,
.start = rtl8187_start,
@@ -1285,8 +1279,7 @@ static const struct ieee80211_ops rtl8187_ops = {
.prepare_multicast = rtl8187_prepare_multicast,
.configure_filter = rtl8187_configure_filter,
.conf_tx = rtl8187_conf_tx,
- .rfkill_poll = rtl8187_rfkill_poll,
- .get_tsf = rtl8187_get_tsf,
+ .rfkill_poll = rtl8187_rfkill_poll
};
static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom)
@@ -1373,6 +1366,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
+ priv->mode = NL80211_IFTYPE_MONITOR;
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_RX_INCLUDES_FCS;
diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8187_leds.c b/trunk/drivers/net/wireless/rtl818x/rtl8187_leds.c
index 4637337d5ce6..ded44c045eb2 100644
--- a/trunk/drivers/net/wireless/rtl818x/rtl8187_leds.c
+++ b/trunk/drivers/net/wireless/rtl818x/rtl8187_leds.c
@@ -33,7 +33,7 @@ static void led_turn_on(struct work_struct *work)
struct rtl8187_led *led = &priv->led_tx;
/* Don't change the LED, when the device is down. */
- if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED)
+ if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
return ;
/* Skip if the LED is not registered. */
@@ -71,7 +71,7 @@ static void led_turn_off(struct work_struct *work)
struct rtl8187_led *led = &priv->led_tx;
/* Don't change the LED, when the device is down. */
- if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED)
+ if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
return ;
/* Skip if the LED is not registered. */
@@ -241,5 +241,5 @@ void rtl8187_leds_exit(struct ieee80211_hw *dev)
cancel_delayed_work_sync(&priv->led_off);
cancel_delayed_work_sync(&priv->led_on);
}
-#endif /* def CONFIG_RTL8187_LEDS */
+#endif /* def CONFIG_RTL8187_LED */
diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8187_leds.h b/trunk/drivers/net/wireless/rtl818x/rtl8187_leds.h
index d743c96d4a20..efe8041bdda4 100644
--- a/trunk/drivers/net/wireless/rtl818x/rtl8187_leds.h
+++ b/trunk/drivers/net/wireless/rtl818x/rtl8187_leds.h
@@ -54,6 +54,6 @@ struct rtl8187_led {
void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code);
void rtl8187_leds_exit(struct ieee80211_hw *dev);
-#endif /* def CONFIG_RTL8187_LEDS */
+#endif /* def CONFIG_RTL8187_LED */
#endif /* RTL8187_LED_H */
diff --git a/trunk/drivers/net/wireless/wl12xx/Makefile b/trunk/drivers/net/wireless/wl12xx/Makefile
index f47ec94c16dc..62e37ad01cc0 100644
--- a/trunk/drivers/net/wireless/wl12xx/Makefile
+++ b/trunk/drivers/net/wireless/wl12xx/Makefile
@@ -10,7 +10,5 @@ obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o
wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \
wl1271_event.o wl1271_tx.o wl1271_rx.o \
wl1271_ps.o wl1271_acx.o wl1271_boot.o \
- wl1271_init.o wl1271_debugfs.o wl1271_io.o
-
-wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o
+ wl1271_init.o wl1271_debugfs.o
obj-$(CONFIG_WL1271) += wl1271.o
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1251.h b/trunk/drivers/net/wireless/wl12xx/wl1251.h
index 37c61c19cae5..054533f7a124 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1251.h
+++ b/trunk/drivers/net/wireless/wl12xx/wl1251.h
@@ -247,7 +247,6 @@ struct wl1251_debugfs {
struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data;
struct dentry *tx_queue_len;
- struct dentry *tx_queue_status;
struct dentry *retry_count;
struct dentry *excessive_retries;
@@ -341,6 +340,9 @@ struct wl1251 {
/* Are we currently scanning */
bool scanning;
+ /* Our association ID */
+ u16 aid;
+
/* Default key (for WEP) */
u32 default_key;
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1251_acx.c b/trunk/drivers/net/wireless/wl12xx/wl1251_acx.c
index beff084040b5..acfa086dbfc5 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1251_acx.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1251_acx.c
@@ -976,72 +976,3 @@ int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim)
kfree(acx);
return ret;
}
-
-int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max,
- u8 aifs, u16 txop)
-{
- struct wl1251_acx_ac_cfg *acx;
- int ret = 0;
-
- wl1251_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d "
- "aifs %d txop %d", ac, cw_min, cw_max, aifs, txop);
-
- acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-
- if (!acx) {
- ret = -ENOMEM;
- goto out;
- }
-
- acx->ac = ac;
- acx->cw_min = cw_min;
- acx->cw_max = cw_max;
- acx->aifsn = aifs;
- acx->txop_limit = txop;
-
- ret = wl1251_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx));
- if (ret < 0) {
- wl1251_warning("acx ac cfg failed: %d", ret);
- goto out;
- }
-
-out:
- kfree(acx);
- return ret;
-}
-
-int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue,
- enum wl1251_acx_channel_type type,
- u8 tsid, enum wl1251_acx_ps_scheme ps_scheme,
- enum wl1251_acx_ack_policy ack_policy)
-{
- struct wl1251_acx_tid_cfg *acx;
- int ret = 0;
-
- wl1251_debug(DEBUG_ACX, "acx tid cfg %d type %d tsid %d "
- "ps_scheme %d ack_policy %d", queue, type, tsid,
- ps_scheme, ack_policy);
-
- acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-
- if (!acx) {
- ret = -ENOMEM;
- goto out;
- }
-
- acx->queue = queue;
- acx->type = type;
- acx->tsid = tsid;
- acx->ps_scheme = ps_scheme;
- acx->ack_policy = ack_policy;
-
- ret = wl1251_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx));
- if (ret < 0) {
- wl1251_warning("acx tid cfg failed: %d", ret);
- goto out;
- }
-
-out:
- kfree(acx);
- return ret;
-}
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1251_acx.h b/trunk/drivers/net/wireless/wl12xx/wl1251_acx.h
index 26160c45784c..652371432cd8 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1251_acx.h
+++ b/trunk/drivers/net/wireless/wl12xx/wl1251_acx.h
@@ -1166,87 +1166,6 @@ struct wl1251_acx_wr_tbtt_and_dtim {
u8 padding;
} __attribute__ ((packed));
-struct wl1251_acx_ac_cfg {
- struct acx_header header;
-
- /*
- * Access Category - The TX queue's access category
- * (refer to AccessCategory_enum)
- */
- u8 ac;
-
- /*
- * The contention window minimum size (in slots) for
- * the access class.
- */
- u8 cw_min;
-
- /*
- * The contention window maximum size (in slots) for
- * the access class.
- */
- u16 cw_max;
-
- /* The AIF value (in slots) for the access class. */
- u8 aifsn;
-
- u8 reserved;
-
- /* The TX Op Limit (in microseconds) for the access class. */
- u16 txop_limit;
-} __attribute__ ((packed));
-
-
-enum wl1251_acx_channel_type {
- CHANNEL_TYPE_DCF = 0,
- CHANNEL_TYPE_EDCF = 1,
- CHANNEL_TYPE_HCCA = 2,
-};
-
-enum wl1251_acx_ps_scheme {
- /* regular ps: simple sending of packets */
- WL1251_ACX_PS_SCHEME_LEGACY = 0,
-
- /* sending a packet triggers a unscheduled apsd downstream */
- WL1251_ACX_PS_SCHEME_UPSD_TRIGGER = 1,
-
- /* a pspoll packet will be sent before every data packet */
- WL1251_ACX_PS_SCHEME_LEGACY_PSPOLL = 2,
-
- /* scheduled apsd mode */
- WL1251_ACX_PS_SCHEME_SAPSD = 3,
-};
-
-enum wl1251_acx_ack_policy {
- WL1251_ACX_ACK_POLICY_LEGACY = 0,
- WL1251_ACX_ACK_POLICY_NO_ACK = 1,
- WL1251_ACX_ACK_POLICY_BLOCK = 2,
-};
-
-struct wl1251_acx_tid_cfg {
- struct acx_header header;
-
- /* tx queue id number (0-7) */
- u8 queue;
-
- /* channel access type for the queue, enum wl1251_acx_channel_type */
- u8 type;
-
- /* EDCA: ac index (0-3), HCCA: traffic stream id (8-15) */
- u8 tsid;
-
- /* ps scheme of the specified queue, enum wl1251_acx_ps_scheme */
- u8 ps_scheme;
-
- /* the tx queue ack policy, enum wl1251_acx_ack_policy */
- u8 ack_policy;
-
- u8 padding[3];
-
- /* not supported */
- u32 apsdconf[2];
-} __attribute__ ((packed));
-
/*************************************************************************
Host Interrupt Register (WiLink -> Host)
@@ -1403,11 +1322,5 @@ int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime);
int wl1251_acx_rate_policies(struct wl1251 *wl);
int wl1251_acx_mem_cfg(struct wl1251 *wl);
int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim);
-int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max,
- u8 aifs, u16 txop);
-int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue,
- enum wl1251_acx_channel_type type,
- u8 tsid, enum wl1251_acx_ps_scheme ps_scheme,
- enum wl1251_acx_ack_policy ack_policy);
#endif /* __WL1251_ACX_H__ */
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1251_cmd.c b/trunk/drivers/net/wireless/wl12xx/wl1251_cmd.c
index 0320b478bb3f..770f260726bd 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1251_cmd.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1251_cmd.c
@@ -410,86 +410,3 @@ int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id,
kfree(cmd);
return ret;
}
-
-int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
- struct ieee80211_channel *channels[],
- unsigned int n_channels, unsigned int n_probes)
-{
- struct wl1251_cmd_scan *cmd;
- int i, ret = 0;
-
- wl1251_debug(DEBUG_CMD, "cmd scan");
-
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
-
- cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
- cmd->params.rx_filter_options = cpu_to_le32(CFG_RX_PRSP_EN |
- CFG_RX_MGMT_EN |
- CFG_RX_BCN_EN);
- cmd->params.scan_options = 0;
- cmd->params.num_channels = n_channels;
- cmd->params.num_probe_requests = n_probes;
- cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */
- cmd->params.tid_trigger = 0;
-
- for (i = 0; i < n_channels; i++) {
- cmd->channels[i].min_duration =
- cpu_to_le32(WL1251_SCAN_MIN_DURATION);
- cmd->channels[i].max_duration =
- cpu_to_le32(WL1251_SCAN_MAX_DURATION);
- memset(&cmd->channels[i].bssid_lsb, 0xff, 4);
- memset(&cmd->channels[i].bssid_msb, 0xff, 2);
- cmd->channels[i].early_termination = 0;
- cmd->channels[i].tx_power_att = 0;
- cmd->channels[i].channel = channels[i]->hw_value;
- }
-
- cmd->params.ssid_len = ssid_len;
- if (ssid)
- memcpy(cmd->params.ssid, ssid, ssid_len);
-
- ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd));
- if (ret < 0) {
- wl1251_error("cmd scan failed: %d", ret);
- goto out;
- }
-
- wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));
-
- if (cmd->header.status != CMD_STATUS_SUCCESS) {
- wl1251_error("cmd scan status wasn't success: %d",
- cmd->header.status);
- ret = -EIO;
- goto out;
- }
-
-out:
- kfree(cmd);
- return ret;
-}
-
-int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout)
-{
- struct wl1251_cmd_trigger_scan_to *cmd;
- int ret;
-
- wl1251_debug(DEBUG_CMD, "cmd trigger scan to");
-
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
-
- cmd->timeout = timeout;
-
- ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd));
- if (ret < 0) {
- wl1251_error("cmd trigger scan to failed: %d", ret);
- goto out;
- }
-
-out:
- kfree(cmd);
- return ret;
-}
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1251_cmd.h b/trunk/drivers/net/wireless/wl12xx/wl1251_cmd.h
index 4ad67cae94d2..dff798ad0ef5 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1251_cmd.h
+++ b/trunk/drivers/net/wireless/wl12xx/wl1251_cmd.h
@@ -27,8 +27,6 @@
#include "wl1251.h"
-#include
-
struct acx_header;
int wl1251_cmd_send(struct wl1251 *wl, u16 type, void *buf, size_t buf_len);
@@ -45,10 +43,6 @@ int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer,
size_t len);
int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id,
void *buf, size_t buf_len);
-int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
- struct ieee80211_channel *channels[],
- unsigned int n_channels, unsigned int n_probes);
-int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout);
/* unit ms */
#define WL1251_COMMAND_TIMEOUT 2000
@@ -169,12 +163,8 @@ struct cmd_read_write_memory {
#define CMDMBOX_HEADER_LEN 4
#define CMDMBOX_INFO_ELEM_HEADER_LEN 4
-#define WL1251_SCAN_MIN_DURATION 30000
-#define WL1251_SCAN_MAX_DURATION 60000
-
-#define WL1251_SCAN_NUM_PROBES 3
-struct wl1251_scan_parameters {
+struct basic_scan_parameters {
u32 rx_config_options;
u32 rx_filter_options;
@@ -199,11 +189,11 @@ struct wl1251_scan_parameters {
u8 tid_trigger;
u8 ssid_len;
- u8 ssid[32];
+ u32 ssid[8];
} __attribute__ ((packed));
-struct wl1251_scan_ch_parameters {
+struct basic_scan_channel_parameters {
u32 min_duration; /* in TU */
u32 max_duration; /* in TU */
u32 bssid_lsb;
@@ -223,11 +213,11 @@ struct wl1251_scan_ch_parameters {
/* SCAN parameters */
#define SCAN_MAX_NUM_OF_CHANNELS 16
-struct wl1251_cmd_scan {
+struct cmd_scan {
struct wl1251_cmd_header header;
- struct wl1251_scan_parameters params;
- struct wl1251_scan_ch_parameters channels[SCAN_MAX_NUM_OF_CHANNELS];
+ struct basic_scan_parameters params;
+ struct basic_scan_channel_parameters channels[SCAN_MAX_NUM_OF_CHANNELS];
} __attribute__ ((packed));
enum {
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1251_debugfs.c b/trunk/drivers/net/wireless/wl12xx/wl1251_debugfs.c
index 0ccba57fb9fb..a00723059f83 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1251_debugfs.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1251_debugfs.c
@@ -237,27 +237,6 @@ static const struct file_operations tx_queue_len_ops = {
.open = wl1251_open_file_generic,
};
-static ssize_t tx_queue_status_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct wl1251 *wl = file->private_data;
- char buf[3], status;
- int len;
-
- if (wl->tx_queue_stopped)
- status = 's';
- else
- status = 'r';
-
- len = scnprintf(buf, sizeof(buf), "%c\n", status);
- return simple_read_from_buffer(userbuf, count, ppos, buf, len);
-}
-
-static const struct file_operations tx_queue_status_ops = {
- .read = tx_queue_status_read,
- .open = wl1251_open_file_generic,
-};
-
static void wl1251_debugfs_delete_files(struct wl1251 *wl)
{
DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow);
@@ -352,7 +331,6 @@ static void wl1251_debugfs_delete_files(struct wl1251 *wl)
DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data);
DEBUGFS_DEL(tx_queue_len);
- DEBUGFS_DEL(tx_queue_status);
DEBUGFS_DEL(retry_count);
DEBUGFS_DEL(excessive_retries);
}
@@ -453,7 +431,6 @@ static int wl1251_debugfs_add_files(struct wl1251 *wl)
DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data);
DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir);
- DEBUGFS_ADD(tx_queue_status, wl->debugfs.rootdir);
DEBUGFS_ADD(retry_count, wl->debugfs.rootdir);
DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir);
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1251_init.c b/trunk/drivers/net/wireless/wl12xx/wl1251_init.c
index 5aad56ea7153..5cb573383eeb 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1251_init.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1251_init.c
@@ -294,11 +294,6 @@ static int wl1251_hw_init_tx_queue_config(struct wl1251 *wl)
goto out;
}
- wl1251_acx_ac_cfg(wl, AC_BE, CWMIN_BE, CWMAX_BE, AIFS_DIFS, TXOP_BE);
- wl1251_acx_ac_cfg(wl, AC_BK, CWMIN_BK, CWMAX_BK, AIFS_DIFS, TXOP_BK);
- wl1251_acx_ac_cfg(wl, AC_VI, CWMIN_VI, CWMAX_VI, AIFS_DIFS, TXOP_VI);
- wl1251_acx_ac_cfg(wl, AC_VO, CWMIN_VO, CWMAX_VO, AIFS_DIFS, TXOP_VO);
-
out:
kfree(config);
return ret;
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1251_init.h b/trunk/drivers/net/wireless/wl12xx/wl1251_init.h
index 269cefb3e7d4..b3b25ec885ea 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1251_init.h
+++ b/trunk/drivers/net/wireless/wl12xx/wl1251_init.h
@@ -26,53 +26,6 @@
#include "wl1251.h"
-enum {
- /* best effort/legacy */
- AC_BE = 0,
-
- /* background */
- AC_BK = 1,
-
- /* video */
- AC_VI = 2,
-
- /* voice */
- AC_VO = 3,
-
- /* broadcast dummy access category */
- AC_BCAST = 4,
-
- NUM_ACCESS_CATEGORIES = 4
-};
-
-/* following are defult values for the IE fields*/
-#define CWMIN_BK 15
-#define CWMIN_BE 15
-#define CWMIN_VI 7
-#define CWMIN_VO 3
-#define CWMAX_BK 1023
-#define CWMAX_BE 63
-#define CWMAX_VI 15
-#define CWMAX_VO 7
-
-/* slot number setting to start transmission at PIFS interval */
-#define AIFS_PIFS 1
-
-/*
- * slot number setting to start transmission at DIFS interval - normal DCF
- * access
- */
-#define AIFS_DIFS 2
-
-#define AIFSN_BK 7
-#define AIFSN_BE 3
-#define AIFSN_VI AIFS_PIFS
-#define AIFSN_VO AIFS_PIFS
-#define TXOP_BK 0
-#define TXOP_BE 0
-#define TXOP_VI 3008
-#define TXOP_VO 1504
-
int wl1251_hw_init_hwenc_config(struct wl1251 *wl);
int wl1251_hw_init_templates_config(struct wl1251 *wl);
int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter);
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1251_main.c b/trunk/drivers/net/wireless/wl12xx/wl1251_main.c
index 24ae6a360ac8..2f50a256efa5 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -395,7 +395,6 @@ static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
* the queue here, otherwise the queue will get too long.
*/
if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_MAX_LENGTH) {
- wl1251_debug(DEBUG_TX, "op_tx: tx_queue full, stop queues");
ieee80211_stop_queues(wl->hw);
/*
@@ -511,13 +510,13 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
}
static int wl1251_op_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct wl1251 *wl = hw->priv;
int ret = 0;
wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
- vif->type, vif->addr);
+ conf->type, conf->mac_addr);
mutex_lock(&wl->mutex);
if (wl->vif) {
@@ -525,9 +524,9 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw,
goto out;
}
- wl->vif = vif;
+ wl->vif = conf->vif;
- switch (vif->type) {
+ switch (conf->type) {
case NL80211_IFTYPE_STATION:
wl->bss_type = BSS_TYPE_STA_BSS;
break;
@@ -539,8 +538,8 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw,
goto out;
}
- if (memcmp(wl->mac_addr, vif->addr, ETH_ALEN)) {
- memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
+ if (memcmp(wl->mac_addr, conf->mac_addr, ETH_ALEN)) {
+ memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
ret = wl1251_acx_station_id(wl);
if (ret < 0)
@@ -553,7 +552,7 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw,
}
static void wl1251_op_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct wl1251 *wl = hw->priv;
@@ -563,25 +562,43 @@ static void wl1251_op_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&wl->mutex);
}
-static int wl1251_build_qos_null_data(struct wl1251 *wl)
+static int wl1251_build_null_data(struct wl1251 *wl)
{
- struct ieee80211_qos_hdr template;
+ struct wl12xx_null_data_template template;
- memset(&template, 0, sizeof(template));
+ if (!is_zero_ether_addr(wl->bssid)) {
+ memcpy(template.header.da, wl->bssid, ETH_ALEN);
+ memcpy(template.header.bssid, wl->bssid, ETH_ALEN);
+ } else {
+ memset(template.header.da, 0xff, ETH_ALEN);
+ memset(template.header.bssid, 0xff, ETH_ALEN);
+ }
+
+ memcpy(template.header.sa, wl->mac_addr, ETH_ALEN);
+ template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
+ IEEE80211_STYPE_NULLFUNC |
+ IEEE80211_FCTL_TODS);
+
+ return wl1251_cmd_template_set(wl, CMD_NULL_DATA, &template,
+ sizeof(template));
+
+}
+
+static int wl1251_build_ps_poll(struct wl1251 *wl, u16 aid)
+{
+ struct wl12xx_ps_poll_template template;
- memcpy(template.addr1, wl->bssid, ETH_ALEN);
- memcpy(template.addr2, wl->mac_addr, ETH_ALEN);
- memcpy(template.addr3, wl->bssid, ETH_ALEN);
+ memcpy(template.bssid, wl->bssid, ETH_ALEN);
+ memcpy(template.ta, wl->mac_addr, ETH_ALEN);
- template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
- IEEE80211_STYPE_QOS_NULLFUNC |
- IEEE80211_FCTL_TODS);
+ /* aid in PS-Poll has its two MSBs each set to 1 */
+ template.aid = cpu_to_le16(1 << 15 | 1 << 14 | aid);
- /* FIXME: not sure what priority to use here */
- template.qos_ctrl = cpu_to_le16(0);
+ template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL);
- return wl1251_cmd_template_set(wl, CMD_QOS_NULL_DATA, &template,
+ return wl1251_cmd_template_set(wl, CMD_PS_POLL, &template,
sizeof(template));
+
}
static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
@@ -617,34 +634,26 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
wl->psm_requested = true;
- wl->dtim_period = conf->ps_dtim_period;
-
- ret = wl1251_acx_wr_tbtt_and_dtim(wl, wl->beacon_int,
- wl->dtim_period);
-
/*
- * mac80211 enables PSM only if we're already associated.
+ * We enter PSM only if we're already associated.
+ * If we're not, we'll enter it when joining an SSID,
+ * through the bss_info_changed() hook.
*/
ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
- if (ret < 0)
- goto out_sleep;
} else if (!(conf->flags & IEEE80211_CONF_PS) &&
wl->psm_requested) {
wl1251_debug(DEBUG_PSM, "psm disabled");
wl->psm_requested = false;
- if (wl->psm) {
+ if (wl->psm)
ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE);
- if (ret < 0)
- goto out_sleep;
- }
}
if (conf->power_level != wl->power_level) {
ret = wl1251_acx_tx_power(wl, conf->power_level);
if (ret < 0)
- goto out_sleep;
+ goto out;
wl->power_level = conf->power_level;
}
@@ -855,61 +864,199 @@ static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return ret;
}
-static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
- struct cfg80211_scan_request *req)
+static int wl1251_build_basic_rates(char *rates)
{
- struct wl1251 *wl = hw->priv;
- struct sk_buff *skb;
- size_t ssid_len = 0;
- u8 *ssid = NULL;
- int ret;
+ u8 index = 0;
- wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan");
+ rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
+ rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
+ rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
+ rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
- if (req->n_ssids) {
- ssid = req->ssids[0].ssid;
- ssid_len = req->ssids[0].ssid_len;
+ return index;
+}
+
+static int wl1251_build_extended_rates(char *rates)
+{
+ u8 index = 0;
+
+ rates[index++] = IEEE80211_OFDM_RATE_6MB;
+ rates[index++] = IEEE80211_OFDM_RATE_9MB;
+ rates[index++] = IEEE80211_OFDM_RATE_12MB;
+ rates[index++] = IEEE80211_OFDM_RATE_18MB;
+ rates[index++] = IEEE80211_OFDM_RATE_24MB;
+ rates[index++] = IEEE80211_OFDM_RATE_36MB;
+ rates[index++] = IEEE80211_OFDM_RATE_48MB;
+ rates[index++] = IEEE80211_OFDM_RATE_54MB;
+
+ return index;
+}
+
+
+static int wl1251_build_probe_req(struct wl1251 *wl, u8 *ssid, size_t ssid_len)
+{
+ struct wl12xx_probe_req_template template;
+ struct wl12xx_ie_rates *rates;
+ char *ptr;
+ u16 size;
+
+ ptr = (char *)&template;
+ size = sizeof(struct ieee80211_header);
+
+ memset(template.header.da, 0xff, ETH_ALEN);
+ memset(template.header.bssid, 0xff, ETH_ALEN);
+ memcpy(template.header.sa, wl->mac_addr, ETH_ALEN);
+ template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
+
+ /* IEs */
+ /* SSID */
+ template.ssid.header.id = WLAN_EID_SSID;
+ template.ssid.header.len = ssid_len;
+ if (ssid_len && ssid)
+ memcpy(template.ssid.ssid, ssid, ssid_len);
+ size += sizeof(struct wl12xx_ie_header) + ssid_len;
+ ptr += size;
+
+ /* Basic Rates */
+ rates = (struct wl12xx_ie_rates *)ptr;
+ rates->header.id = WLAN_EID_SUPP_RATES;
+ rates->header.len = wl1251_build_basic_rates(rates->rates);
+ size += sizeof(struct wl12xx_ie_header) + rates->header.len;
+ ptr += sizeof(struct wl12xx_ie_header) + rates->header.len;
+
+ /* Extended rates */
+ rates = (struct wl12xx_ie_rates *)ptr;
+ rates->header.id = WLAN_EID_EXT_SUPP_RATES;
+ rates->header.len = wl1251_build_extended_rates(rates->rates);
+ size += sizeof(struct wl12xx_ie_header) + rates->header.len;
+
+ wl1251_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size);
+
+ return wl1251_cmd_template_set(wl, CMD_PROBE_REQ, &template,
+ size);
+}
+
+static int wl1251_hw_scan(struct wl1251 *wl, u8 *ssid, size_t len,
+ u8 active_scan, u8 high_prio, u8 num_channels,
+ u8 probe_requests)
+{
+ struct wl1251_cmd_trigger_scan_to *trigger = NULL;
+ struct cmd_scan *params = NULL;
+ int i, ret;
+ u16 scan_options = 0;
+
+ if (wl->scanning)
+ return -EINVAL;
+
+ params = kzalloc(sizeof(*params), GFP_KERNEL);
+ if (!params)
+ return -ENOMEM;
+
+ params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
+ params->params.rx_filter_options =
+ cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN);
+
+ /* High priority scan */
+ if (!active_scan)
+ scan_options |= SCAN_PASSIVE;
+ if (high_prio)
+ scan_options |= SCAN_PRIORITY_HIGH;
+ params->params.scan_options = scan_options;
+
+ params->params.num_channels = num_channels;
+ params->params.num_probe_requests = probe_requests;
+ params->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */
+ params->params.tid_trigger = 0;
+
+ for (i = 0; i < num_channels; i++) {
+ params->channels[i].min_duration = cpu_to_le32(30000);
+ params->channels[i].max_duration = cpu_to_le32(60000);
+ memset(¶ms->channels[i].bssid_lsb, 0xff, 4);
+ memset(¶ms->channels[i].bssid_msb, 0xff, 2);
+ params->channels[i].early_termination = 0;
+ params->channels[i].tx_power_att = 0;
+ params->channels[i].channel = i + 1;
+ memset(params->channels[i].pad, 0, 3);
}
- mutex_lock(&wl->mutex);
+ for (i = num_channels; i < SCAN_MAX_NUM_OF_CHANNELS; i++)
+ memset(¶ms->channels[i], 0,
+ sizeof(struct basic_scan_channel_parameters));
- if (wl->scanning) {
- wl1251_debug(DEBUG_SCAN, "scan already in progress");
- ret = -EINVAL;
+ if (len && ssid) {
+ params->params.ssid_len = len;
+ memcpy(params->params.ssid, ssid, len);
+ } else {
+ params->params.ssid_len = 0;
+ memset(params->params.ssid, 0, 32);
+ }
+
+ ret = wl1251_build_probe_req(wl, ssid, len);
+ if (ret < 0) {
+ wl1251_error("PROBE request template failed");
goto out;
}
- ret = wl1251_ps_elp_wakeup(wl);
- if (ret < 0)
+ trigger = kzalloc(sizeof(*trigger), GFP_KERNEL);
+ if (!trigger)
goto out;
- skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len,
- req->ie, req->ie_len);
- if (!skb) {
- ret = -ENOMEM;
+ trigger->timeout = 0;
+
+ ret = wl1251_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger,
+ sizeof(*trigger));
+ if (ret < 0) {
+ wl1251_error("trigger scan to failed for hw scan");
goto out;
}
- ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, skb->data,
- skb->len);
- dev_kfree_skb(skb);
- if (ret < 0)
- goto out_sleep;
+ wl1251_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params));
+
+ wl->scanning = true;
- ret = wl1251_cmd_trigger_scan_to(wl, 0);
+ ret = wl1251_cmd_send(wl, CMD_SCAN, params, sizeof(*params));
if (ret < 0)
- goto out_sleep;
+ wl1251_error("SCAN failed");
- wl->scanning = true;
+ wl1251_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params));
- ret = wl1251_cmd_scan(wl, ssid, ssid_len, req->channels,
- req->n_channels, WL1251_SCAN_NUM_PROBES);
- if (ret < 0) {
+ if (params->header.status != CMD_STATUS_SUCCESS) {
+ wl1251_error("TEST command answer error: %d",
+ params->header.status);
wl->scanning = false;
- goto out_sleep;
+ ret = -EIO;
+ goto out;
}
-out_sleep:
+out:
+ kfree(params);
+ return ret;
+
+}
+
+static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
+ struct cfg80211_scan_request *req)
+{
+ struct wl1251 *wl = hw->priv;
+ int ret;
+ u8 *ssid = NULL;
+ size_t ssid_len = 0;
+
+ wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan");
+
+ if (req->n_ssids) {
+ ssid = req->ssids[0].ssid;
+ ssid_len = req->ssids[0].ssid_len;
+ }
+
+ mutex_lock(&wl->mutex);
+
+ ret = wl1251_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1251_hw_scan(hw->priv, ssid, ssid_len, 1, 0, 13, 3);
+
wl1251_ps_elp_sleep(wl);
out:
@@ -946,8 +1093,9 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *bss_conf,
u32 changed)
{
+ enum wl1251_cmd_ps_mode mode;
struct wl1251 *wl = hw->priv;
- struct sk_buff *beacon, *skb;
+ struct sk_buff *beacon;
int ret;
wl1251_debug(DEBUG_MAC80211, "mac80211 bss info changed");
@@ -961,17 +1109,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_BSSID) {
memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
- skb = ieee80211_nullfunc_get(wl->hw, wl->vif);
- if (!skb)
- goto out_sleep;
-
- ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA,
- skb->data, skb->len);
- dev_kfree_skb(skb);
- if (ret < 0)
- goto out_sleep;
-
- ret = wl1251_build_qos_null_data(wl);
+ ret = wl1251_build_null_data(wl);
if (ret < 0)
goto out;
@@ -986,21 +1124,27 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_ASSOC) {
if (bss_conf->assoc) {
wl->beacon_int = bss_conf->beacon_int;
+ wl->dtim_period = bss_conf->dtim_period;
- skb = ieee80211_pspoll_get(wl->hw, wl->vif);
- if (!skb)
- goto out_sleep;
+ ret = wl1251_acx_wr_tbtt_and_dtim(wl, wl->beacon_int,
+ wl->dtim_period);
+ wl->aid = bss_conf->aid;
- ret = wl1251_cmd_template_set(wl, CMD_PS_POLL,
- skb->data,
- skb->len);
- dev_kfree_skb(skb);
+ ret = wl1251_build_ps_poll(wl, wl->aid);
if (ret < 0)
goto out_sleep;
- ret = wl1251_acx_aid(wl, bss_conf->aid);
+ ret = wl1251_acx_aid(wl, wl->aid);
if (ret < 0)
goto out_sleep;
+
+ /* If we want to go in PSM but we're not there yet */
+ if (wl->psm_requested && !wl->psm) {
+ mode = STATION_POWER_SAVE_MODE;
+ ret = wl1251_ps_set_mode(wl, mode);
+ if (ret < 0)
+ goto out_sleep;
+ }
} else {
/* use defaults when not associated */
wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
@@ -1032,7 +1176,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
ret = wl1251_acx_cts_protect(wl, CTSPROTECT_DISABLE);
if (ret < 0) {
wl1251_warning("Set ctsprotect failed %d", ret);
- goto out_sleep;
+ goto out;
}
}
@@ -1043,7 +1187,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
if (ret < 0) {
dev_kfree_skb(beacon);
- goto out_sleep;
+ goto out;
}
ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, beacon->data,
@@ -1052,13 +1196,13 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
dev_kfree_skb(beacon);
if (ret < 0)
- goto out_sleep;
+ goto out;
ret = wl1251_join(wl, wl->bss_type, wl->beacon_int,
wl->channel, wl->dtim_period);
if (ret < 0)
- goto out_sleep;
+ goto out;
}
out_sleep:
@@ -1129,49 +1273,6 @@ static struct ieee80211_channel wl1251_channels[] = {
{ .hw_value = 13, .center_freq = 2472},
};
-static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
- const struct ieee80211_tx_queue_params *params)
-{
- enum wl1251_acx_ps_scheme ps_scheme;
- struct wl1251 *wl = hw->priv;
- int ret;
-
- mutex_lock(&wl->mutex);
-
- wl1251_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue);
-
- ret = wl1251_ps_elp_wakeup(wl);
- if (ret < 0)
- goto out;
-
- /* mac80211 uses units of 32 usec */
- ret = wl1251_acx_ac_cfg(wl, wl1251_tx_get_queue(queue),
- params->cw_min, params->cw_max,
- params->aifs, params->txop * 32);
- if (ret < 0)
- goto out_sleep;
-
- if (params->uapsd)
- ps_scheme = WL1251_ACX_PS_SCHEME_UPSD_TRIGGER;
- else
- ps_scheme = WL1251_ACX_PS_SCHEME_LEGACY;
-
- ret = wl1251_acx_tid_cfg(wl, wl1251_tx_get_queue(queue),
- CHANNEL_TYPE_EDCF,
- wl1251_tx_get_queue(queue), ps_scheme,
- WL1251_ACX_ACK_POLICY_LEGACY);
- if (ret < 0)
- goto out_sleep;
-
-out_sleep:
- wl1251_ps_elp_sleep(wl);
-
-out:
- mutex_unlock(&wl->mutex);
-
- return ret;
-}
-
/* can't be const, mac80211 writes to this */
static struct ieee80211_supported_band wl1251_band_2ghz = {
.channels = wl1251_channels,
@@ -1192,7 +1293,6 @@ static const struct ieee80211_ops wl1251_ops = {
.hw_scan = wl1251_op_hw_scan,
.bss_info_changed = wl1251_op_bss_info_changed,
.set_rts_threshold = wl1251_op_set_rts_threshold,
- .conf_tx = wl1251_op_conf_tx,
};
static int wl1251_register_hw(struct wl1251 *wl)
@@ -1232,15 +1332,12 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM |
IEEE80211_HW_SUPPORTS_PS |
- IEEE80211_HW_BEACON_FILTER |
- IEEE80211_HW_SUPPORTS_UAPSD;
+ IEEE80211_HW_BEACON_FILTER;
wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
wl->hw->wiphy->max_scan_ssids = 1;
wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz;
- wl->hw->queues = 4;
-
ret = wl1251_register_hw(wl);
if (ret)
goto out;
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1251_ps.c b/trunk/drivers/net/wireless/wl12xx/wl1251_ps.c
index 851dfb65e474..9931b197ff77 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1251_ps.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1251_ps.c
@@ -26,8 +26,7 @@
#include "wl1251_cmd.h"
#include "wl1251_io.h"
-/* in ms */
-#define WL1251_WAKEUP_TIMEOUT 100
+#define WL1251_WAKEUP_TIMEOUT 2000
void wl1251_elp_work(struct work_struct *work)
{
@@ -68,7 +67,7 @@ void wl1251_ps_elp_sleep(struct wl1251 *wl)
int wl1251_ps_elp_wakeup(struct wl1251 *wl)
{
- unsigned long timeout, start;
+ unsigned long timeout;
u32 elp_reg;
if (!wl->elp)
@@ -76,7 +75,6 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl)
wl1251_debug(DEBUG_PSM, "waking up chip from elp");
- start = jiffies;
timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT);
wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);
@@ -97,7 +95,8 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl)
}
wl1251_debug(DEBUG_PSM, "wakeup time: %u ms",
- jiffies_to_msecs(jiffies - start));
+ jiffies_to_msecs(jiffies) -
+ (jiffies_to_msecs(timeout) - WL1251_WAKEUP_TIMEOUT));
wl->elp = false;
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1251_rx.c b/trunk/drivers/net/wireless/wl12xx/wl1251_rx.c
index b56732226cc0..f84cc89cbffc 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1251_rx.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1251_rx.c
@@ -126,7 +126,7 @@ static void wl1251_rx_body(struct wl1251 *wl,
if (wl->rx_current_buffer)
rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size;
- skb = __dev_alloc_skb(length, GFP_KERNEL);
+ skb = dev_alloc_skb(length);
if (!skb) {
wl1251_error("Couldn't allocate RX frame");
return;
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1251_tx.c b/trunk/drivers/net/wireless/wl12xx/wl1251_tx.c
index c8223185efd2..f85970615849 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1251_tx.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1251_tx.c
@@ -167,7 +167,8 @@ static int wl1251_tx_fill_hdr(struct wl1251 *wl, struct sk_buff *skb,
tx_hdr->expiry_time = cpu_to_le32(1 << 16);
tx_hdr->id = id;
- tx_hdr->xmit_queue = wl1251_tx_get_queue(skb_get_queue_mapping(skb));
+ /* FIXME: how to get the correct queue id? */
+ tx_hdr->xmit_queue = 0;
wl1251_tx_control(tx_hdr, control, fc);
wl1251_tx_frag_block_num(tx_hdr);
@@ -219,7 +220,6 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb,
/* align the buffer on a 4-byte boundary */
skb_reserve(skb, offset);
memmove(skb->data, src, skb->len);
- tx_hdr = (struct tx_double_buffer_desc *) skb->data;
} else {
wl1251_info("No handler, fixme!");
return -EINVAL;
@@ -237,9 +237,8 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb,
wl1251_mem_write(wl, addr, skb->data, len);
- wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x "
- "queue %d", tx_hdr->id, skb, tx_hdr->length,
- tx_hdr->rate, tx_hdr->xmit_queue);
+ wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x",
+ tx_hdr->id, skb, tx_hdr->length, tx_hdr->rate);
return 0;
}
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1251_tx.h b/trunk/drivers/net/wireless/wl12xx/wl1251_tx.h
index 55856c6bb97a..7c1c1665c810 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1251_tx.h
+++ b/trunk/drivers/net/wireless/wl12xx/wl1251_tx.h
@@ -26,7 +26,6 @@
#define __WL1251_TX_H__
#include
-#include "wl1251_acx.h"
/*
*
@@ -210,22 +209,6 @@ struct tx_result {
u8 done_2;
} __attribute__ ((packed));
-static inline int wl1251_tx_get_queue(int queue)
-{
- switch (queue) {
- case 0:
- return QOS_AC_VO;
- case 1:
- return QOS_AC_VI;
- case 2:
- return QOS_AC_BE;
- case 3:
- return QOS_AC_BK;
- default:
- return QOS_AC_BE;
- }
-}
-
void wl1251_tx_work(struct work_struct *work);
void wl1251_tx_complete(struct wl1251 *wl);
void wl1251_tx_flush(struct wl1251 *wl);
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271.h b/trunk/drivers/net/wireless/wl12xx/wl1271.h
index 97ea5096bc8c..94359b1a861f 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271.h
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271.h
@@ -43,7 +43,7 @@ enum {
DEBUG_SPI = BIT(1),
DEBUG_BOOT = BIT(2),
DEBUG_MAILBOX = BIT(3),
- DEBUG_TESTMODE = BIT(4),
+ DEBUG_NETLINK = BIT(4),
DEBUG_EVENT = BIT(5),
DEBUG_TX = BIT(6),
DEBUG_RX = BIT(7),
@@ -107,36 +107,11 @@ enum {
CFG_RX_CTL_EN | CFG_RX_BCN_EN | \
CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
+#define WL1271_DEFAULT_BASIC_RATE_SET (CONF_TX_RATE_MASK_ALL)
+
#define WL1271_FW_NAME "wl1271-fw.bin"
#define WL1271_NVS_NAME "wl1271-nvs.bin"
-/* NVS data structure */
-#define WL1271_NVS_SECTION_SIZE 468
-
-#define WL1271_NVS_GENERAL_PARAMS_SIZE 57
-#define WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED \
- (WL1271_NVS_GENERAL_PARAMS_SIZE + 1)
-#define WL1271_NVS_STAT_RADIO_PARAMS_SIZE 17
-#define WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED \
- (WL1271_NVS_STAT_RADIO_PARAMS_SIZE + 1)
-#define WL1271_NVS_DYN_RADIO_PARAMS_SIZE 65
-#define WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED \
- (WL1271_NVS_DYN_RADIO_PARAMS_SIZE + 1)
-#define WL1271_NVS_FEM_COUNT 2
-#define WL1271_NVS_INI_SPARE_SIZE 124
-
-struct wl1271_nvs_file {
- /* NVS section */
- u8 nvs[WL1271_NVS_SECTION_SIZE];
-
- /* INI section */
- u8 general_params[WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED];
- u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED];
- u8 dyn_radio_params[WL1271_NVS_FEM_COUNT]
- [WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED];
- u8 ini_spare[WL1271_NVS_INI_SPARE_SIZE];
-} __attribute__ ((packed));
-
/*
* Enable/disable 802.11a support for WL1273
*/
@@ -301,7 +276,6 @@ struct wl1271_debugfs {
struct dentry *retry_count;
struct dentry *excessive_retries;
- struct dentry *gpio_power;
};
#define NUM_TX_QUEUES 4
@@ -348,17 +322,6 @@ struct wl1271 {
enum wl1271_state state;
struct mutex mutex;
-#define WL1271_FLAG_STA_RATES_CHANGED (0)
-#define WL1271_FLAG_STA_ASSOCIATED (1)
-#define WL1271_FLAG_JOINED (2)
-#define WL1271_FLAG_GPIO_POWER (3)
-#define WL1271_FLAG_TX_QUEUE_STOPPED (4)
-#define WL1271_FLAG_SCANNING (5)
-#define WL1271_FLAG_IN_ELP (6)
-#define WL1271_FLAG_PSM (7)
-#define WL1271_FLAG_PSM_REQUESTED (8)
- unsigned long flags;
-
struct wl1271_partition_set part;
struct wl1271_chip chip;
@@ -368,7 +331,8 @@ struct wl1271 {
u8 *fw;
size_t fw_len;
- struct wl1271_nvs_file *nvs;
+ u8 *nvs;
+ size_t nvs_len;
u8 bssid[ETH_ALEN];
u8 mac_addr[ETH_ALEN];
@@ -395,6 +359,7 @@ struct wl1271 {
/* Frames scheduled for transmission, not handled yet */
struct sk_buff_head tx_queue;
+ bool tx_queue_stopped;
struct work_struct tx_work;
@@ -422,15 +387,14 @@ struct wl1271 {
u32 mbox_ptr[2];
/* Are we currently scanning */
+ bool scanning;
struct wl1271_scan scan;
/* Our association ID */
u16 aid;
/* currently configured rate set */
- u32 sta_rate_set;
u32 basic_rate_set;
- u32 rate_set;
/* The current band */
enum ieee80211_band band;
@@ -441,9 +405,18 @@ struct wl1271 {
unsigned int rx_config;
unsigned int rx_filter;
+ /* is firmware in elp mode */
+ bool elp;
+
struct completion *elp_compl;
struct delayed_work elp_work;
+ /* we can be in psm, but not in elp, we have to differentiate */
+ bool psm;
+
+ /* PSM mode requested */
+ bool psm_requested;
+
/* retry counter for PSM entries */
u8 psm_entry_retry;
@@ -462,6 +435,9 @@ struct wl1271 {
struct ieee80211_vif *vif;
+ /* Used for a workaround to send disconnect before rejoining */
+ bool joined;
+
/* Current chipset configuration */
struct conf_drv_settings conf;
@@ -479,14 +455,11 @@ int wl1271_plt_stop(struct wl1271 *wl);
#define WL1271_TX_QUEUE_MAX_LENGTH 20
-/* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power
- on in case is has been shut down shortly before */
-#define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */
+/* WL1271 needs a 200ms sleep after power on */
#define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */
static inline bool wl1271_11a_enabled(void)
{
- /* FIXME: this could be determined based on the NVS-INI file */
#ifdef WL1271_80211A_ENABLED
return true;
#else
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_acx.c b/trunk/drivers/net/wireless/wl12xx/wl1271_acx.c
index 60f10dce4800..5cc89bbdac7a 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -390,35 +390,6 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold)
return ret;
}
-int wl1271_acx_dco_itrim_params(struct wl1271 *wl)
-{
- struct acx_dco_itrim_params *dco;
- struct conf_itrim_settings *c = &wl->conf.itrim;
- int ret;
-
- wl1271_debug(DEBUG_ACX, "acx dco itrim parameters");
-
- dco = kzalloc(sizeof(*dco), GFP_KERNEL);
- if (!dco) {
- ret = -ENOMEM;
- goto out;
- }
-
- dco->enable = c->enable;
- dco->timeout = cpu_to_le32(c->timeout);
-
- ret = wl1271_cmd_configure(wl, ACX_SET_DCO_ITRIM_PARAMS,
- dco, sizeof(*dco));
- if (ret < 0) {
- wl1271_warning("failed to set dco itrim parameters: %d", ret);
- goto out;
- }
-
-out:
- kfree(dco);
- return ret;
-}
-
int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter)
{
struct acx_beacon_filter_option *beacon_filter = NULL;
@@ -787,11 +758,10 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats)
return 0;
}
-int wl1271_acx_rate_policies(struct wl1271 *wl)
+int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates)
{
struct acx_rate_policy *acx;
struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf;
- int idx = 0;
int ret = 0;
wl1271_debug(DEBUG_ACX, "acx rate policies");
@@ -803,21 +773,12 @@ int wl1271_acx_rate_policies(struct wl1271 *wl)
goto out;
}
- /* configure one basic rate class */
- idx = ACX_TX_BASIC_RATE;
- acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set);
- acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
- acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
- acx->rate_class[idx].aflags = c->aflags;
-
- /* configure one AP supported rate class */
- idx = ACX_TX_AP_FULL_RATE;
- acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->rate_set);
- acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
- acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
- acx->rate_class[idx].aflags = c->aflags;
-
- acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT);
+ /* configure one default (one-size-fits-all) rate class */
+ acx->rate_class_cnt = cpu_to_le32(1);
+ acx->rate_class[0].enabled_rates = cpu_to_le32(enabled_rates);
+ acx->rate_class[0].short_retry_limit = c->short_retry_limit;
+ acx->rate_class[0].long_retry_limit = c->long_retry_limit;
+ acx->rate_class[0].aflags = c->aflags;
ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
if (ret < 0) {
@@ -830,14 +791,12 @@ int wl1271_acx_rate_policies(struct wl1271 *wl)
return ret;
}
-int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
- u8 aifsn, u16 txop)
+int wl1271_acx_ac_cfg(struct wl1271 *wl)
{
struct acx_ac_cfg *acx;
- int ret = 0;
+ int i, ret = 0;
- wl1271_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d "
- "aifs %d txop %d", ac, cw_min, cw_max, aifsn, txop);
+ wl1271_debug(DEBUG_ACX, "acx access category config");
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
@@ -846,16 +805,21 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
goto out;
}
- acx->ac = ac;
- acx->cw_min = cw_min;
- acx->cw_max = cpu_to_le16(cw_max);
- acx->aifsn = aifsn;
- acx->tx_op_limit = cpu_to_le16(txop);
+ for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
+ struct conf_tx_ac_category *c = &(wl->conf.tx.ac_conf[i]);
+ acx->ac = c->ac;
+ acx->cw_min = c->cw_min;
+ acx->cw_max = cpu_to_le16(c->cw_max);
+ acx->aifsn = c->aifsn;
+ acx->reserved = 0;
+ acx->tx_op_limit = cpu_to_le16(c->tx_op_limit);
- ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx));
- if (ret < 0) {
- wl1271_warning("acx ac cfg failed: %d", ret);
- goto out;
+ ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("Setting of access category "
+ "config: %d", ret);
+ goto out;
+ }
}
out:
@@ -863,12 +827,10 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
return ret;
}
-int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
- u8 tsid, u8 ps_scheme, u8 ack_policy,
- u32 apsd_conf0, u32 apsd_conf1)
+int wl1271_acx_tid_cfg(struct wl1271 *wl)
{
struct acx_tid_config *acx;
- int ret = 0;
+ int i, ret = 0;
wl1271_debug(DEBUG_ACX, "acx tid config");
@@ -879,18 +841,21 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
goto out;
}
- acx->queue_id = queue_id;
- acx->channel_type = channel_type;
- acx->tsid = tsid;
- acx->ps_scheme = ps_scheme;
- acx->ack_policy = ack_policy;
- acx->apsd_conf[0] = cpu_to_le32(apsd_conf0);
- acx->apsd_conf[1] = cpu_to_le32(apsd_conf1);
+ for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
+ struct conf_tx_tid *c = &(wl->conf.tx.tid_conf[i]);
+ acx->queue_id = c->queue_id;
+ acx->channel_type = c->channel_type;
+ acx->tsid = c->tsid;
+ acx->ps_scheme = c->ps_scheme;
+ acx->ack_policy = c->ack_policy;
+ acx->apsd_conf[0] = cpu_to_le32(c->apsd_conf[0]);
+ acx->apsd_conf[1] = cpu_to_le32(c->apsd_conf[1]);
- ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx));
- if (ret < 0) {
- wl1271_warning("Setting of tid config failed: %d", ret);
- goto out;
+ ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("Setting of tid config failed: %d", ret);
+ goto out;
+ }
}
out:
@@ -1047,6 +1012,59 @@ int wl1271_acx_init_rx_interrupt(struct wl1271 *wl)
return ret;
}
+int wl1271_acx_smart_reflex(struct wl1271 *wl)
+{
+ struct acx_smart_reflex_state *sr_state = NULL;
+ struct acx_smart_reflex_config_params *sr_param = NULL;
+ int i, ret;
+
+ wl1271_debug(DEBUG_ACX, "acx smart reflex");
+
+ sr_param = kzalloc(sizeof(*sr_param), GFP_KERNEL);
+ if (!sr_param) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ for (i = 0; i < CONF_SR_ERR_TBL_COUNT; i++) {
+ struct conf_mart_reflex_err_table *e =
+ &(wl->conf.init.sr_err_tbl[i]);
+
+ sr_param->error_table[i].len = e->len;
+ sr_param->error_table[i].upper_limit = e->upper_limit;
+ memcpy(sr_param->error_table[i].values, e->values, e->len);
+ }
+
+ ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_PARAMS,
+ sr_param, sizeof(*sr_param));
+ if (ret < 0) {
+ wl1271_warning("failed to set smart reflex params: %d", ret);
+ goto out;
+ }
+
+ sr_state = kzalloc(sizeof(*sr_state), GFP_KERNEL);
+ if (!sr_state) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* enable smart reflex */
+ sr_state->enable = wl->conf.init.sr_enable;
+
+ ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_STATE,
+ sr_state, sizeof(*sr_state));
+ if (ret < 0) {
+ wl1271_warning("failed to set smart reflex params: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(sr_state);
+ kfree(sr_param);
+ return ret;
+
+}
+
int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable)
{
struct wl1271_acx_bet_enable *acx = NULL;
@@ -1114,31 +1132,3 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address,
kfree(acx);
return ret;
}
-
-int wl1271_acx_pm_config(struct wl1271 *wl)
-{
- struct wl1271_acx_pm_config *acx = NULL;
- struct conf_pm_config_settings *c = &wl->conf.pm_config;
- int ret = 0;
-
- wl1271_debug(DEBUG_ACX, "acx pm config");
-
- acx = kzalloc(sizeof(*acx), GFP_KERNEL);
- if (!acx) {
- ret = -ENOMEM;
- goto out;
- }
-
- acx->host_clk_settling_time = cpu_to_le32(c->host_clk_settling_time);
- acx->host_fast_wakeup_support = c->host_fast_wakeup_support;
-
- ret = wl1271_cmd_configure(wl, ACX_PM_CONFIG, acx, sizeof(*acx));
- if (ret < 0) {
- wl1271_warning("acx pm config failed: %d", ret);
- goto out;
- }
-
-out:
- kfree(acx);
- return ret;
-}
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_acx.h b/trunk/drivers/net/wireless/wl12xx/wl1271_acx.h
index aeccc98581eb..2ce0a8128542 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -2,7 +2,7 @@
* This file is part of wl1271
*
* Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
- * Copyright (C) 2008-2010 Nokia Corporation
+ * Copyright (C) 2008-2009 Nokia Corporation
*
* Contact: Luciano Coelho
*
@@ -348,7 +348,7 @@ struct acx_beacon_filter_option {
* ACXBeaconFilterEntry (not 221)
* Byte Offset Size (Bytes) Definition
* =========== ============ ==========
- * 0 1 IE identifier
+ * 0 1 IE identifier
* 1 1 Treatment bit mask
*
* ACXBeaconFilterEntry (221)
@@ -381,8 +381,8 @@ struct acx_beacon_filter_ie_table {
struct acx_header header;
u8 num_ie;
- u8 pad[3];
u8 table[BEACON_FILTER_TABLE_MAX_SIZE];
+ u8 pad[3];
} __attribute__ ((packed));
struct acx_conn_monit_params {
@@ -415,12 +415,23 @@ struct acx_bt_wlan_coex {
u8 pad[3];
} __attribute__ ((packed));
-struct acx_dco_itrim_params {
+struct acx_smart_reflex_state {
struct acx_header header;
u8 enable;
u8 padding[3];
- __le32 timeout;
+} __attribute__ ((packed));
+
+struct smart_reflex_err_table {
+ u8 len;
+ s8 upper_limit;
+ s8 values[14];
+} __attribute__ ((packed));
+
+struct acx_smart_reflex_config_params {
+ struct acx_header header;
+
+ struct smart_reflex_err_table error_table[3];
} __attribute__ ((packed));
#define PTA_ANTENNA_TYPE_DEF (0)
@@ -826,9 +837,6 @@ struct acx_rate_class {
u8 reserved;
};
-#define ACX_TX_BASIC_RATE 0
-#define ACX_TX_AP_FULL_RATE 1
-#define ACX_TX_RATE_POLICY_CNT 2
struct acx_rate_policy {
struct acx_header header;
@@ -869,8 +877,8 @@ struct acx_tx_config_options {
__le16 tx_compl_threshold; /* number of packets */
} __attribute__ ((packed));
-#define ACX_RX_MEM_BLOCKS 70
-#define ACX_TX_MIN_MEM_BLOCKS 40
+#define ACX_RX_MEM_BLOCKS 64
+#define ACX_TX_MIN_MEM_BLOCKS 64
#define ACX_TX_DESCRIPTORS 32
#define ACX_NUM_SSID_PROFILES 1
@@ -961,13 +969,6 @@ struct wl1271_acx_arp_filter {
used. */
} __attribute__((packed));
-struct wl1271_acx_pm_config {
- struct acx_header header;
-
- __le32 host_clk_settling_time;
- u8 host_fast_wakeup_support;
- u8 padding[3];
-} __attribute__ ((packed));
enum {
ACX_WAKE_UP_CONDITIONS = 0x0002,
@@ -1026,13 +1027,13 @@ enum {
ACX_HT_BSS_OPERATION = 0x0058,
ACX_COEX_ACTIVITY = 0x0059,
ACX_SET_SMART_REFLEX_DEBUG = 0x005A,
- ACX_SET_DCO_ITRIM_PARAMS = 0x0061,
+ ACX_SET_SMART_REFLEX_STATE = 0x005B,
+ ACX_SET_SMART_REFLEX_PARAMS = 0x005F,
DOT11_RX_MSDU_LIFE_TIME = 0x1004,
DOT11_CUR_TX_PWR = 0x100D,
DOT11_RX_DOT11_MODE = 0x1012,
DOT11_RTS_THRESHOLD = 0x1013,
DOT11_GROUP_ADDRESS_TBL = 0x1014,
- ACX_PM_CONFIG = 0x1016,
MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL,
@@ -1055,7 +1056,6 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
void *mc_list, u32 mc_list_len);
int wl1271_acx_service_period_timeout(struct wl1271 *wl);
int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold);
-int wl1271_acx_dco_itrim_params(struct wl1271 *wl);
int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter);
int wl1271_acx_beacon_filter_table(struct wl1271 *wl);
int wl1271_acx_conn_monit_params(struct wl1271 *wl);
@@ -1069,12 +1069,9 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble);
int wl1271_acx_cts_protect(struct wl1271 *wl,
enum acx_ctsprotect_type ctsprotect);
int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats);
-int wl1271_acx_rate_policies(struct wl1271 *wl);
-int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
- u8 aifsn, u16 txop);
-int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
- u8 tsid, u8 ps_scheme, u8 ack_policy,
- u32 apsd_conf0, u32 apsd_conf1);
+int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates);
+int wl1271_acx_ac_cfg(struct wl1271 *wl);
+int wl1271_acx_tid_cfg(struct wl1271 *wl);
int wl1271_acx_frag_threshold(struct wl1271 *wl);
int wl1271_acx_tx_config_options(struct wl1271 *wl);
int wl1271_acx_mem_cfg(struct wl1271 *wl);
@@ -1084,6 +1081,5 @@ int wl1271_acx_smart_reflex(struct wl1271 *wl);
int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable);
int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address,
u8 version);
-int wl1271_acx_pm_config(struct wl1271 *wl);
#endif /* __WL1271_ACX_H__ */
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_boot.c b/trunk/drivers/net/wireless/wl12xx/wl1271_boot.c
index 2be76ee42bb9..b7c96454cca3 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -27,7 +27,6 @@
#include "wl1271_reg.h"
#include "wl1271_boot.h"
#include "wl1271_spi.h"
-#include "wl1271_io.h"
#include "wl1271_event.h"
static struct wl1271_partition_set part_table[PART_TABLE_LEN] = {
@@ -94,19 +93,19 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
u32 cpu_ctrl;
/* 10.5.0 run the firmware (I) */
- cpu_ctrl = wl1271_read32(wl, ACX_REG_ECPU_CONTROL);
+ cpu_ctrl = wl1271_spi_read32(wl, ACX_REG_ECPU_CONTROL);
/* 10.5.1 run the firmware (II) */
cpu_ctrl |= flag;
- wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
+ wl1271_spi_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
}
static void wl1271_boot_fw_version(struct wl1271 *wl)
{
struct wl1271_static_data static_data;
- wl1271_read(wl, wl->cmd_box_addr, &static_data, sizeof(static_data),
- false);
+ wl1271_spi_read(wl, wl->cmd_box_addr,
+ &static_data, sizeof(static_data), false);
strncpy(wl->chip.fw_ver, static_data.fw_version,
sizeof(wl->chip.fw_ver));
@@ -165,7 +164,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
memcpy(chunk, p, CHUNK_SIZE);
wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
p, addr);
- wl1271_write(wl, addr, chunk, CHUNK_SIZE, false);
+ wl1271_spi_write(wl, addr, chunk, CHUNK_SIZE, false);
chunk_num++;
}
@@ -176,7 +175,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
memcpy(chunk, p, fw_data_len % CHUNK_SIZE);
wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x",
fw_data_len % CHUNK_SIZE, p, addr);
- wl1271_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false);
+ wl1271_spi_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false);
kfree(chunk);
return 0;
@@ -220,14 +219,23 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
size_t nvs_len, burst_len;
int i;
u32 dest_addr, val;
- u8 *nvs_ptr, *nvs_aligned;
+ u8 *nvs_ptr, *nvs, *nvs_aligned;
- if (wl->nvs == NULL)
+ nvs = wl->nvs;
+ if (nvs == NULL)
return -ENODEV;
- /* only the first part of the NVS needs to be uploaded */
- nvs_len = sizeof(wl->nvs->nvs);
- nvs_ptr = (u8 *)wl->nvs->nvs;
+ nvs_ptr = nvs;
+
+ nvs_len = wl->nvs_len;
+
+ /* Update the device MAC address into the nvs */
+ nvs[11] = wl->mac_addr[0];
+ nvs[10] = wl->mac_addr[1];
+ nvs[6] = wl->mac_addr[2];
+ nvs[5] = wl->mac_addr[3];
+ nvs[4] = wl->mac_addr[4];
+ nvs[3] = wl->mac_addr[5];
/*
* Layout before the actual NVS tables:
@@ -257,7 +265,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
wl1271_debug(DEBUG_BOOT,
"nvs burst write 0x%x: 0x%x",
dest_addr, val);
- wl1271_write32(wl, dest_addr, val);
+ wl1271_spi_write32(wl, dest_addr, val);
nvs_ptr += 4;
dest_addr += 4;
@@ -269,7 +277,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
* is 7 bytes further.
*/
nvs_ptr += 7;
- nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs;
+ nvs_len -= nvs_ptr - nvs;
nvs_len = ALIGN(nvs_len, 4);
/* FIXME: The driver sets the partition here, but this is not needed,
@@ -278,20 +286,15 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
wl1271_set_partition(wl, &part_table[PART_WORK]);
/* Copy the NVS tables to a new block to ensure alignment */
- /* FIXME: We jump 3 more bytes before uploading the NVS. It seems
- that our NVS files have three extra zeros here. I'm not sure whether
- the problem is in our NVS generation or we should really jumpt these
- 3 bytes here */
- nvs_ptr += 3;
-
- nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); if
- (!nvs_aligned) return -ENOMEM;
+ nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
+ if (!nvs_aligned)
+ return -ENOMEM;
/* And finally we upload the NVS tables */
/* FIXME: In wl1271, we upload everything at once.
No endianness handling needed here?! The ref driver doesn't do
anything about it at this point */
- wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false);
+ wl1271_spi_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false);
kfree(nvs_aligned);
return 0;
@@ -300,9 +303,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
static void wl1271_boot_enable_interrupts(struct wl1271 *wl)
{
enable_irq(wl->irq);
- wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
- WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
- wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
+ wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK,
+ WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
+ wl1271_spi_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
}
static int wl1271_boot_soft_reset(struct wl1271 *wl)
@@ -311,12 +314,13 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl)
u32 boot_data;
/* perform soft reset */
- wl1271_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
+ wl1271_spi_write32(wl, ACX_REG_SLV_SOFT_RESET,
+ ACX_SLV_SOFT_RESET_BIT);
/* SOFT_RESET is self clearing */
timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
while (1) {
- boot_data = wl1271_read32(wl, ACX_REG_SLV_SOFT_RESET);
+ boot_data = wl1271_spi_read32(wl, ACX_REG_SLV_SOFT_RESET);
wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
break;
@@ -332,10 +336,10 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl)
}
/* disable Rx/Tx */
- wl1271_write32(wl, ENABLE, 0x0);
+ wl1271_spi_write32(wl, ENABLE, 0x0);
/* disable auto calibration on start*/
- wl1271_write32(wl, SPARE_A2, 0xffff);
+ wl1271_spi_write32(wl, SPARE_A2, 0xffff);
return 0;
}
@@ -347,7 +351,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
- chip_id = wl1271_read32(wl, CHIP_ID_B);
+ chip_id = wl1271_spi_read32(wl, CHIP_ID_B);
wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
@@ -360,7 +364,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
loop = 0;
while (loop++ < INIT_LOOP) {
udelay(INIT_LOOP_DELAY);
- interrupt = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+ interrupt = wl1271_spi_read32(wl,
+ ACX_REG_INTERRUPT_NO_CLEAR);
if (interrupt == 0xffffffff) {
wl1271_error("error reading hardware complete "
@@ -369,8 +374,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
}
/* check that ACX_INTR_INIT_COMPLETE is enabled */
else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) {
- wl1271_write32(wl, ACX_REG_INTERRUPT_ACK,
- WL1271_ACX_INTR_INIT_COMPLETE);
+ wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK,
+ WL1271_ACX_INTR_INIT_COMPLETE);
break;
}
}
@@ -382,10 +387,10 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
}
/* get hardware config command mail box */
- wl->cmd_box_addr = wl1271_read32(wl, REG_COMMAND_MAILBOX_PTR);
+ wl->cmd_box_addr = wl1271_spi_read32(wl, REG_COMMAND_MAILBOX_PTR);
/* get hardware config event mail box */
- wl->event_box_addr = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR);
+ wl->event_box_addr = wl1271_spi_read32(wl, REG_EVENT_MAILBOX_PTR);
/* set the working partition to its "running" mode offset */
wl1271_set_partition(wl, &part_table[PART_WORK]);
@@ -458,9 +463,9 @@ int wl1271_boot(struct wl1271 *wl)
wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
}
- wl1271_write32(wl, PLL_PARAMETERS, clk);
+ wl1271_spi_write32(wl, PLL_PARAMETERS, clk);
- pause = wl1271_read32(wl, PLL_PARAMETERS);
+ pause = wl1271_spi_read32(wl, PLL_PARAMETERS);
wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
@@ -469,10 +474,10 @@ int wl1271_boot(struct wl1271 *wl)
* 0x3ff (magic number ). How does
* this work?! */
pause |= WU_COUNTER_PAUSE_VAL;
- wl1271_write32(wl, WU_COUNTER_PAUSE, pause);
+ wl1271_spi_write32(wl, WU_COUNTER_PAUSE, pause);
/* Continue the ELP wake up sequence */
- wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
+ wl1271_spi_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
udelay(500);
wl1271_set_partition(wl, &part_table[PART_DRPW]);
@@ -482,18 +487,18 @@ int wl1271_boot(struct wl1271 *wl)
before taking DRPw out of reset */
wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START);
- clk = wl1271_read32(wl, DRPW_SCRATCH_START);
+ clk = wl1271_spi_read32(wl, DRPW_SCRATCH_START);
wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
/* 2 */
clk |= (REF_CLOCK << 1) << 4;
- wl1271_write32(wl, DRPW_SCRATCH_START, clk);
+ wl1271_spi_write32(wl, DRPW_SCRATCH_START, clk);
wl1271_set_partition(wl, &part_table[PART_WORK]);
/* Disable interrupts */
- wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
+ wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
ret = wl1271_boot_soft_reset(wl);
if (ret < 0)
@@ -508,22 +513,23 @@ int wl1271_boot(struct wl1271 *wl)
* ACX_EEPROMLESS_IND_REG */
wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");
- wl1271_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG);
+ wl1271_spi_write32(wl, ACX_EEPROMLESS_IND_REG,
+ ACX_EEPROMLESS_IND_REG);
- tmp = wl1271_read32(wl, CHIP_ID_B);
+ tmp = wl1271_spi_read32(wl, CHIP_ID_B);
wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
/* 6. read the EEPROM parameters */
- tmp = wl1271_read32(wl, SCR_PAD2);
+ tmp = wl1271_spi_read32(wl, SCR_PAD2);
ret = wl1271_boot_write_irq_polarity(wl);
if (ret < 0)
goto out;
/* FIXME: Need to check whether this is really what we want */
- wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
- WL1271_ACX_ALL_EVENTS_VECTOR);
+ wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK,
+ WL1271_ACX_ALL_EVENTS_VECTOR);
/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
* to upload_fw) */
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_cmd.c b/trunk/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 36a64e06f290..c3385b3d246c 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -30,7 +30,6 @@
#include "wl1271.h"
#include "wl1271_reg.h"
#include "wl1271_spi.h"
-#include "wl1271_io.h"
#include "wl1271_acx.h"
#include "wl12xx_80211.h"
#include "wl1271_cmd.h"
@@ -58,13 +57,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
WARN_ON(len % 4 != 0);
- wl1271_write(wl, wl->cmd_box_addr, buf, len, false);
+ wl1271_spi_write(wl, wl->cmd_box_addr, buf, len, false);
- wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
+ wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT);
- intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+ intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) {
if (time_after(jiffies, timeout)) {
wl1271_error("command complete timeout");
@@ -74,13 +73,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
msleep(1);
- intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+ intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
}
/* read back the status code of the command */
if (res_len == 0)
res_len = sizeof(struct wl1271_cmd_header);
- wl1271_read(wl, wl->cmd_box_addr, cmd, res_len, false);
+ wl1271_spi_read(wl, wl->cmd_box_addr, cmd, res_len, false);
status = le16_to_cpu(cmd->status);
if (status != CMD_STATUS_SUCCESS) {
@@ -88,8 +87,8 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
ret = -EIO;
}
- wl1271_write32(wl, ACX_REG_INTERRUPT_ACK,
- WL1271_ACX_INTR_CMD_COMPLETE);
+ wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK,
+ WL1271_ACX_INTR_CMD_COMPLETE);
out:
return ret;
@@ -192,19 +191,23 @@ static int wl1271_cmd_cal(struct wl1271 *wl)
int wl1271_cmd_general_parms(struct wl1271 *wl)
{
struct wl1271_general_parms_cmd *gen_parms;
+ struct conf_general_parms *g = &wl->conf.init.genparam;
int ret;
- if (!wl->nvs)
- return -ENODEV;
-
gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
if (!gen_parms)
return -ENOMEM;
gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM;
- memcpy(gen_parms->params, wl->nvs->general_params,
- WL1271_NVS_GENERAL_PARAMS_SIZE);
+ gen_parms->ref_clk = g->ref_clk;
+ gen_parms->settling_time = g->settling_time;
+ gen_parms->clk_valid_on_wakeup = g->clk_valid_on_wakeup;
+ gen_parms->dc2dcmode = g->dc2dcmode;
+ gen_parms->single_dual_band = g->single_dual_band;
+ gen_parms->tx_bip_fem_autodetect = g->tx_bip_fem_autodetect;
+ gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer;
+ gen_parms->settings = g->settings;
ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0);
if (ret < 0)
@@ -217,11 +220,8 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
int wl1271_cmd_radio_parms(struct wl1271 *wl)
{
struct wl1271_radio_parms_cmd *radio_parms;
- struct conf_radio_parms *rparam = &wl->conf.init.radioparam;
- int ret;
-
- if (!wl->nvs)
- return -ENODEV;
+ struct conf_radio_parms *r = &wl->conf.init.radioparam;
+ int i, ret;
radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL);
if (!radio_parms)
@@ -229,13 +229,60 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;
- memcpy(radio_parms->stat_radio_params, wl->nvs->stat_radio_params,
- WL1271_NVS_STAT_RADIO_PARAMS_SIZE);
- memcpy(radio_parms->dyn_radio_params,
- wl->nvs->dyn_radio_params[rparam->fem],
- WL1271_NVS_DYN_RADIO_PARAMS_SIZE);
-
- /* FIXME: current NVS is missing 5GHz parameters */
+ /* Static radio parameters */
+ radio_parms->rx_trace_loss = r->rx_trace_loss;
+ radio_parms->tx_trace_loss = r->tx_trace_loss;
+ memcpy(radio_parms->rx_rssi_and_proc_compens,
+ r->rx_rssi_and_proc_compens,
+ CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE);
+
+ memcpy(radio_parms->rx_trace_loss_5, r->rx_trace_loss_5,
+ CONF_NUMBER_OF_SUB_BANDS_5);
+ memcpy(radio_parms->tx_trace_loss_5, r->tx_trace_loss_5,
+ CONF_NUMBER_OF_SUB_BANDS_5);
+ memcpy(radio_parms->rx_rssi_and_proc_compens_5,
+ r->rx_rssi_and_proc_compens_5,
+ CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE);
+
+ /* Dynamic radio parameters */
+ radio_parms->tx_ref_pd_voltage = cpu_to_le16(r->tx_ref_pd_voltage);
+ radio_parms->tx_ref_power = r->tx_ref_power;
+ radio_parms->tx_offset_db = r->tx_offset_db;
+
+ memcpy(radio_parms->tx_rate_limits_normal, r->tx_rate_limits_normal,
+ CONF_NUMBER_OF_RATE_GROUPS);
+ memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded,
+ CONF_NUMBER_OF_RATE_GROUPS);
+
+ memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b,
+ CONF_NUMBER_OF_CHANNELS_2_4);
+ memcpy(radio_parms->tx_channel_limits_ofdm, r->tx_channel_limits_ofdm,
+ CONF_NUMBER_OF_CHANNELS_2_4);
+ memcpy(radio_parms->tx_pdv_rate_offsets, r->tx_pdv_rate_offsets,
+ CONF_NUMBER_OF_RATE_GROUPS);
+ memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS);
+
+ radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss;
+
+ for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++)
+ radio_parms->tx_ref_pd_voltage_5[i] =
+ cpu_to_le16(r->tx_ref_pd_voltage_5[i]);
+ memcpy(radio_parms->tx_ref_power_5, r->tx_ref_power_5,
+ CONF_NUMBER_OF_SUB_BANDS_5);
+ memcpy(radio_parms->tx_offset_db_5, r->tx_offset_db_5,
+ CONF_NUMBER_OF_SUB_BANDS_5);
+ memcpy(radio_parms->tx_rate_limits_normal_5,
+ r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS);
+ memcpy(radio_parms->tx_rate_limits_degraded_5,
+ r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS);
+ memcpy(radio_parms->tx_channel_limits_ofdm_5,
+ r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5);
+ memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5,
+ CONF_NUMBER_OF_RATE_GROUPS);
+ memcpy(radio_parms->tx_ibias_5, r->tx_ibias_5,
+ CONF_NUMBER_OF_RATE_GROUPS);
+ memcpy(radio_parms->rx_fem_insertion_loss_5,
+ r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5);
wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
radio_parms, sizeof(*radio_parms));
@@ -264,6 +311,19 @@ int wl1271_cmd_join(struct wl1271 *wl)
do_cal = false;
}
+ /* FIXME: This is a workaround, because with the current stack, we
+ * cannot know when we have disassociated. So, if we have already
+ * joined, we disconnect before joining again. */
+ if (wl->joined) {
+ ret = wl1271_cmd_disconnect(wl);
+ if (ret < 0) {
+ wl1271_error("failed to disconnect before rejoining");
+ goto out;
+ }
+
+ wl->joined = false;
+ }
+
join = kzalloc(sizeof(*join), GFP_KERNEL);
if (!join) {
ret = -ENOMEM;
@@ -328,6 +388,8 @@ int wl1271_cmd_join(struct wl1271 *wl)
goto out_free;
}
+ wl->joined = true;
+
/*
* ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to
* simplify locking we just sleep instead, for now
@@ -425,7 +487,7 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len)
return 0;
}
-int wl1271_cmd_data_path(struct wl1271 *wl, bool enable)
+int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable)
{
struct cmd_enabledisable_path *cmd;
int ret;
@@ -439,8 +501,7 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable)
goto out;
}
- /* the channel here is only used for calibration, so hardcoded to 1 */
- cmd->channel = 1;
+ cmd->channel = channel;
if (enable) {
cmd_rx = CMD_ENABLE_RX;
@@ -453,29 +514,29 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable)
ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("rx %s cmd for channel %d failed",
- enable ? "start" : "stop", cmd->channel);
+ enable ? "start" : "stop", channel);
goto out;
}
wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d",
- enable ? "start" : "stop", cmd->channel);
+ enable ? "start" : "stop", channel);
ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("tx %s cmd for channel %d failed",
- enable ? "start" : "stop", cmd->channel);
+ enable ? "start" : "stop", channel);
return ret;
}
wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d",
- enable ? "start" : "stop", cmd->channel);
+ enable ? "start" : "stop", channel);
out:
kfree(cmd);
return ret;
}
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send)
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
{
struct wl1271_cmd_ps_params *ps_params = NULL;
int ret = 0;
@@ -496,7 +557,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send)
}
ps_params->ps_mode = ps_mode;
- ps_params->send_null_data = send;
+ ps_params->send_null_data = 1;
ps_params->retries = 5;
ps_params->hang_over_period = 128;
ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */
@@ -575,7 +636,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
channels = wl->hw->wiphy->bands[ieee_band]->channels;
n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels;
- if (test_bit(WL1271_FLAG_SCANNING, &wl->flags))
+ if (wl->scanning)
return -EINVAL;
params = kzalloc(sizeof(*params), GFP_KERNEL);
@@ -650,7 +711,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params));
- set_bit(WL1271_FLAG_SCANNING, &wl->flags);
+ wl->scanning = true;
if (wl1271_11a_enabled()) {
wl->scan.state = band;
if (band == WL1271_SCAN_BAND_DUAL) {
@@ -668,7 +729,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0);
if (ret < 0) {
wl1271_error("SCAN failed");
- clear_bit(WL1271_FLAG_SCANNING, &wl->flags);
+ wl->scanning = false;
goto out;
}
@@ -942,7 +1003,7 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_warning("could not set keys");
- goto out;
+ goto out;
}
out:
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_cmd.h b/trunk/drivers/net/wireless/wl12xx/wl1271_cmd.h
index 2dc06c73532b..b4fa4acb9229 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -37,8 +37,8 @@ int wl1271_cmd_join(struct wl1271 *wl);
int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
-int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send);
+int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable);
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode);
int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
size_t len);
int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
@@ -428,24 +428,67 @@ struct wl1271_general_parms_cmd {
struct wl1271_cmd_test_header test;
- u8 params[WL1271_NVS_GENERAL_PARAMS_SIZE];
- s8 reserved[23];
-} __attribute__ ((packed));
+ u8 ref_clk;
+ u8 settling_time;
+ u8 clk_valid_on_wakeup;
+ u8 dc2dcmode;
+ u8 single_dual_band;
-#define WL1271_STAT_RADIO_PARAMS_5_SIZE 29
-#define WL1271_DYN_RADIO_PARAMS_5_SIZE 104
+ u8 tx_bip_fem_autodetect;
+ u8 tx_bip_fem_manufacturer;
+ u8 settings;
+} __attribute__ ((packed));
struct wl1271_radio_parms_cmd {
struct wl1271_cmd_header header;
struct wl1271_cmd_test_header test;
- u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE];
- u8 stat_radio_params_5[WL1271_STAT_RADIO_PARAMS_5_SIZE];
+ /* Static radio parameters */
+ /* 2.4GHz */
+ u8 rx_trace_loss;
+ u8 tx_trace_loss;
+ s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
- u8 dyn_radio_params[WL1271_NVS_DYN_RADIO_PARAMS_SIZE];
- u8 reserved;
- u8 dyn_radio_params_5[WL1271_DYN_RADIO_PARAMS_5_SIZE];
+ /* 5GHz */
+ u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
+ u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
+ s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
+
+ /* Dynamic radio parameters */
+ /* 2.4GHz */
+ __le16 tx_ref_pd_voltage;
+ s8 tx_ref_power;
+ s8 tx_offset_db;
+
+ s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS];
+ s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS];
+
+ s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4];
+ s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4];
+ s8 tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS];
+
+ u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS];
+ u8 rx_fem_insertion_loss;
+
+ u8 padding2;
+
+ /* 5GHz */
+ __le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5];
+ s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5];
+ s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5];
+
+ s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS];
+ s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS];
+
+ s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5];
+ s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS];
+
+ /* FIXME: this is inconsistent with the types for 2.4GHz */
+ s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS];
+ s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
+
+ u8 padding3[2];
} __attribute__ ((packed));
struct wl1271_cmd_cal_channel_tune {
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_conf.h b/trunk/drivers/net/wireless/wl12xx/wl1271_conf.h
index 6f9e75cc5640..565373ede265 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_conf.h
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_conf.h
@@ -258,8 +258,7 @@ struct conf_rx_settings {
#define CONF_TX_MAX_RATE_CLASSES 8
#define CONF_TX_RATE_MASK_UNSPECIFIED 0
-#define CONF_TX_RATE_MASK_BASIC (CONF_HW_BIT_RATE_1MBPS | \
- CONF_HW_BIT_RATE_2MBPS)
+#define CONF_TX_RATE_MASK_ALL 0x1eff
#define CONF_TX_RATE_RETRY_LIMIT 10
struct conf_tx_rate_class {
@@ -723,6 +722,31 @@ struct conf_conn_settings {
u8 psm_entry_retries;
};
+#define CONF_SR_ERR_TBL_MAX_VALUES 14
+
+struct conf_mart_reflex_err_table {
+ /*
+ * Length of the error table values table.
+ *
+ * Range: 0 - CONF_SR_ERR_TBL_MAX_VALUES
+ */
+ u8 len;
+
+ /*
+ * Smart Reflex error table upper limit.
+ *
+ * Range: s8
+ */
+ s8 upper_limit;
+
+ /*
+ * Smart Reflex error table values.
+ *
+ * Range: s8
+ */
+ s8 values[CONF_SR_ERR_TBL_MAX_VALUES];
+};
+
enum {
CONF_REF_CLK_19_2_E,
CONF_REF_CLK_26_E,
@@ -735,6 +759,64 @@ enum single_dual_band_enum {
CONF_DUAL_BAND
};
+struct conf_general_parms {
+ /*
+ * RF Reference Clock type / speed
+ *
+ * Range: CONF_REF_CLK_*
+ */
+ u8 ref_clk;
+
+ /*
+ * Settling time of the reference clock after boot.
+ *
+ * Range: u8
+ */
+ u8 settling_time;
+
+ /*
+ * Flag defining whether clock is valid on wakeup.
+ *
+ * Range: 0 - not valid on wakeup, 1 - valid on wakeup
+ */
+ u8 clk_valid_on_wakeup;
+
+ /*
+ * DC-to-DC mode.
+ *
+ * Range: Unknown
+ */
+ u8 dc2dcmode;
+
+ /*
+ * Flag defining whether used as single or dual-band.
+ *
+ * Range: CONF_SINGLE_BAND, CONF_DUAL_BAND
+ */
+ u8 single_dual_band;
+
+ /*
+ * TX bip fem autodetect flag.
+ *
+ * Range: Unknown
+ */
+ u8 tx_bip_fem_autodetect;
+
+ /*
+ * TX bip gem manufacturer.
+ *
+ * Range: Unknown
+ */
+ u8 tx_bip_fem_manufacturer;
+
+ /*
+ * Settings flags.
+ *
+ * Range: Unknown
+ */
+ u8 settings;
+};
+
#define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15
#define CONF_NUMBER_OF_SUB_BANDS_5 7
#define CONF_NUMBER_OF_RATE_GROUPS 6
@@ -743,43 +825,87 @@ enum single_dual_band_enum {
struct conf_radio_parms {
/*
- * FEM parameter set to use
+ * Static radio parameters for 2.4GHz
*
- * Range: 0 or 1
+ * Range: unknown
*/
- u8 fem;
-};
+ u8 rx_trace_loss;
+ u8 tx_trace_loss;
+ s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
-struct conf_init_settings {
/*
- * Configure radio parameters.
+ * Static radio parameters for 5GHz
+ *
+ * Range: unknown
*/
- struct conf_radio_parms radioparam;
+ u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
+ u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
+ s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
-};
+ /*
+ * Dynamic radio parameters for 2.4GHz
+ *
+ * Range: unknown
+ */
+ s16 tx_ref_pd_voltage;
+ s8 tx_ref_power;
+ s8 tx_offset_db;
-struct conf_itrim_settings {
- /* enable dco itrim */
- u8 enable;
+ s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS];
+ s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS];
- /* moderation timeout in microsecs from the last TX */
- u32 timeout;
-};
+ s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4];
+ s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4];
+ s8 tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS];
+
+ u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS];
+ u8 rx_fem_insertion_loss;
-struct conf_pm_config_settings {
/*
- * Host clock settling time
+ * Dynamic radio parameters for 5GHz
*
- * Range: 0 - 30000 us
+ * Range: unknown
+ */
+ s16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5];
+ s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5];
+ s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5];
+
+ s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS];
+ s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS];
+
+ s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5];
+ s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS];
+
+ /* FIXME: this is inconsistent with the types for 2.4GHz */
+ s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS];
+ s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
+};
+
+#define CONF_SR_ERR_TBL_COUNT 3
+
+struct conf_init_settings {
+ /*
+ * Configure Smart Reflex error table values.
*/
- u32 host_clk_settling_time;
+ struct conf_mart_reflex_err_table sr_err_tbl[CONF_SR_ERR_TBL_COUNT];
/*
- * Host fast wakeup support
+ * Smart Reflex enable flag.
*
- * Range: true, false
+ * Range: 1 - Smart Reflex enabled, 0 - Smart Reflex disabled
*/
- bool host_fast_wakeup_support;
+ u8 sr_enable;
+
+ /*
+ * Configure general parameters.
+ */
+ struct conf_general_parms genparam;
+
+ /*
+ * Configure radio parameters.
+ */
+ struct conf_radio_parms radioparam;
+
};
struct conf_drv_settings {
@@ -788,8 +914,6 @@ struct conf_drv_settings {
struct conf_tx_settings tx;
struct conf_conn_settings conn;
struct conf_init_settings init;
- struct conf_itrim_settings itrim;
- struct conf_pm_config_settings pm_config;
};
#endif
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/trunk/drivers/net/wireless/wl12xx/wl1271_debugfs.c
index 8d7588ca68fd..c1805e5f8964 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_debugfs.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_debugfs.c
@@ -237,64 +237,6 @@ static const struct file_operations tx_queue_len_ops = {
.open = wl1271_open_file_generic,
};
-static ssize_t gpio_power_read(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct wl1271 *wl = file->private_data;
- bool state = test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
-
- int res;
- char buf[10];
-
- res = scnprintf(buf, sizeof(buf), "%d\n", state);
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, res);
-}
-
-static ssize_t gpio_power_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct wl1271 *wl = file->private_data;
- char buf[10];
- size_t len;
- unsigned long value;
- int ret;
-
- mutex_lock(&wl->mutex);
-
- len = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, len)) {
- ret = -EFAULT;
- goto out;
- }
- buf[len] = '\0';
-
- ret = strict_strtoul(buf, 0, &value);
- if (ret < 0) {
- wl1271_warning("illegal value in gpio_power");
- goto out;
- }
-
- if (value) {
- wl->set_power(true);
- set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
- } else {
- wl->set_power(false);
- clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
- }
-
-out:
- mutex_unlock(&wl->mutex);
- return count;
-}
-
-static const struct file_operations gpio_power_ops = {
- .read = gpio_power_read,
- .write = gpio_power_write,
- .open = wl1271_open_file_generic
-};
-
static void wl1271_debugfs_delete_files(struct wl1271 *wl)
{
DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow);
@@ -391,8 +333,6 @@ static void wl1271_debugfs_delete_files(struct wl1271 *wl)
DEBUGFS_DEL(tx_queue_len);
DEBUGFS_DEL(retry_count);
DEBUGFS_DEL(excessive_retries);
-
- DEBUGFS_DEL(gpio_power);
}
static int wl1271_debugfs_add_files(struct wl1271 *wl)
@@ -494,8 +434,6 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl)
DEBUGFS_ADD(retry_count, wl->debugfs.rootdir);
DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir);
- DEBUGFS_ADD(gpio_power, wl->debugfs.rootdir);
-
out:
if (ret < 0)
wl1271_debugfs_delete_files(wl);
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_event.c b/trunk/drivers/net/wireless/wl12xx/wl1271_event.c
index 7468ef10194b..d13fdd99c85c 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -24,7 +24,6 @@
#include "wl1271.h"
#include "wl1271_reg.h"
#include "wl1271_spi.h"
-#include "wl1271_io.h"
#include "wl1271_event.h"
#include "wl1271_ps.h"
#include "wl12xx_80211.h"
@@ -36,7 +35,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl,
wl1271_debug(DEBUG_EVENT, "status: 0x%x",
mbox->scheduled_scan_status);
- if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) {
+ if (wl->scanning) {
if (wl->scan.state == WL1271_SCAN_BAND_DUAL) {
wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
NULL, size);
@@ -44,7 +43,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl,
* to the wl1271_cmd_scan function that we are not
* scanning as it checks that.
*/
- clear_bit(WL1271_FLAG_SCANNING, &wl->flags);
+ wl->scanning = false;
wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len,
wl->scan.active,
wl->scan.high_prio,
@@ -63,7 +62,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl,
mutex_unlock(&wl->mutex);
ieee80211_scan_completed(wl->hw, false);
mutex_lock(&wl->mutex);
- clear_bit(WL1271_FLAG_SCANNING, &wl->flags);
+ wl->scanning = false;
}
}
return 0;
@@ -79,61 +78,25 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
switch (mbox->ps_status) {
case EVENT_ENTER_POWER_SAVE_FAIL:
- wl1271_debug(DEBUG_PSM, "PSM entry failed");
-
- if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
- /* remain in active mode */
+ if (!wl->psm) {
wl->psm_entry_retry = 0;
break;
}
if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) {
wl->psm_entry_retry++;
- ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
- true);
+ ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
} else {
wl1271_error("PSM entry failed, giving up.\n");
- /* FIXME: this may need to be reconsidered. for now it
- is not possible to indicate to the mac80211
- afterwards that PSM entry failed. To maximize
- functionality (receiving data and remaining
- associated) make sure that we are in sync with the
- AP in regard of PSM mode. */
- ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
- false);
wl->psm_entry_retry = 0;
+ *beacon_loss = true;
}
break;
case EVENT_ENTER_POWER_SAVE_SUCCESS:
wl->psm_entry_retry = 0;
-
- /* enable beacon filtering */
- ret = wl1271_acx_beacon_filter_opt(wl, true);
- if (ret < 0)
- break;
-
- /* enable beacon early termination */
- ret = wl1271_acx_bet_enable(wl, true);
- if (ret < 0)
- break;
-
- /* go to extremely low power mode */
- wl1271_ps_elp_sleep(wl);
- if (ret < 0)
- break;
break;
case EVENT_EXIT_POWER_SAVE_FAIL:
- wl1271_debug(DEBUG_PSM, "PSM exit failed");
-
- if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
- wl->psm_entry_retry = 0;
- break;
- }
-
- /* make sure the firmware goes to active mode - the frame to
- be sent next will indicate to the AP, that we are active. */
- ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
- false);
+ wl1271_info("PSM exit failed");
break;
case EVENT_EXIT_POWER_SAVE_SUCCESS:
default:
@@ -173,8 +136,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
* filtering) is enabled. Without PSM, the stack will receive all
* beacons and can detect beacon loss by itself.
*/
- if (vector & BSS_LOSE_EVENT_ID &&
- test_bit(WL1271_FLAG_PSM, &wl->flags)) {
+ if (vector & BSS_LOSE_EVENT_ID && wl->psm) {
wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT");
/* indicate to the stack, that beacons have been lost */
@@ -188,7 +150,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
return ret;
}
- if (wl->vif && beacon_loss) {
+ if (beacon_loss) {
/* Obviously, it's dangerous to release the mutex while
we are holding many of the variables in the wl struct.
That's why it's done last in the function, and care must
@@ -215,14 +177,14 @@ int wl1271_event_unmask(struct wl1271 *wl)
void wl1271_event_mbox_config(struct wl1271 *wl)
{
- wl->mbox_ptr[0] = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR);
+ wl->mbox_ptr[0] = wl1271_spi_read32(wl, REG_EVENT_MAILBOX_PTR);
wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
wl->mbox_ptr[0], wl->mbox_ptr[1]);
}
-int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
+int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num, bool do_ack)
{
struct event_mailbox mbox;
int ret;
@@ -233,8 +195,8 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
return -EINVAL;
/* first we read the mbox descriptor */
- wl1271_read(wl, wl->mbox_ptr[mbox_num], &mbox,
- sizeof(struct event_mailbox), false);
+ wl1271_spi_read(wl, wl->mbox_ptr[mbox_num], &mbox,
+ sizeof(struct event_mailbox), false);
/* process the descriptor */
ret = wl1271_event_process(wl, &mbox);
@@ -242,7 +204,9 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
return ret;
/* then we let the firmware know it can go on...*/
- wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
+ if (do_ack)
+ wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG,
+ INTR_TRIG_EVENT_ACK);
return 0;
}
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_event.h b/trunk/drivers/net/wireless/wl12xx/wl1271_event.h
index 278f9206aa56..4e3f55ebb1a8 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_event.h
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_event.h
@@ -112,6 +112,6 @@ struct event_mailbox {
int wl1271_event_unmask(struct wl1271 *wl);
void wl1271_event_mbox_config(struct wl1271 *wl);
-int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
+int wl1271_event_handle(struct wl1271 *wl, u8 mbox, bool do_ack);
#endif
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_init.c b/trunk/drivers/net/wireless/wl12xx/wl1271_init.c
index 86c30a86a456..11249b436cf1 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -49,7 +49,7 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl)
return 0;
}
-int wl1271_init_templates_config(struct wl1271 *wl)
+static int wl1271_init_templates_config(struct wl1271 *wl)
{
int ret;
@@ -113,7 +113,7 @@ static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
return 0;
}
-int wl1271_init_phy_config(struct wl1271 *wl)
+static int wl1271_init_phy_config(struct wl1271 *wl)
{
int ret;
@@ -156,7 +156,7 @@ static int wl1271_init_beacon_filter(struct wl1271 *wl)
return 0;
}
-int wl1271_init_pta(struct wl1271 *wl)
+static int wl1271_init_pta(struct wl1271 *wl)
{
int ret;
@@ -171,7 +171,7 @@ int wl1271_init_pta(struct wl1271 *wl)
return 0;
}
-int wl1271_init_energy_detection(struct wl1271 *wl)
+static int wl1271_init_energy_detection(struct wl1271 *wl)
{
int ret;
@@ -195,9 +195,7 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
int wl1271_hw_init(struct wl1271 *wl)
{
- struct conf_tx_ac_category *conf_ac;
- struct conf_tx_tid *conf_tid;
- int ret, i;
+ int ret;
ret = wl1271_cmd_general_parms(wl);
if (ret < 0)
@@ -231,10 +229,6 @@ int wl1271_hw_init(struct wl1271 *wl)
if (ret < 0)
goto out_free_memmap;
- ret = wl1271_acx_dco_itrim_params(wl);
- if (ret < 0)
- goto out_free_memmap;
-
/* Initialize connection monitoring thresholds */
ret = wl1271_acx_conn_monit_params(wl);
if (ret < 0)
@@ -276,36 +270,22 @@ int wl1271_hw_init(struct wl1271 *wl)
goto out_free_memmap;
/* Default TID configuration */
- for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
- conf_tid = &wl->conf.tx.tid_conf[i];
- ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id,
- conf_tid->channel_type,
- conf_tid->tsid,
- conf_tid->ps_scheme,
- conf_tid->ack_policy,
- conf_tid->apsd_conf[0],
- conf_tid->apsd_conf[1]);
- if (ret < 0)
- goto out_free_memmap;
- }
+ ret = wl1271_acx_tid_cfg(wl);
+ if (ret < 0)
+ goto out_free_memmap;
/* Default AC configuration */
- for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
- conf_ac = &wl->conf.tx.ac_conf[i];
- ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
- conf_ac->cw_max, conf_ac->aifsn,
- conf_ac->tx_op_limit);
- if (ret < 0)
- goto out_free_memmap;
- }
+ ret = wl1271_acx_ac_cfg(wl);
+ if (ret < 0)
+ goto out_free_memmap;
/* Configure TX rate classes */
- ret = wl1271_acx_rate_policies(wl);
+ ret = wl1271_acx_rate_policies(wl, CONF_TX_RATE_MASK_ALL);
if (ret < 0)
goto out_free_memmap;
/* Enable data path */
- ret = wl1271_cmd_data_path(wl, 1);
+ ret = wl1271_cmd_data_path(wl, wl->channel, 1);
if (ret < 0)
goto out_free_memmap;
@@ -319,8 +299,8 @@ int wl1271_hw_init(struct wl1271 *wl)
if (ret < 0)
goto out_free_memmap;
- /* configure PM */
- ret = wl1271_acx_pm_config(wl);
+ /* Configure smart reflex */
+ ret = wl1271_acx_smart_reflex(wl);
if (ret < 0)
goto out_free_memmap;
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_init.h b/trunk/drivers/net/wireless/wl12xx/wl1271_init.h
index bc26f8c53b91..930677fbe852 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_init.h
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_init.h
@@ -27,10 +27,6 @@
#include "wl1271.h"
int wl1271_hw_init_power_auth(struct wl1271 *wl);
-int wl1271_init_templates_config(struct wl1271 *wl);
-int wl1271_init_phy_config(struct wl1271 *wl);
-int wl1271_init_pta(struct wl1271 *wl);
-int wl1271_init_energy_detection(struct wl1271 *wl);
int wl1271_hw_init(struct wl1271 *wl);
#endif
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_io.c b/trunk/drivers/net/wireless/wl12xx/wl1271_io.c
deleted file mode 100644
index 5cd94d5666c2..000000000000
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_io.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * This file is part of wl1271
- *
- * Copyright (C) 2008-2010 Nokia Corporation
- *
- * Contact: Luciano Coelho
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include
-#include
-#include
-#include
-
-#include "wl1271.h"
-#include "wl12xx_80211.h"
-#include "wl1271_spi.h"
-#include "wl1271_io.h"
-
-static int wl1271_translate_addr(struct wl1271 *wl, int addr)
-{
- /*
- * To translate, first check to which window of addresses the
- * particular address belongs. Then subtract the starting address
- * of that window from the address. Then, add offset of the
- * translated region.
- *
- * The translated regions occur next to each other in physical device
- * memory, so just add the sizes of the preceeding address regions to
- * get the offset to the new region.
- *
- * Currently, only the two first regions are addressed, and the
- * assumption is that all addresses will fall into either of those
- * two.
- */
- if ((addr >= wl->part.reg.start) &&
- (addr < wl->part.reg.start + wl->part.reg.size))
- return addr - wl->part.reg.start + wl->part.mem.size;
- else
- return addr - wl->part.mem.start;
-}
-
-/* Set the SPI partitions to access the chip addresses
- *
- * To simplify driver code, a fixed (virtual) memory map is defined for
- * register and memory addresses. Because in the chipset, in different stages
- * of operation, those addresses will move around, an address translation
- * mechanism is required.
- *
- * There are four partitions (three memory and one register partition),
- * which are mapped to two different areas of the hardware memory.
- *
- * Virtual address
- * space
- *
- * | |
- * ...+----+--> mem.start
- * Physical address ... | |
- * space ... | | [PART_0]
- * ... | |
- * 00000000 <--+----+... ...+----+--> mem.start + mem.size
- * | | ... | |
- * |MEM | ... | |
- * | | ... | |
- * mem.size <--+----+... | | {unused area)
- * | | ... | |
- * |REG | ... | |
- * mem.size | | ... | |
- * + <--+----+... ...+----+--> reg.start
- * reg.size | | ... | |
- * |MEM2| ... | | [PART_1]
- * | | ... | |
- * ...+----+--> reg.start + reg.size
- * | |
- *
- */
-int wl1271_set_partition(struct wl1271 *wl,
- struct wl1271_partition_set *p)
-{
- /* copy partition info */
- memcpy(&wl->part, p, sizeof(*p));
-
- wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
- p->mem.start, p->mem.size);
- wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
- p->reg.start, p->reg.size);
- wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X",
- p->mem2.start, p->mem2.size);
- wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X",
- p->mem3.start, p->mem3.size);
-
- /* write partition info to the chipset */
- wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start);
- wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size);
- wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start);
- wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size);
- wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start);
- wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size);
- wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
-
- return 0;
-}
-
-void wl1271_io_reset(struct wl1271 *wl)
-{
- wl1271_spi_reset(wl);
-}
-
-void wl1271_io_init(struct wl1271 *wl)
-{
- wl1271_spi_init(wl);
-}
-
-void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
- size_t len, bool fixed)
-{
- wl1271_spi_raw_write(wl, addr, buf, len, fixed);
-}
-
-void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf,
- size_t len, bool fixed)
-{
- wl1271_spi_raw_read(wl, addr, buf, len, fixed);
-}
-
-void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len,
- bool fixed)
-{
- int physical;
-
- physical = wl1271_translate_addr(wl, addr);
-
- wl1271_spi_raw_read(wl, physical, buf, len, fixed);
-}
-
-void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len,
- bool fixed)
-{
- int physical;
-
- physical = wl1271_translate_addr(wl, addr);
-
- wl1271_spi_raw_write(wl, physical, buf, len, fixed);
-}
-
-u32 wl1271_read32(struct wl1271 *wl, int addr)
-{
- return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr));
-}
-
-void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
-{
- wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val);
-}
-
-void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val)
-{
- /* write address >> 1 + 0x30000 to OCP_POR_CTR */
- addr = (addr >> 1) + 0x30000;
- wl1271_write32(wl, OCP_POR_CTR, addr);
-
- /* write value to OCP_POR_WDATA */
- wl1271_write32(wl, OCP_DATA_WRITE, val);
-
- /* write 1 to OCP_CMD */
- wl1271_write32(wl, OCP_CMD, OCP_CMD_WRITE);
-}
-
-u16 wl1271_top_reg_read(struct wl1271 *wl, int addr)
-{
- u32 val;
- int timeout = OCP_CMD_LOOP;
-
- /* write address >> 1 + 0x30000 to OCP_POR_CTR */
- addr = (addr >> 1) + 0x30000;
- wl1271_write32(wl, OCP_POR_CTR, addr);
-
- /* write 2 to OCP_CMD */
- wl1271_write32(wl, OCP_CMD, OCP_CMD_READ);
-
- /* poll for data ready */
- do {
- val = wl1271_read32(wl, OCP_DATA_READ);
- } while (!(val & OCP_READY_MASK) && --timeout);
-
- if (!timeout) {
- wl1271_warning("Top register access timed out.");
- return 0xffff;
- }
-
- /* check data status and return if OK */
- if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK)
- return val & 0xffff;
- else {
- wl1271_warning("Top register access returned error.");
- return 0xffff;
- }
-}
-
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_io.h b/trunk/drivers/net/wireless/wl12xx/wl1271_io.h
deleted file mode 100644
index fa9a0b35788f..000000000000
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_io.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * This file is part of wl1271
- *
- * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
- * Copyright (C) 2008-2010 Nokia Corporation
- *
- * Contact: Luciano Coelho
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __WL1271_IO_H__
-#define __WL1271_IO_H__
-
-struct wl1271;
-
-void wl1271_io_reset(struct wl1271 *wl);
-void wl1271_io_init(struct wl1271 *wl);
-
-/* Raw target IO, address is not translated */
-void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
- size_t len, bool fixed);
-void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf,
- size_t len, bool fixed);
-
-/* Translated target IO */
-void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len,
- bool fixed);
-void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len,
- bool fixed);
-u32 wl1271_read32(struct wl1271 *wl, int addr);
-void wl1271_write32(struct wl1271 *wl, int addr, u32 val);
-
-/* Top Register IO */
-void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val);
-u16 wl1271_top_reg_read(struct wl1271 *wl, int addr);
-
-int wl1271_set_partition(struct wl1271 *wl,
- struct wl1271_partition_set *p);
-
-static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr)
-{
- wl1271_raw_read(wl, addr, &wl->buffer_32,
- sizeof(wl->buffer_32), false);
-
- return wl->buffer_32;
-}
-
-static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val)
-{
- wl->buffer_32 = val;
- wl1271_raw_write(wl, addr, &wl->buffer_32,
- sizeof(wl->buffer_32), false);
-}
-#endif
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_main.c b/trunk/drivers/net/wireless/wl12xx/wl1271_main.c
index 2a864b24291d..b62c00ff42fe 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1,7 +1,7 @@
/*
* This file is part of wl1271
*
- * Copyright (C) 2008-2010 Nokia Corporation
+ * Copyright (C) 2008-2009 Nokia Corporation
*
* Contact: Luciano Coelho
*
@@ -38,7 +38,6 @@
#include "wl12xx_80211.h"
#include "wl1271_reg.h"
#include "wl1271_spi.h"
-#include "wl1271_io.h"
#include "wl1271_event.h"
#include "wl1271_tx.h"
#include "wl1271_rx.h"
@@ -47,9 +46,6 @@
#include "wl1271_debugfs.h"
#include "wl1271_cmd.h"
#include "wl1271_boot.h"
-#include "wl1271_testmode.h"
-
-#define WL1271_BOOT_RETRIES 3
static struct conf_drv_settings default_conf = {
.sg = {
@@ -71,17 +67,16 @@ static struct conf_drv_settings default_conf = {
.ps_poll_timeout = 15,
.upsd_timeout = 15,
.rts_threshold = 2347,
- .rx_cca_threshold = 0,
- .irq_blk_threshold = 0xFFFF,
- .irq_pkt_threshold = 0,
- .irq_timeout = 600,
+ .rx_cca_threshold = 0xFFEF,
+ .irq_blk_threshold = 0,
+ .irq_pkt_threshold = USHORT_MAX,
+ .irq_timeout = 5,
.queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY,
},
.tx = {
.tx_energy_detection = 0,
.rc_conf = {
- .enabled_rates = CONF_HW_BIT_RATE_1MBPS |
- CONF_HW_BIT_RATE_2MBPS,
+ .enabled_rates = CONF_TX_RATE_MASK_UNSPECIFIED,
.short_retry_limit = 10,
.long_retry_limit = 10,
.aflags = 0
@@ -177,8 +172,8 @@ static struct conf_drv_settings default_conf = {
}
},
.frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD,
- .tx_compl_timeout = 700,
- .tx_compl_threshold = 4
+ .tx_compl_timeout = 5,
+ .tx_compl_threshold = 5
},
.conn = {
.wake_up_event = CONF_WAKE_UP_EVENT_DTIM,
@@ -191,12 +186,12 @@ static struct conf_drv_settings default_conf = {
.rule = CONF_BCN_RULE_PASS_ON_APPEARANCE,
}
},
- .synch_fail_thold = 10,
+ .synch_fail_thold = 5,
.bss_lose_timeout = 100,
.beacon_rx_timeout = 10000,
.broadcast_timeout = 20000,
.rx_broadcast_in_ps = 1,
- .ps_poll_threshold = 20,
+ .ps_poll_threshold = 4,
.sig_trigger_count = 2,
.sig_trigger = {
[0] = {
@@ -231,17 +226,97 @@ static struct conf_drv_settings default_conf = {
.psm_entry_retries = 3
},
.init = {
+ .sr_err_tbl = {
+ [0] = {
+ .len = 7,
+ .upper_limit = 0x03,
+ .values = {
+ 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8,
+ 0x00 }
+ },
+ [1] = {
+ .len = 7,
+ .upper_limit = 0x03,
+ .values = {
+ 0x18, 0x10, 0x05, 0xf6, 0xf0, 0xe8,
+ 0x00 }
+ },
+ [2] = {
+ .len = 7,
+ .upper_limit = 0x03,
+ .values = {
+ 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8,
+ 0x00 }
+ }
+ },
+ .sr_enable = 1,
+ .genparam = {
+ .ref_clk = CONF_REF_CLK_38_4_E,
+ .settling_time = 5,
+ .clk_valid_on_wakeup = 0,
+ .dc2dcmode = 0,
+ .single_dual_band = CONF_SINGLE_BAND,
+ .tx_bip_fem_autodetect = 0,
+ .tx_bip_fem_manufacturer = 1,
+ .settings = 1,
+ },
.radioparam = {
- .fem = 1,
+ .rx_trace_loss = 10,
+ .tx_trace_loss = 10,
+ .rx_rssi_and_proc_compens = {
+ 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8,
+ 0xfc, 0x00, 0x08, 0x10, 0xf0, 0xf8,
+ 0x00, 0x0a, 0x14 },
+ .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 },
+ .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 },
+ .rx_rssi_and_proc_compens_5 = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00 },
+ .tx_ref_pd_voltage = 0x24e,
+ .tx_ref_power = 0x78,
+ .tx_offset_db = 0x0,
+ .tx_rate_limits_normal = {
+ 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 },
+ .tx_rate_limits_degraded = {
+ 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 },
+ .tx_channel_limits_11b = {
+ 0x22, 0x50, 0x50, 0x50, 0x50, 0x50,
+ 0x50, 0x50, 0x50, 0x50, 0x22, 0x50,
+ 0x22, 0x50 },
+ .tx_channel_limits_ofdm = {
+ 0x20, 0x50, 0x50, 0x50, 0x50, 0x50,
+ 0x50, 0x50, 0x50, 0x50, 0x20, 0x50,
+ 0x20, 0x50 },
+ .tx_pdv_rate_offsets = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ .tx_ibias = {
+ 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 },
+ .rx_fem_insertion_loss = 0x14,
+ .tx_ref_pd_voltage_5 = {
+ 0x0190, 0x01a4, 0x01c3, 0x01d8,
+ 0x020a, 0x021c },
+ .tx_ref_power_5 = {
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 },
+ .tx_offset_db_5 = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ .tx_rate_limits_normal_5 = {
+ 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
+ .tx_rate_limits_degraded_5 = {
+ 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
+ .tx_channel_limits_ofdm_5 = {
+ 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
+ 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
+ 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
+ 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
+ 0x50, 0x50, 0x50 },
+ .tx_pdv_rate_offsets_5 = {
+ 0x01, 0x02, 0x02, 0x02, 0x02, 0x00 },
+ .tx_ibias_5 = {
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
+ .rx_fem_insertion_loss_5 = {
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }
}
- },
- .itrim = {
- .enable = false,
- .timeout = 50000,
- },
- .pm_config = {
- .host_clk_settling_time = 5000,
- .host_fast_wakeup_support = false
}
};
@@ -262,14 +337,15 @@ static void wl1271_conf_init(struct wl1271 *wl)
/* apply driver default configuration */
memcpy(&wl->conf, &default_conf, sizeof(default_conf));
+
+ if (wl1271_11a_enabled())
+ wl->conf.init.genparam.single_dual_band = CONF_DUAL_BAND;
}
static int wl1271_plt_init(struct wl1271 *wl)
{
- struct conf_tx_ac_category *conf_ac;
- struct conf_tx_tid *conf_tid;
- int ret, i;
+ int ret;
ret = wl1271_cmd_general_parms(wl);
if (ret < 0)
@@ -279,89 +355,15 @@ static int wl1271_plt_init(struct wl1271 *wl)
if (ret < 0)
return ret;
- ret = wl1271_init_templates_config(wl);
- if (ret < 0)
- return ret;
-
ret = wl1271_acx_init_mem_config(wl);
if (ret < 0)
return ret;
- /* PHY layer config */
- ret = wl1271_init_phy_config(wl);
- if (ret < 0)
- goto out_free_memmap;
-
- ret = wl1271_acx_dco_itrim_params(wl);
- if (ret < 0)
- goto out_free_memmap;
-
- /* Initialize connection monitoring thresholds */
- ret = wl1271_acx_conn_monit_params(wl);
- if (ret < 0)
- goto out_free_memmap;
-
- /* Bluetooth WLAN coexistence */
- ret = wl1271_init_pta(wl);
- if (ret < 0)
- goto out_free_memmap;
-
- /* Energy detection */
- ret = wl1271_init_energy_detection(wl);
- if (ret < 0)
- goto out_free_memmap;
-
- /* Default fragmentation threshold */
- ret = wl1271_acx_frag_threshold(wl);
- if (ret < 0)
- goto out_free_memmap;
-
- /* Default TID configuration */
- for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
- conf_tid = &wl->conf.tx.tid_conf[i];
- ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id,
- conf_tid->channel_type,
- conf_tid->tsid,
- conf_tid->ps_scheme,
- conf_tid->ack_policy,
- conf_tid->apsd_conf[0],
- conf_tid->apsd_conf[1]);
- if (ret < 0)
- goto out_free_memmap;
- }
-
- /* Default AC configuration */
- for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
- conf_ac = &wl->conf.tx.ac_conf[i];
- ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
- conf_ac->cw_max, conf_ac->aifsn,
- conf_ac->tx_op_limit);
- if (ret < 0)
- goto out_free_memmap;
- }
-
- /* Enable data path */
- ret = wl1271_cmd_data_path(wl, 1);
+ ret = wl1271_cmd_data_path(wl, wl->channel, 1);
if (ret < 0)
- goto out_free_memmap;
-
- /* Configure for CAM power saving (ie. always active) */
- ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
- if (ret < 0)
- goto out_free_memmap;
-
- /* configure PM */
- ret = wl1271_acx_pm_config(wl);
- if (ret < 0)
- goto out_free_memmap;
+ return ret;
return 0;
-
- out_free_memmap:
- kfree(wl->target_mem_map);
- wl->target_mem_map = NULL;
-
- return ret;
}
static void wl1271_disable_interrupts(struct wl1271 *wl)
@@ -372,13 +374,11 @@ static void wl1271_disable_interrupts(struct wl1271 *wl)
static void wl1271_power_off(struct wl1271 *wl)
{
wl->set_power(false);
- clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
}
static void wl1271_power_on(struct wl1271 *wl)
{
wl->set_power(true);
- set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
}
static void wl1271_fw_status(struct wl1271 *wl,
@@ -387,7 +387,8 @@ static void wl1271_fw_status(struct wl1271 *wl,
u32 total = 0;
int i;
- wl1271_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false);
+ wl1271_spi_read(wl, FW_STATUS_ADDR, status,
+ sizeof(*status), false);
wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
"drv_rx_counter = %d, tx_results_counter = %d)",
@@ -434,7 +435,7 @@ static void wl1271_irq_work(struct work_struct *work)
if (ret < 0)
goto out;
- wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
+ wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
wl1271_fw_status(wl, wl->fw_status);
intr = le32_to_cpu(wl->fw_status->intr);
@@ -446,13 +447,14 @@ static void wl1271_irq_work(struct work_struct *work)
intr &= WL1271_INTR_MASK;
if (intr & WL1271_ACX_INTR_EVENT_A) {
+ bool do_ack = (intr & WL1271_ACX_INTR_EVENT_B) ? false : true;
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A");
- wl1271_event_handle(wl, 0);
+ wl1271_event_handle(wl, 0, do_ack);
}
if (intr & WL1271_ACX_INTR_EVENT_B) {
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B");
- wl1271_event_handle(wl, 1);
+ wl1271_event_handle(wl, 1, true);
}
if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
@@ -476,8 +478,8 @@ static void wl1271_irq_work(struct work_struct *work)
}
out_sleep:
- wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
- WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
+ wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK,
+ WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
wl1271_ps_elp_sleep(wl);
out:
@@ -544,40 +546,6 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
return ret;
}
-static int wl1271_update_mac_addr(struct wl1271 *wl)
-{
- int ret = 0;
- u8 *nvs_ptr = (u8 *)wl->nvs->nvs;
-
- /* get mac address from the NVS */
- wl->mac_addr[0] = nvs_ptr[11];
- wl->mac_addr[1] = nvs_ptr[10];
- wl->mac_addr[2] = nvs_ptr[6];
- wl->mac_addr[3] = nvs_ptr[5];
- wl->mac_addr[4] = nvs_ptr[4];
- wl->mac_addr[5] = nvs_ptr[3];
-
- /* FIXME: if it is a zero-address, we should bail out. Now, instead,
- we randomize an address */
- if (is_zero_ether_addr(wl->mac_addr)) {
- static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
- memcpy(wl->mac_addr, nokia_oui, 3);
- get_random_bytes(wl->mac_addr + 3, 3);
-
- /* update this address to the NVS */
- nvs_ptr[11] = wl->mac_addr[0];
- nvs_ptr[10] = wl->mac_addr[1];
- nvs_ptr[6] = wl->mac_addr[2];
- nvs_ptr[5] = wl->mac_addr[3];
- nvs_ptr[4] = wl->mac_addr[4];
- nvs_ptr[3] = wl->mac_addr[5];
- }
-
- SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
-
- return ret;
-}
-
static int wl1271_fetch_nvs(struct wl1271 *wl)
{
const struct firmware *fw;
@@ -590,14 +558,15 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
return ret;
}
- if (fw->size != sizeof(struct wl1271_nvs_file)) {
- wl1271_error("nvs size is not as expected: %zu != %zu",
- fw->size, sizeof(struct wl1271_nvs_file));
+ if (fw->size % 4) {
+ wl1271_error("nvs size is not multiple of 32 bits: %zu",
+ fw->size);
ret = -EILSEQ;
goto out;
}
- wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL);
+ wl->nvs_len = fw->size;
+ wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL);
if (!wl->nvs) {
wl1271_error("could not allocate memory for the nvs file");
@@ -605,9 +574,9 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
goto out;
}
- memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file));
+ memcpy(wl->nvs, fw->data, wl->nvs_len);
- ret = wl1271_update_mac_addr(wl);
+ ret = 0;
out:
release_firmware(fw);
@@ -645,11 +614,10 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
struct wl1271_partition_set partition;
int ret = 0;
- msleep(WL1271_PRE_POWER_ON_SLEEP);
wl1271_power_on(wl);
msleep(WL1271_POWER_ON_SLEEP);
- wl1271_io_reset(wl);
- wl1271_io_init(wl);
+ wl1271_spi_reset(wl);
+ wl1271_spi_init(wl);
/* We don't need a real memory partition here, because we only want
* to use the registers at this point. */
@@ -664,7 +632,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
/* whal_FwCtrl_BootSm() */
/* 0. read chip id from CHIP_ID */
- wl->chip.id = wl1271_read32(wl, CHIP_ID_B);
+ wl->chip.id = wl1271_spi_read32(wl, CHIP_ID_B);
/* 1. check if chip id is valid */
@@ -675,7 +643,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
ret = wl1271_setup(wl);
if (ret < 0)
- goto out;
+ goto out_power_off;
break;
case CHIP_ID_1271_PG20:
wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
@@ -683,34 +651,38 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
ret = wl1271_setup(wl);
if (ret < 0)
- goto out;
+ goto out_power_off;
break;
default:
- wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
+ wl1271_error("unsupported chip id: 0x%x", wl->chip.id);
ret = -ENODEV;
- goto out;
+ goto out_power_off;
}
if (wl->fw == NULL) {
ret = wl1271_fetch_firmware(wl);
if (ret < 0)
- goto out;
+ goto out_power_off;
}
/* No NVS from netlink, try to get it from the filesystem */
if (wl->nvs == NULL) {
ret = wl1271_fetch_nvs(wl);
if (ret < 0)
- goto out;
+ goto out_power_off;
}
+ goto out;
+
+out_power_off:
+ wl1271_power_off(wl);
+
out:
return ret;
}
int wl1271_plt_start(struct wl1271 *wl)
{
- int retries = WL1271_BOOT_RETRIES;
int ret;
mutex_lock(&wl->mutex);
@@ -724,43 +696,35 @@ int wl1271_plt_start(struct wl1271 *wl)
goto out;
}
- while (retries) {
- retries--;
- ret = wl1271_chip_wakeup(wl);
- if (ret < 0)
- goto power_off;
+ wl->state = WL1271_STATE_PLT;
- ret = wl1271_boot(wl);
- if (ret < 0)
- goto power_off;
+ ret = wl1271_chip_wakeup(wl);
+ if (ret < 0)
+ goto out;
- ret = wl1271_plt_init(wl);
- if (ret < 0)
- goto irq_disable;
+ ret = wl1271_boot(wl);
+ if (ret < 0)
+ goto out_power_off;
- wl->state = WL1271_STATE_PLT;
- wl1271_notice("firmware booted in PLT mode (%s)",
- wl->chip.fw_ver);
- goto out;
+ wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver);
-irq_disable:
- wl1271_disable_interrupts(wl);
- mutex_unlock(&wl->mutex);
- /* Unlocking the mutex in the middle of handling is
- inherently unsafe. In this case we deem it safe to do,
- because we need to let any possibly pending IRQ out of
- the system (and while we are WL1271_STATE_OFF the IRQ
- work function will not do anything.) Also, any other
- possible concurrent operations will fail due to the
- current state, hence the wl1271 struct should be safe. */
- cancel_work_sync(&wl->irq_work);
- mutex_lock(&wl->mutex);
-power_off:
- wl1271_power_off(wl);
- }
+ ret = wl1271_plt_init(wl);
+ if (ret < 0)
+ goto out_irq_disable;
+
+ /* Make sure power saving is disabled */
+ ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
+ if (ret < 0)
+ goto out_irq_disable;
+
+ goto out;
+
+out_irq_disable:
+ wl1271_disable_interrupts(wl);
+
+out_power_off:
+ wl1271_power_off(wl);
- wl1271_error("firmware boot in PLT mode failed despite %d retries",
- WL1271_BOOT_RETRIES);
out:
mutex_unlock(&wl->mutex);
@@ -798,20 +762,7 @@ int wl1271_plt_stop(struct wl1271 *wl)
static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct wl1271 *wl = hw->priv;
- struct ieee80211_conf *conf = &hw->conf;
- struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
- struct ieee80211_sta *sta = txinfo->control.sta;
- unsigned long flags;
-
- /* peek into the rates configured in the STA entry */
- spin_lock_irqsave(&wl->wl_lock, flags);
- if (sta && sta->supp_rates[conf->channel->band] != wl->sta_rate_set) {
- wl->sta_rate_set = sta->supp_rates[conf->channel->band];
- set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags);
- }
- spin_unlock_irqrestore(&wl->wl_lock, flags);
- /* queue the packet */
skb_queue_tail(&wl->tx_queue, skb);
/*
@@ -833,7 +784,7 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
* protected. Maybe fix this by removing the stupid
* variable altogether and checking the real queue state?
*/
- set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
+ wl->tx_queue_stopped = true;
}
return NETDEV_TX_OK;
@@ -929,7 +880,6 @@ static struct notifier_block wl1271_dev_notifier = {
static int wl1271_op_start(struct ieee80211_hw *hw)
{
struct wl1271 *wl = hw->priv;
- int retries = WL1271_BOOT_RETRIES;
int ret = 0;
wl1271_debug(DEBUG_MAC80211, "mac80211 start");
@@ -943,42 +893,30 @@ static int wl1271_op_start(struct ieee80211_hw *hw)
goto out;
}
- while (retries) {
- retries--;
- ret = wl1271_chip_wakeup(wl);
- if (ret < 0)
- goto power_off;
+ ret = wl1271_chip_wakeup(wl);
+ if (ret < 0)
+ goto out;
- ret = wl1271_boot(wl);
- if (ret < 0)
- goto power_off;
+ ret = wl1271_boot(wl);
+ if (ret < 0)
+ goto out_power_off;
- ret = wl1271_hw_init(wl);
- if (ret < 0)
- goto irq_disable;
+ ret = wl1271_hw_init(wl);
+ if (ret < 0)
+ goto out_irq_disable;
- wl->state = WL1271_STATE_ON;
- wl1271_info("firmware booted (%s)", wl->chip.fw_ver);
- goto out;
+ wl->state = WL1271_STATE_ON;
-irq_disable:
- wl1271_disable_interrupts(wl);
- mutex_unlock(&wl->mutex);
- /* Unlocking the mutex in the middle of handling is
- inherently unsafe. In this case we deem it safe to do,
- because we need to let any possibly pending IRQ out of
- the system (and while we are WL1271_STATE_OFF the IRQ
- work function will not do anything.) Also, any other
- possible concurrent operations will fail due to the
- current state, hence the wl1271 struct should be safe. */
- cancel_work_sync(&wl->irq_work);
- mutex_lock(&wl->mutex);
-power_off:
- wl1271_power_off(wl);
- }
+ wl1271_info("firmware booted (%s)", wl->chip.fw_ver);
+
+ goto out;
+
+out_irq_disable:
+ wl1271_disable_interrupts(wl);
+
+out_power_off:
+ wl1271_power_off(wl);
- wl1271_error("firmware boot failed despite %d retries",
- WL1271_BOOT_RETRIES);
out:
mutex_unlock(&wl->mutex);
@@ -1006,10 +944,11 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
WARN_ON(wl->state != WL1271_STATE_ON);
- if (test_and_clear_bit(WL1271_FLAG_SCANNING, &wl->flags)) {
+ if (wl->scanning) {
mutex_unlock(&wl->mutex);
ieee80211_scan_completed(wl->hw, true);
mutex_lock(&wl->mutex);
+ wl->scanning = false;
}
wl->state = WL1271_STATE_OFF;
@@ -1034,7 +973,10 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wl->band = IEEE80211_BAND_2GHZ;
wl->rx_counter = 0;
+ wl->elp = false;
+ wl->psm = 0;
wl->psm_entry_retry = 0;
+ wl->tx_queue_stopped = false;
wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
wl->tx_blocks_available = 0;
wl->tx_results_count = 0;
@@ -1044,9 +986,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wl->tx_security_seq_32 = 0;
wl->time_offset = 0;
wl->session_counter = 0;
- wl->rate_set = CONF_TX_RATE_MASK_BASIC;
- wl->sta_rate_set = 0;
- wl->flags = 0;
+ wl->joined = false;
for (i = 0; i < NUM_TX_QUEUES; i++)
wl->tx_blocks_freed[i] = 0;
@@ -1056,13 +996,13 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
}
static int wl1271_op_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct wl1271 *wl = hw->priv;
int ret = 0;
wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
- vif->type, vif->addr);
+ conf->type, conf->mac_addr);
mutex_lock(&wl->mutex);
if (wl->vif) {
@@ -1070,9 +1010,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
goto out;
}
- wl->vif = vif;
+ wl->vif = conf->vif;
- switch (vif->type) {
+ switch (conf->type) {
case NL80211_IFTYPE_STATION:
wl->bss_type = BSS_TYPE_STA_BSS;
break;
@@ -1092,7 +1032,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
}
static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct wl1271 *wl = hw->priv;
@@ -1169,51 +1109,6 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw,
}
#endif
-static int wl1271_join_channel(struct wl1271 *wl, int channel)
-{
- int ret = 0;
- /* we need to use a dummy BSSID for now */
- static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde,
- 0xad, 0xbe, 0xef };
-
- /* the dummy join is not required for ad-hoc */
- if (wl->bss_type == BSS_TYPE_IBSS)
- goto out;
-
- /* disable mac filter, so we hear everything */
- wl->rx_config &= ~CFG_BSSID_FILTER_EN;
-
- wl->channel = channel;
- memcpy(wl->bssid, dummy_bssid, ETH_ALEN);
-
- ret = wl1271_cmd_join(wl);
- if (ret < 0)
- goto out;
-
- set_bit(WL1271_FLAG_JOINED, &wl->flags);
-
-out:
- return ret;
-}
-
-static int wl1271_unjoin_channel(struct wl1271 *wl)
-{
- int ret;
-
- /* to stop listening to a channel, we disconnect */
- ret = wl1271_cmd_disconnect(wl);
- if (ret < 0)
- goto out;
-
- clear_bit(WL1271_FLAG_JOINED, &wl->flags);
- wl->channel = 0;
- memset(wl->bssid, 0, ETH_ALEN);
- wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
-
-out:
- return ret;
-}
-
static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
{
struct wl1271 *wl = hw->priv;
@@ -1222,11 +1117,10 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
- wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s",
+ wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
channel,
conf->flags & IEEE80211_CONF_PS ? "on" : "off",
- conf->power_level,
- conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use");
+ conf->power_level);
mutex_lock(&wl->mutex);
@@ -1236,55 +1130,35 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if (ret < 0)
goto out;
- if (changed & IEEE80211_CONF_CHANGE_IDLE) {
- if (conf->flags & IEEE80211_CONF_IDLE &&
- test_bit(WL1271_FLAG_JOINED, &wl->flags))
- wl1271_unjoin_channel(wl);
- else if (!(conf->flags & IEEE80211_CONF_IDLE))
- wl1271_join_channel(wl, channel);
-
- if (conf->flags & IEEE80211_CONF_IDLE) {
- wl->rate_set = CONF_TX_RATE_MASK_BASIC;
- wl->sta_rate_set = 0;
- wl1271_acx_rate_policies(wl);
- }
+ if (channel != wl->channel) {
+ /*
+ * We assume that the stack will configure the right channel
+ * before associating, so we don't need to send a join
+ * command here. We will join the right channel when the
+ * BSSID changes
+ */
+ wl->channel = channel;
}
- /* if the channel changes while joined, join again */
- if (channel != wl->channel &&
- test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
- wl->channel = channel;
- /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */
- ret = wl1271_cmd_join(wl);
- if (ret < 0)
- wl1271_warning("cmd join to update channel failed %d",
- ret);
- } else
- wl->channel = channel;
+ if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
+ wl1271_info("psm enabled");
- if (conf->flags & IEEE80211_CONF_PS &&
- !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
- set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags);
+ wl->psm_requested = true;
/*
* We enter PSM only if we're already associated.
* If we're not, we'll enter it when joining an SSID,
* through the bss_info_changed() hook.
*/
- if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
- wl1271_info("psm enabled");
- ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
- true);
- }
+ ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
} else if (!(conf->flags & IEEE80211_CONF_PS) &&
- test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
+ wl->psm_requested) {
wl1271_info("psm disabled");
- clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags);
+ wl->psm_requested = false;
- if (test_bit(WL1271_FLAG_PSM, &wl->flags))
- ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
- true);
+ if (wl->psm)
+ ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE);
}
if (conf->power_level != wl->power_level) {
@@ -1476,24 +1350,9 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
wl1271_error("Could not add or replace key");
goto out_sleep;
}
-
- /* the default WEP key needs to be configured at least once */
- if (key_type == KEY_WEP) {
- ret = wl1271_cmd_set_default_wep_key(wl,
- wl->default_key);
- if (ret < 0)
- goto out_sleep;
- }
break;
case DISABLE_KEY:
- /* The wl1271 does not allow to remove unicast keys - they
- will be cleared automatically on next CMD_JOIN. Ignore the
- request silently, as we dont want the mac80211 to emit
- an error message. */
- if (!is_broadcast_ether_addr(addr))
- break;
-
ret = wl1271_cmd_set_key(wl, KEY_REMOVE,
key_conf->keyidx, key_type,
key_conf->keylen, key_conf->key,
@@ -1581,21 +1440,20 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
return ret;
}
-static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *beacon)
+static u32 wl1271_enabled_rates_get(struct wl1271 *wl, u64 basic_rate_set)
{
- u8 *ptr = beacon->data +
- offsetof(struct ieee80211_mgmt, u.beacon.variable);
-
- /* find the location of the ssid in the beacon */
- while (ptr < beacon->data + beacon->len) {
- if (ptr[0] == WLAN_EID_SSID) {
- wl->ssid_len = ptr[1];
- memcpy(wl->ssid, ptr+2, wl->ssid_len);
- return;
- }
- ptr += ptr[1];
+ struct ieee80211_supported_band *band;
+ u32 enabled_rates = 0;
+ int bit;
+
+ band = wl->hw->wiphy->bands[wl->band];
+ for (bit = 0; bit < band->n_bitrates; bit++) {
+ if (basic_rate_set & 0x1)
+ enabled_rates |= band->bitrates[bit].hw_value;
+ basic_rate_set >>= 1;
}
- wl1271_error("ad-hoc beacon template has no SSID!\n");
+
+ return enabled_rates;
}
static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
@@ -1605,7 +1463,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
{
enum wl1271_cmd_ps_mode mode;
struct wl1271 *wl = hw->priv;
- bool do_join = false;
int ret;
wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed");
@@ -1616,67 +1473,9 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
if (ret < 0)
goto out;
- if (wl->bss_type == BSS_TYPE_IBSS) {
- /* FIXME: This implements rudimentary ad-hoc support -
- proper templates are on the wish list and notification
- on when they change. This patch will update the templates
- on every call to this function. */
- struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
-
- if (beacon) {
- struct ieee80211_hdr *hdr;
-
- wl1271_ssid_set(wl, beacon);
- ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON,
- beacon->data,
- beacon->len);
-
- if (ret < 0) {
- dev_kfree_skb(beacon);
- goto out_sleep;
- }
-
- hdr = (struct ieee80211_hdr *) beacon->data;
- hdr->frame_control = cpu_to_le16(
- IEEE80211_FTYPE_MGMT |
- IEEE80211_STYPE_PROBE_RESP);
-
- ret = wl1271_cmd_template_set(wl,
- CMD_TEMPL_PROBE_RESPONSE,
- beacon->data,
- beacon->len);
- dev_kfree_skb(beacon);
- if (ret < 0)
- goto out_sleep;
-
- /* Need to update the SSID (for filtering etc) */
- do_join = true;
- }
- }
-
- if ((changed & BSS_CHANGED_BSSID) &&
- /*
- * Now we know the correct bssid, so we send a new join command
- * and enable the BSSID filter
- */
- memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) {
- wl->rx_config |= CFG_BSSID_FILTER_EN;
- memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
- ret = wl1271_cmd_build_null_data(wl);
- if (ret < 0) {
- wl1271_warning("cmd buld null data failed %d",
- ret);
- goto out_sleep;
- }
-
- /* Need to update the BSSID (for filtering etc) */
- do_join = true;
- }
-
if (changed & BSS_CHANGED_ASSOC) {
if (bss_conf->assoc) {
wl->aid = bss_conf->aid;
- set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
/*
* with wl1271, we don't need to update the
@@ -1693,16 +1492,15 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
goto out_sleep;
/* If we want to go in PSM but we're not there yet */
- if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
- !test_bit(WL1271_FLAG_PSM, &wl->flags)) {
+ if (wl->psm_requested && !wl->psm) {
mode = STATION_POWER_SAVE_MODE;
- ret = wl1271_ps_set_mode(wl, mode, true);
+ ret = wl1271_ps_set_mode(wl, mode);
if (ret < 0)
goto out_sleep;
}
} else {
/* use defaults when not associated */
- clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
+ wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
wl->aid = 0;
}
@@ -1737,13 +1535,15 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
}
}
- if (do_join) {
- ret = wl1271_cmd_join(wl);
+ if (changed & BSS_CHANGED_BASIC_RATES) {
+ wl->basic_rate_set = wl1271_enabled_rates_get(
+ wl, bss_conf->basic_rates);
+
+ ret = wl1271_acx_rate_policies(wl, wl->basic_rate_set);
if (ret < 0) {
- wl1271_warning("cmd join failed %d", ret);
+ wl1271_warning("Set rate policies failed %d", ret);
goto out_sleep;
}
- set_bit(WL1271_FLAG_JOINED, &wl->flags);
}
out_sleep:
@@ -1753,43 +1553,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
mutex_unlock(&wl->mutex);
}
-static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
- const struct ieee80211_tx_queue_params *params)
-{
- struct wl1271 *wl = hw->priv;
- int ret;
-
- mutex_lock(&wl->mutex);
-
- wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue);
-
- ret = wl1271_ps_elp_wakeup(wl, false);
- if (ret < 0)
- goto out;
-
- ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue),
- params->cw_min, params->cw_max,
- params->aifs, params->txop);
- if (ret < 0)
- goto out_sleep;
-
- ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue),
- CONF_CHANNEL_TYPE_EDCF,
- wl1271_tx_get_queue(queue),
- CONF_PS_SCHEME_LEGACY_PSPOLL,
- CONF_ACK_POLICY_LEGACY, 0, 0);
- if (ret < 0)
- goto out_sleep;
-
-out_sleep:
- wl1271_ps_elp_sleep(wl);
-
-out:
- mutex_unlock(&wl->mutex);
-
- return ret;
-}
-
/* can't be const, mac80211 writes to this */
static struct ieee80211_rate wl1271_rates[] = {
@@ -1836,19 +1599,19 @@ static struct ieee80211_rate wl1271_rates[] = {
/* can't be const, mac80211 writes to this */
static struct ieee80211_channel wl1271_channels[] = {
- { .hw_value = 1, .center_freq = 2412, .max_power = 25 },
- { .hw_value = 2, .center_freq = 2417, .max_power = 25 },
- { .hw_value = 3, .center_freq = 2422, .max_power = 25 },
- { .hw_value = 4, .center_freq = 2427, .max_power = 25 },
- { .hw_value = 5, .center_freq = 2432, .max_power = 25 },
- { .hw_value = 6, .center_freq = 2437, .max_power = 25 },
- { .hw_value = 7, .center_freq = 2442, .max_power = 25 },
- { .hw_value = 8, .center_freq = 2447, .max_power = 25 },
- { .hw_value = 9, .center_freq = 2452, .max_power = 25 },
- { .hw_value = 10, .center_freq = 2457, .max_power = 25 },
- { .hw_value = 11, .center_freq = 2462, .max_power = 25 },
- { .hw_value = 12, .center_freq = 2467, .max_power = 25 },
- { .hw_value = 13, .center_freq = 2472, .max_power = 25 },
+ { .hw_value = 1, .center_freq = 2412},
+ { .hw_value = 2, .center_freq = 2417},
+ { .hw_value = 3, .center_freq = 2422},
+ { .hw_value = 4, .center_freq = 2427},
+ { .hw_value = 5, .center_freq = 2432},
+ { .hw_value = 6, .center_freq = 2437},
+ { .hw_value = 7, .center_freq = 2442},
+ { .hw_value = 8, .center_freq = 2447},
+ { .hw_value = 9, .center_freq = 2452},
+ { .hw_value = 10, .center_freq = 2457},
+ { .hw_value = 11, .center_freq = 2462},
+ { .hw_value = 12, .center_freq = 2467},
+ { .hw_value = 13, .center_freq = 2472},
};
/* can't be const, mac80211 writes to this */
@@ -1955,8 +1718,6 @@ static const struct ieee80211_ops wl1271_ops = {
.hw_scan = wl1271_op_hw_scan,
.bss_info_changed = wl1271_op_bss_info_changed,
.set_rts_threshold = wl1271_op_set_rts_threshold,
- .conf_tx = wl1271_op_conf_tx,
- CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
};
static int wl1271_register_hw(struct wl1271 *wl)
@@ -1996,8 +1757,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
IEEE80211_HW_BEACON_FILTER |
IEEE80211_HW_SUPPORTS_PS;
- wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC);
+ wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
wl->hw->wiphy->max_scan_ssids = 1;
wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz;
@@ -2025,17 +1785,24 @@ static struct platform_device wl1271_device = {
};
#define WL1271_DEFAULT_CHANNEL 0
-
-static struct ieee80211_hw *wl1271_alloc_hw(void)
+static int __devinit wl1271_probe(struct spi_device *spi)
{
+ struct wl12xx_platform_data *pdata;
struct ieee80211_hw *hw;
struct wl1271 *wl;
- int i;
+ int ret, i;
+ static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
+
+ pdata = spi->dev.platform_data;
+ if (!pdata) {
+ wl1271_error("no platform data");
+ return -ENODEV;
+ }
hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
if (!hw) {
wl1271_error("could not alloc ieee80211_hw");
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
}
wl = hw->priv;
@@ -2044,80 +1811,44 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
INIT_LIST_HEAD(&wl->list);
wl->hw = hw;
+ dev_set_drvdata(&spi->dev, wl);
+ wl->spi = spi;
skb_queue_head_init(&wl->tx_queue);
INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work);
wl->channel = WL1271_DEFAULT_CHANNEL;
+ wl->scanning = false;
wl->default_key = 0;
wl->rx_counter = 0;
wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
+ wl->elp = false;
+ wl->psm = 0;
+ wl->psm_requested = false;
wl->psm_entry_retry = 0;
+ wl->tx_queue_stopped = false;
wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
- wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC;
- wl->rate_set = CONF_TX_RATE_MASK_BASIC;
- wl->sta_rate_set = 0;
+ wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
wl->band = IEEE80211_BAND_2GHZ;
wl->vif = NULL;
- wl->flags = 0;
+ wl->joined = false;
for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
wl->tx_frames[i] = NULL;
spin_lock_init(&wl->wl_lock);
+ /*
+ * In case our MAC address is not correctly set,
+ * we use a random but Nokia MAC.
+ */
+ memcpy(wl->mac_addr, nokia_oui, 3);
+ get_random_bytes(wl->mac_addr + 3, 3);
+
wl->state = WL1271_STATE_OFF;
mutex_init(&wl->mutex);
- /* Apply default driver configuration. */
- wl1271_conf_init(wl);
-
- return hw;
-}
-
-int wl1271_free_hw(struct wl1271 *wl)
-{
- ieee80211_unregister_hw(wl->hw);
-
- wl1271_debugfs_exit(wl);
-
- kfree(wl->target_mem_map);
- vfree(wl->fw);
- wl->fw = NULL;
- kfree(wl->nvs);
- wl->nvs = NULL;
-
- kfree(wl->fw_status);
- kfree(wl->tx_res_if);
-
- ieee80211_free_hw(wl->hw);
-
- return 0;
-}
-
-static int __devinit wl1271_probe(struct spi_device *spi)
-{
- struct wl12xx_platform_data *pdata;
- struct ieee80211_hw *hw;
- struct wl1271 *wl;
- int ret;
-
- pdata = spi->dev.platform_data;
- if (!pdata) {
- wl1271_error("no platform data");
- return -ENODEV;
- }
-
- hw = wl1271_alloc_hw();
- if (IS_ERR(hw))
- return PTR_ERR(hw);
-
- wl = hw->priv;
-
- dev_set_drvdata(&spi->dev, wl);
- wl->spi = spi;
-
/* This is the only SPI value that we need to set here, the rest
* comes from the board-peripherals file */
spi->bits_per_word = 32;
@@ -2159,6 +1890,9 @@ static int __devinit wl1271_probe(struct spi_device *spi)
}
dev_set_drvdata(&wl1271_device.dev, wl);
+ /* Apply default driver configuration. */
+ wl1271_conf_init(wl);
+
ret = wl1271_init_ieee80211(wl);
if (ret)
goto out_platform;
@@ -2189,10 +1923,21 @@ static int __devexit wl1271_remove(struct spi_device *spi)
{
struct wl1271 *wl = dev_get_drvdata(&spi->dev);
+ ieee80211_unregister_hw(wl->hw);
+
+ wl1271_debugfs_exit(wl);
platform_device_unregister(&wl1271_device);
free_irq(wl->irq, wl);
+ kfree(wl->target_mem_map);
+ vfree(wl->fw);
+ wl->fw = NULL;
+ kfree(wl->nvs);
+ wl->nvs = NULL;
- wl1271_free_hw(wl);
+ kfree(wl->fw_status);
+ kfree(wl->tx_res_if);
+
+ ieee80211_free_hw(wl->hw);
return 0;
}
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_ps.c b/trunk/drivers/net/wireless/wl12xx/wl1271_ps.c
index e2b1ebf096e8..507cd91d7eed 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_ps.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_ps.c
@@ -24,7 +24,6 @@
#include "wl1271_reg.h"
#include "wl1271_ps.h"
#include "wl1271_spi.h"
-#include "wl1271_io.h"
#define WL1271_WAKEUP_TIMEOUT 500
@@ -40,13 +39,12 @@ void wl1271_elp_work(struct work_struct *work)
mutex_lock(&wl->mutex);
- if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) ||
- !test_bit(WL1271_FLAG_PSM, &wl->flags))
+ if (wl->elp || !wl->psm)
goto out;
wl1271_debug(DEBUG_PSM, "chip to elp");
wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
- set_bit(WL1271_FLAG_IN_ELP, &wl->flags);
+ wl->elp = true;
out:
mutex_unlock(&wl->mutex);
@@ -57,7 +55,7 @@ void wl1271_elp_work(struct work_struct *work)
/* Routines to toggle sleep mode while in ELP */
void wl1271_ps_elp_sleep(struct wl1271 *wl)
{
- if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
+ if (wl->psm) {
cancel_delayed_work(&wl->elp_work);
ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
msecs_to_jiffies(ELP_ENTRY_DELAY));
@@ -72,7 +70,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
u32 start_time = jiffies;
bool pending = false;
- if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags))
+ if (!wl->elp)
return 0;
wl1271_debug(DEBUG_PSM, "waking up chip from elp");
@@ -103,7 +101,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
}
}
- clear_bit(WL1271_FLAG_IN_ELP, &wl->flags);
+ wl->elp = false;
wl1271_debug(DEBUG_PSM, "wakeup time: %u ms",
jiffies_to_msecs(jiffies - start_time));
@@ -119,8 +117,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
return 0;
}
-int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
- bool send)
+int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode)
{
int ret;
@@ -128,11 +125,25 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
case STATION_POWER_SAVE_MODE:
wl1271_debug(DEBUG_PSM, "entering psm");
- ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE, send);
+ /* enable beacon filtering */
+ ret = wl1271_acx_beacon_filter_opt(wl, true);
if (ret < 0)
return ret;
- set_bit(WL1271_FLAG_PSM, &wl->flags);
+ /* enable beacon early termination */
+ ret = wl1271_acx_bet_enable(wl, true);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
+ if (ret < 0)
+ return ret;
+
+ wl1271_ps_elp_sleep(wl);
+ if (ret < 0)
+ return ret;
+
+ wl->psm = 1;
break;
case STATION_ACTIVE_MODE:
default:
@@ -151,11 +162,11 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
if (ret < 0)
return ret;
- ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE, send);
+ ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
if (ret < 0)
return ret;
- clear_bit(WL1271_FLAG_PSM, &wl->flags);
+ wl->psm = 0;
break;
}
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_ps.h b/trunk/drivers/net/wireless/wl12xx/wl1271_ps.h
index 940276f517a4..779653d0ae85 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_ps.h
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_ps.h
@@ -27,8 +27,7 @@
#include "wl1271.h"
#include "wl1271_acx.h"
-int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
- bool send);
+int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode);
void wl1271_ps_elp_sleep(struct wl1271 *wl);
int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake);
void wl1271_elp_work(struct work_struct *work);
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_reg.h b/trunk/drivers/net/wireless/wl12xx/wl1271_reg.h
index 990960771528..1f237389d1c7 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_reg.h
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_reg.h
@@ -62,10 +62,73 @@
#define WL1271_SLV_REG_DATA (REGISTERS_BASE + 0x0008)
#define WL1271_SLV_REG_ADATA (REGISTERS_BASE + 0x000c)
#define WL1271_SLV_MEM_DATA (REGISTERS_BASE + 0x0018)
+/*
+ * Interrupt registers.
+ * 64 bit interrupt sources registers ws ced.
+ * sme interupts were removed and new ones were added.
+ * Order was changed.
+ */
+#define FIQ_MASK (REGISTERS_BASE + 0x0400)
+#define FIQ_MASK_L (REGISTERS_BASE + 0x0400)
+#define FIQ_MASK_H (REGISTERS_BASE + 0x0404)
+#define FIQ_MASK_SET (REGISTERS_BASE + 0x0408)
+#define FIQ_MASK_SET_L (REGISTERS_BASE + 0x0408)
+#define FIQ_MASK_SET_H (REGISTERS_BASE + 0x040C)
+#define FIQ_MASK_CLR (REGISTERS_BASE + 0x0410)
+#define FIQ_MASK_CLR_L (REGISTERS_BASE + 0x0410)
+#define FIQ_MASK_CLR_H (REGISTERS_BASE + 0x0414)
+#define IRQ_MASK (REGISTERS_BASE + 0x0418)
+#define IRQ_MASK_L (REGISTERS_BASE + 0x0418)
+#define IRQ_MASK_H (REGISTERS_BASE + 0x041C)
+#define IRQ_MASK_SET (REGISTERS_BASE + 0x0420)
+#define IRQ_MASK_SET_L (REGISTERS_BASE + 0x0420)
+#define IRQ_MASK_SET_H (REGISTERS_BASE + 0x0424)
+#define IRQ_MASK_CLR (REGISTERS_BASE + 0x0428)
+#define IRQ_MASK_CLR_L (REGISTERS_BASE + 0x0428)
+#define IRQ_MASK_CLR_H (REGISTERS_BASE + 0x042C)
+#define ECPU_MASK (REGISTERS_BASE + 0x0448)
+#define FIQ_STS_L (REGISTERS_BASE + 0x044C)
+#define FIQ_STS_H (REGISTERS_BASE + 0x0450)
+#define IRQ_STS_L (REGISTERS_BASE + 0x0454)
+#define IRQ_STS_H (REGISTERS_BASE + 0x0458)
+#define INT_STS_ND (REGISTERS_BASE + 0x0464)
+#define INT_STS_RAW_L (REGISTERS_BASE + 0x0464)
+#define INT_STS_RAW_H (REGISTERS_BASE + 0x0468)
+#define INT_STS_CLR (REGISTERS_BASE + 0x04B4)
+#define INT_STS_CLR_L (REGISTERS_BASE + 0x04B4)
+#define INT_STS_CLR_H (REGISTERS_BASE + 0x04B8)
+#define INT_ACK (REGISTERS_BASE + 0x046C)
+#define INT_ACK_L (REGISTERS_BASE + 0x046C)
+#define INT_ACK_H (REGISTERS_BASE + 0x0470)
+#define INT_TRIG (REGISTERS_BASE + 0x0474)
+#define INT_TRIG_L (REGISTERS_BASE + 0x0474)
+#define INT_TRIG_H (REGISTERS_BASE + 0x0478)
+#define HOST_STS_L (REGISTERS_BASE + 0x045C)
+#define HOST_STS_H (REGISTERS_BASE + 0x0460)
+#define HOST_MASK (REGISTERS_BASE + 0x0430)
+#define HOST_MASK_L (REGISTERS_BASE + 0x0430)
+#define HOST_MASK_H (REGISTERS_BASE + 0x0434)
+#define HOST_MASK_SET (REGISTERS_BASE + 0x0438)
+#define HOST_MASK_SET_L (REGISTERS_BASE + 0x0438)
+#define HOST_MASK_SET_H (REGISTERS_BASE + 0x043C)
+#define HOST_MASK_CLR (REGISTERS_BASE + 0x0440)
+#define HOST_MASK_CLR_L (REGISTERS_BASE + 0x0440)
+#define HOST_MASK_CLR_H (REGISTERS_BASE + 0x0444)
#define ACX_REG_INTERRUPT_TRIG (REGISTERS_BASE + 0x0474)
#define ACX_REG_INTERRUPT_TRIG_H (REGISTERS_BASE + 0x0478)
+/* Host Interrupts*/
+#define HINT_MASK (REGISTERS_BASE + 0x0494)
+#define HINT_MASK_SET (REGISTERS_BASE + 0x0498)
+#define HINT_MASK_CLR (REGISTERS_BASE + 0x049C)
+#define HINT_STS_ND_MASKED (REGISTERS_BASE + 0x04A0)
+/*1150 spec calls this HINT_STS_RAW*/
+#define HINT_STS_ND (REGISTERS_BASE + 0x04B0)
+#define HINT_STS_CLR (REGISTERS_BASE + 0x04A4)
+#define HINT_ACK (REGISTERS_BASE + 0x04A8)
+#define HINT_TRIG (REGISTERS_BASE + 0x04AC)
+
/*=============================================
Host Interrupt Mask Register - 32bit (RW)
------------------------------------------
@@ -369,6 +432,16 @@
| CFG_RX_PRSP_EN)
+/*===============================================
+ Phy regs
+ ===============================================*/
+#define ACX_PHY_ADDR_REG SBB_ADDR
+#define ACX_PHY_DATA_REG SBB_DATA
+#define ACX_PHY_CTRL_REG SBB_CTL
+#define ACX_PHY_REG_WR_MASK 0x00000001ul
+#define ACX_PHY_REG_RD_MASK 0x00000002ul
+
+
/*===============================================
EEPROM Read/Write Request 32bit RW
------------------------------------------
@@ -438,6 +511,28 @@
#define ACX_CONT_WIND_MIN_MASK 0x0000007f
#define ACX_CONT_WIND_MAX 0x03ff0000
+/*
+ * Indirect slave register/memory registers
+ * ----------------------------------------
+ */
+#define HW_SLAVE_REG_ADDR_REG 0x00000004
+#define HW_SLAVE_REG_DATA_REG 0x00000008
+#define HW_SLAVE_REG_CTRL_REG 0x0000000c
+
+#define SLAVE_AUTO_INC 0x00010000
+#define SLAVE_NO_AUTO_INC 0x00000000
+#define SLAVE_HOST_LITTLE_ENDIAN 0x00000000
+
+#define HW_SLAVE_MEM_ADDR_REG SLV_MEM_ADDR
+#define HW_SLAVE_MEM_DATA_REG SLV_MEM_DATA
+#define HW_SLAVE_MEM_CTRL_REG SLV_MEM_CTL
+#define HW_SLAVE_MEM_ENDIAN_REG SLV_END_CTL
+
+#define HW_FUNC_EVENT_INT_EN 0x8000
+#define HW_FUNC_EVENT_MASK_REG 0x00000034
+
+#define ACX_MAC_TIMESTAMP_REG (MAC_TIMESTAMP)
+
/*===============================================
HI_CFG Interface Configuration Register Values
------------------------------------------
@@ -552,6 +647,10 @@ b12-b0 - Supported Rate indicator bits as defined below.
******************************************************************************/
+#define TNETW1251_CHIP_ID_PG1_0 0x07010101
+#define TNETW1251_CHIP_ID_PG1_1 0x07020101
+#define TNETW1251_CHIP_ID_PG1_2 0x07030101
+
/*************************************************************************
Interrupt Trigger Register (Host -> WiLink)
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_rx.c b/trunk/drivers/net/wireless/wl12xx/wl1271_rx.c
index 6730f5b96e76..ca645f38109b 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_rx.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -26,7 +26,6 @@
#include "wl1271_reg.h"
#include "wl1271_rx.h"
#include "wl1271_spi.h"
-#include "wl1271_io.h"
static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status,
u32 drv_rx_counter)
@@ -167,7 +166,7 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
}
buf = skb_put(skb, length);
- wl1271_read(wl, WL1271_SLV_MEM_DATA, buf, length, true);
+ wl1271_spi_read(wl, WL1271_SLV_MEM_DATA, buf, length, true);
/* the data read starts with the descriptor */
desc = (struct wl1271_rx_descriptor *) buf;
@@ -211,13 +210,15 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
wl->rx_mem_pool_addr.addr + 4;
/* Choose the block we want to read */
- wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr,
- sizeof(wl->rx_mem_pool_addr), false);
+ wl1271_spi_write(wl, WL1271_SLV_REG_DATA,
+ &wl->rx_mem_pool_addr,
+ sizeof(wl->rx_mem_pool_addr), false);
wl1271_rx_handle_data(wl, buf_size);
wl->rx_counter++;
drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
- wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
}
+
+ wl1271_spi_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
}
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_spi.c b/trunk/drivers/net/wireless/wl12xx/wl1271_spi.c
index 67a82934f36e..02978a16e732 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_spi.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -30,6 +30,28 @@
#include "wl12xx_80211.h"
#include "wl1271_spi.h"
+static int wl1271_translate_addr(struct wl1271 *wl, int addr)
+{
+ /*
+ * To translate, first check to which window of addresses the
+ * particular address belongs. Then subtract the starting address
+ * of that window from the address. Then, add offset of the
+ * translated region.
+ *
+ * The translated regions occur next to each other in physical device
+ * memory, so just add the sizes of the preceeding address regions to
+ * get the offset to the new region.
+ *
+ * Currently, only the two first regions are addressed, and the
+ * assumption is that all addresses will fall into either of those
+ * two.
+ */
+ if ((addr >= wl->part.reg.start) &&
+ (addr < wl->part.reg.start + wl->part.reg.size))
+ return addr - wl->part.reg.start + wl->part.mem.size;
+ else
+ return addr - wl->part.mem.start;
+}
void wl1271_spi_reset(struct wl1271 *wl)
{
@@ -111,6 +133,67 @@ void wl1271_spi_init(struct wl1271 *wl)
wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
}
+/* Set the SPI partitions to access the chip addresses
+ *
+ * To simplify driver code, a fixed (virtual) memory map is defined for
+ * register and memory addresses. Because in the chipset, in different stages
+ * of operation, those addresses will move around, an address translation
+ * mechanism is required.
+ *
+ * There are four partitions (three memory and one register partition),
+ * which are mapped to two different areas of the hardware memory.
+ *
+ * Virtual address
+ * space
+ *
+ * | |
+ * ...+----+--> mem.start
+ * Physical address ... | |
+ * space ... | | [PART_0]
+ * ... | |
+ * 00000000 <--+----+... ...+----+--> mem.start + mem.size
+ * | | ... | |
+ * |MEM | ... | |
+ * | | ... | |
+ * mem.size <--+----+... | | {unused area)
+ * | | ... | |
+ * |REG | ... | |
+ * mem.size | | ... | |
+ * + <--+----+... ...+----+--> reg.start
+ * reg.size | | ... | |
+ * |MEM2| ... | | [PART_1]
+ * | | ... | |
+ * ...+----+--> reg.start + reg.size
+ * | |
+ *
+ */
+int wl1271_set_partition(struct wl1271 *wl,
+ struct wl1271_partition_set *p)
+{
+ /* copy partition info */
+ memcpy(&wl->part, p, sizeof(*p));
+
+ wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+ p->mem.start, p->mem.size);
+ wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+ p->reg.start, p->reg.size);
+ wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X",
+ p->mem2.start, p->mem2.size);
+ wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X",
+ p->mem3.start, p->mem3.size);
+
+ /* write partition info to the chipset */
+ wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start);
+ wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size);
+ wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start);
+ wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size);
+ wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start);
+ wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size);
+ wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
+
+ return 0;
+}
+
#define WL1271_BUSY_WORD_TIMEOUT 1000
/* FIXME: Check busy words, removed due to SPI bug */
@@ -255,3 +338,78 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
}
+
+void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len,
+ bool fixed)
+{
+ int physical;
+
+ physical = wl1271_translate_addr(wl, addr);
+
+ wl1271_spi_raw_read(wl, physical, buf, len, fixed);
+}
+
+void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len,
+ bool fixed)
+{
+ int physical;
+
+ physical = wl1271_translate_addr(wl, addr);
+
+ wl1271_spi_raw_write(wl, physical, buf, len, fixed);
+}
+
+u32 wl1271_spi_read32(struct wl1271 *wl, int addr)
+{
+ return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr));
+}
+
+void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val)
+{
+ wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val);
+}
+
+void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val)
+{
+ /* write address >> 1 + 0x30000 to OCP_POR_CTR */
+ addr = (addr >> 1) + 0x30000;
+ wl1271_spi_write32(wl, OCP_POR_CTR, addr);
+
+ /* write value to OCP_POR_WDATA */
+ wl1271_spi_write32(wl, OCP_DATA_WRITE, val);
+
+ /* write 1 to OCP_CMD */
+ wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_WRITE);
+}
+
+u16 wl1271_top_reg_read(struct wl1271 *wl, int addr)
+{
+ u32 val;
+ int timeout = OCP_CMD_LOOP;
+
+ /* write address >> 1 + 0x30000 to OCP_POR_CTR */
+ addr = (addr >> 1) + 0x30000;
+ wl1271_spi_write32(wl, OCP_POR_CTR, addr);
+
+ /* write 2 to OCP_CMD */
+ wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_READ);
+
+ /* poll for data ready */
+ do {
+ val = wl1271_spi_read32(wl, OCP_DATA_READ);
+ timeout--;
+ } while (!(val & OCP_READY_MASK) && timeout);
+
+ if (!timeout) {
+ wl1271_warning("Top register access timed out.");
+ return 0xffff;
+ }
+
+ /* check data status and return if OK */
+ if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK)
+ return val & 0xffff;
+ else {
+ wl1271_warning("Top register access returned error.");
+ return 0xffff;
+ }
+}
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_spi.h b/trunk/drivers/net/wireless/wl12xx/wl1271_spi.h
index a803596dad4a..cb7df1c56314 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_spi.h
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_spi.h
@@ -90,7 +90,37 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf,
size_t len, bool fixed);
+/* Translated target IO */
+void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len,
+ bool fixed);
+void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len,
+ bool fixed);
+u32 wl1271_spi_read32(struct wl1271 *wl, int addr);
+void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val);
+
+/* Top Register IO */
+void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val);
+u16 wl1271_top_reg_read(struct wl1271 *wl, int addr);
+
/* INIT and RESET words */
void wl1271_spi_reset(struct wl1271 *wl);
void wl1271_spi_init(struct wl1271 *wl);
+int wl1271_set_partition(struct wl1271 *wl,
+ struct wl1271_partition_set *p);
+
+static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr)
+{
+ wl1271_spi_raw_read(wl, addr, &wl->buffer_32,
+ sizeof(wl->buffer_32), false);
+
+ return wl->buffer_32;
+}
+
+static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val)
+{
+ wl->buffer_32 = val;
+ wl1271_spi_raw_write(wl, addr, &wl->buffer_32,
+ sizeof(wl->buffer_32), false);
+}
+
#endif /* __WL1271_SPI_H__ */
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_testmode.c b/trunk/drivers/net/wireless/wl12xx/wl1271_testmode.c
deleted file mode 100644
index 3919102e942e..000000000000
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_testmode.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * This file is part of wl1271
- *
- * Copyright (C) 2010 Nokia Corporation
- *
- * Contact: Luciano Coelho
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-#include "wl1271_testmode.h"
-
-#include
-
-#include "wl1271.h"
-#include "wl1271_spi.h"
-#include "wl1271_acx.h"
-
-#define WL1271_TM_MAX_DATA_LENGTH 1024
-
-enum wl1271_tm_commands {
- WL1271_TM_CMD_UNSPEC,
- WL1271_TM_CMD_TEST,
- WL1271_TM_CMD_INTERROGATE,
- WL1271_TM_CMD_CONFIGURE,
- WL1271_TM_CMD_NVS_PUSH,
- WL1271_TM_CMD_SET_PLT_MODE,
-
- __WL1271_TM_CMD_AFTER_LAST
-};
-#define WL1271_TM_CMD_MAX (__WL1271_TM_CMD_AFTER_LAST - 1)
-
-enum wl1271_tm_attrs {
- WL1271_TM_ATTR_UNSPEC,
- WL1271_TM_ATTR_CMD_ID,
- WL1271_TM_ATTR_ANSWER,
- WL1271_TM_ATTR_DATA,
- WL1271_TM_ATTR_IE_ID,
- WL1271_TM_ATTR_PLT_MODE,
-
- __WL1271_TM_ATTR_AFTER_LAST
-};
-#define WL1271_TM_ATTR_MAX (__WL1271_TM_ATTR_AFTER_LAST - 1)
-
-static struct nla_policy wl1271_tm_policy[WL1271_TM_ATTR_MAX + 1] = {
- [WL1271_TM_ATTR_CMD_ID] = { .type = NLA_U32 },
- [WL1271_TM_ATTR_ANSWER] = { .type = NLA_U8 },
- [WL1271_TM_ATTR_DATA] = { .type = NLA_BINARY,
- .len = WL1271_TM_MAX_DATA_LENGTH },
- [WL1271_TM_ATTR_IE_ID] = { .type = NLA_U32 },
- [WL1271_TM_ATTR_PLT_MODE] = { .type = NLA_U32 },
-};
-
-
-static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[])
-{
- int buf_len, ret, len;
- struct sk_buff *skb;
- void *buf;
- u8 answer = 0;
-
- wl1271_debug(DEBUG_TESTMODE, "testmode cmd test");
-
- if (!tb[WL1271_TM_ATTR_DATA])
- return -EINVAL;
-
- buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
- buf_len = nla_len(tb[WL1271_TM_ATTR_DATA]);
-
- if (tb[WL1271_TM_ATTR_ANSWER])
- answer = nla_get_u8(tb[WL1271_TM_ATTR_ANSWER]);
-
- if (buf_len > sizeof(struct wl1271_command))
- return -EMSGSIZE;
-
- mutex_lock(&wl->mutex);
- ret = wl1271_cmd_test(wl, buf, buf_len, answer);
- mutex_unlock(&wl->mutex);
-
- if (ret < 0) {
- wl1271_warning("testmode cmd test failed: %d", ret);
- return ret;
- }
-
- if (answer) {
- len = nla_total_size(buf_len);
- skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len);
- if (!skb)
- return -ENOMEM;
-
- NLA_PUT(skb, WL1271_TM_ATTR_DATA, buf_len, buf);
- ret = cfg80211_testmode_reply(skb);
- if (ret < 0)
- return ret;
- }
-
- return 0;
-
-nla_put_failure:
- kfree_skb(skb);
- return -EMSGSIZE;
-}
-
-static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[])
-{
- int ret;
- struct wl1271_command *cmd;
- struct sk_buff *skb;
- u8 ie_id;
-
- wl1271_debug(DEBUG_TESTMODE, "testmode cmd interrogate");
-
- if (!tb[WL1271_TM_ATTR_IE_ID])
- return -EINVAL;
-
- ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]);
-
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
-
- mutex_lock(&wl->mutex);
- ret = wl1271_cmd_interrogate(wl, ie_id, cmd, sizeof(*cmd));
- mutex_unlock(&wl->mutex);
-
- if (ret < 0) {
- wl1271_warning("testmode cmd interrogate failed: %d", ret);
- return ret;
- }
-
- skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, sizeof(*cmd));
- if (!skb)
- return -ENOMEM;
-
- NLA_PUT(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd);
-
- return 0;
-
-nla_put_failure:
- kfree_skb(skb);
- return -EMSGSIZE;
-}
-
-static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[])
-{
- int buf_len, ret;
- void *buf;
- u8 ie_id;
-
- wl1271_debug(DEBUG_TESTMODE, "testmode cmd configure");
-
- if (!tb[WL1271_TM_ATTR_DATA])
- return -EINVAL;
- if (!tb[WL1271_TM_ATTR_IE_ID])
- return -EINVAL;
-
- ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]);
- buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
- buf_len = nla_len(tb[WL1271_TM_ATTR_DATA]);
-
- if (buf_len > sizeof(struct wl1271_command))
- return -EMSGSIZE;
-
- mutex_lock(&wl->mutex);
- ret = wl1271_cmd_configure(wl, ie_id, buf, buf_len);
- mutex_unlock(&wl->mutex);
-
- if (ret < 0) {
- wl1271_warning("testmode cmd configure failed: %d", ret);
- return ret;
- }
-
- return 0;
-}
-
-static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
-{
- int ret = 0;
- size_t len;
- void *buf;
-
- wl1271_debug(DEBUG_TESTMODE, "testmode cmd nvs push");
-
- if (!tb[WL1271_TM_ATTR_DATA])
- return -EINVAL;
-
- buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
- len = nla_len(tb[WL1271_TM_ATTR_DATA]);
-
- if (len != sizeof(struct wl1271_nvs_file)) {
- wl1271_error("nvs size is not as expected: %zu != %zu",
- len, sizeof(struct wl1271_nvs_file));
- return -EMSGSIZE;
- }
-
- mutex_lock(&wl->mutex);
-
- kfree(wl->nvs);
-
- wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL);
- if (!wl->nvs) {
- wl1271_error("could not allocate memory for the nvs file");
- ret = -ENOMEM;
- goto out;
- }
-
- memcpy(wl->nvs, buf, len);
-
- wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs");
-
-out:
- mutex_unlock(&wl->mutex);
-
- return ret;
-}
-
-static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[])
-{
- u32 val;
- int ret;
-
- wl1271_debug(DEBUG_TESTMODE, "testmode cmd set plt mode");
-
- if (!tb[WL1271_TM_ATTR_PLT_MODE])
- return -EINVAL;
-
- val = nla_get_u32(tb[WL1271_TM_ATTR_PLT_MODE]);
-
- switch (val) {
- case 0:
- ret = wl1271_plt_stop(wl);
- break;
- case 1:
- ret = wl1271_plt_start(wl);
- break;
- default:
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
-int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len)
-{
- struct wl1271 *wl = hw->priv;
- struct nlattr *tb[WL1271_TM_ATTR_MAX + 1];
- int err;
-
- err = nla_parse(tb, WL1271_TM_ATTR_MAX, data, len, wl1271_tm_policy);
- if (err)
- return err;
-
- if (!tb[WL1271_TM_ATTR_CMD_ID])
- return -EINVAL;
-
- switch (nla_get_u32(tb[WL1271_TM_ATTR_CMD_ID])) {
- case WL1271_TM_CMD_TEST:
- return wl1271_tm_cmd_test(wl, tb);
- case WL1271_TM_CMD_INTERROGATE:
- return wl1271_tm_cmd_interrogate(wl, tb);
- case WL1271_TM_CMD_CONFIGURE:
- return wl1271_tm_cmd_configure(wl, tb);
- case WL1271_TM_CMD_NVS_PUSH:
- return wl1271_tm_cmd_nvs_push(wl, tb);
- case WL1271_TM_CMD_SET_PLT_MODE:
- return wl1271_tm_cmd_set_plt_mode(wl, tb);
- default:
- return -EOPNOTSUPP;
- }
-}
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_testmode.h b/trunk/drivers/net/wireless/wl12xx/wl1271_testmode.h
deleted file mode 100644
index c196d28f9d9d..000000000000
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_testmode.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * This file is part of wl1271
- *
- * Copyright (C) 2010 Nokia Corporation
- *
- * Contact: Luciano Coelho
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __WL1271_TESTMODE_H__
-#define __WL1271_TESTMODE_H__
-
-#include
-
-int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len);
-
-#endif /* __WL1271_TESTMODE_H__ */
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_tx.c b/trunk/drivers/net/wireless/wl12xx/wl1271_tx.c
index 811e739d05bf..00af065c77c2 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -26,7 +26,6 @@
#include "wl1271.h"
#include "wl1271_spi.h"
-#include "wl1271_io.h"
#include "wl1271_reg.h"
#include "wl1271_ps.h"
#include "wl1271_tx.h"
@@ -88,7 +87,7 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
u32 extra, struct ieee80211_tx_info *control)
{
struct wl1271_tx_hw_descr *desc;
- int pad, ac;
+ int pad;
u16 tx_attr;
desc = (struct wl1271_tx_hw_descr *) skb->data;
@@ -108,11 +107,9 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
/* configure the tx attributes */
tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
-
- /* queue */
- ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
- desc->tid = wl1271_tx_ac_to_tid(ac);
-
+ /* FIXME: do we know the packet priority? can we identify mgmt
+ packets, and use max prio for them at least? */
+ desc->tid = 0;
desc->aid = TX_HW_DEFAULT_AID;
desc->reserved = 0;
@@ -124,11 +121,6 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
pad = pad - skb->len;
tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD;
- /* if the packets are destined for AP (have a STA entry) send them
- with AP rate policies, otherwise use default basic rates */
- if (control->control.sta)
- tx_attr |= ACX_TX_AP_FULL_RATE << TX_HW_ATTR_OFST_RATE_POLICY;
-
desc->tx_attr = cpu_to_le16(tx_attr);
wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad);
@@ -166,11 +158,11 @@ static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb,
len = WL1271_TX_ALIGN(skb->len);
/* perform a fixed address block write with the packet */
- wl1271_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true);
+ wl1271_spi_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true);
/* write packet new counter into the write access register */
wl->tx_packets_count++;
- wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
+ wl1271_spi_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
desc = (struct wl1271_tx_hw_descr *) skb->data;
wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)",
@@ -204,7 +196,6 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb)
ret = wl1271_cmd_set_default_wep_key(wl, idx);
if (ret < 0)
return ret;
- wl->default_key = idx;
}
}
@@ -223,50 +214,18 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb)
return ret;
}
-static u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
-{
- struct ieee80211_supported_band *band;
- u32 enabled_rates = 0;
- int bit;
-
- band = wl->hw->wiphy->bands[wl->band];
- for (bit = 0; bit < band->n_bitrates; bit++) {
- if (rate_set & 0x1)
- enabled_rates |= band->bitrates[bit].hw_value;
- rate_set >>= 1;
- }
-
- return enabled_rates;
-}
-
void wl1271_tx_work(struct work_struct *work)
{
struct wl1271 *wl = container_of(work, struct wl1271, tx_work);
struct sk_buff *skb;
bool woken_up = false;
- u32 sta_rates = 0;
int ret;
- /* check if the rates supported by the AP have changed */
- if (unlikely(test_and_clear_bit(WL1271_FLAG_STA_RATES_CHANGED,
- &wl->flags))) {
- unsigned long flags;
- spin_lock_irqsave(&wl->wl_lock, flags);
- sta_rates = wl->sta_rate_set;
- spin_unlock_irqrestore(&wl->wl_lock, flags);
- }
-
mutex_lock(&wl->mutex);
if (unlikely(wl->state == WL1271_STATE_OFF))
goto out;
- /* if rates have changed, re-configure the rate policy */
- if (unlikely(sta_rates)) {
- wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates);
- wl1271_acx_rate_policies(wl);
- }
-
while ((skb = skb_dequeue(&wl->tx_queue))) {
if (!woken_up) {
ret = wl1271_ps_elp_wakeup(wl, false);
@@ -281,18 +240,18 @@ void wl1271_tx_work(struct work_struct *work)
wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, "
"stop queues");
ieee80211_stop_queues(wl->hw);
- set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
+ wl->tx_queue_stopped = true;
skb_queue_head(&wl->tx_queue, skb);
goto out;
} else if (ret < 0) {
dev_kfree_skb(skb);
goto out;
- } else if (test_and_clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED,
- &wl->flags)) {
+ } else if (wl->tx_queue_stopped) {
/* firmware buffer has space, restart queues */
wl1271_debug(DEBUG_TX,
"complete_packet: waking queues");
ieee80211_wake_queues(wl->hw);
+ wl->tx_queue_stopped = false;
}
}
@@ -376,8 +335,8 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count)
wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count);
/* read the tx results from the chipset */
- wl1271_read(wl, le32_to_cpu(memmap->tx_result),
- wl->tx_res_if, sizeof(*wl->tx_res_if), false);
+ wl1271_spi_read(wl, le32_to_cpu(memmap->tx_result),
+ wl->tx_res_if, sizeof(*wl->tx_res_if), false);
/* verify that the result buffer is not getting overrun */
if (count > TX_HW_RESULT_QUEUE_LEN) {
@@ -398,10 +357,10 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count)
}
/* write host counter to chipset (to ack) */
- wl1271_write32(wl, le32_to_cpu(memmap->tx_result) +
- offsetof(struct wl1271_tx_hw_res_if,
- tx_result_host_counter),
- le32_to_cpu(wl->tx_res_if->tx_result_fw_counter));
+ wl1271_spi_write32(wl, le32_to_cpu(memmap->tx_result) +
+ offsetof(struct wl1271_tx_hw_res_if,
+ tx_result_host_counter),
+ le32_to_cpu(wl->tx_res_if->tx_result_fw_counter));
}
/* caller must hold wl->mutex */
diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_tx.h b/trunk/drivers/net/wireless/wl12xx/wl1271_tx.h
index 17e405a09caa..416396caf0a0 100644
--- a/trunk/drivers/net/wireless/wl12xx/wl1271_tx.h
+++ b/trunk/drivers/net/wireless/wl12xx/wl1271_tx.h
@@ -123,42 +123,6 @@ struct wl1271_tx_hw_res_if {
struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN];
} __attribute__ ((packed));
-static inline int wl1271_tx_get_queue(int queue)
-{
- /* FIXME: use best effort until WMM is enabled */
- return CONF_TX_AC_BE;
-
- switch (queue) {
- case 0:
- return CONF_TX_AC_VO;
- case 1:
- return CONF_TX_AC_VI;
- case 2:
- return CONF_TX_AC_BE;
- case 3:
- return CONF_TX_AC_BK;
- default:
- return CONF_TX_AC_BE;
- }
-}
-
-/* wl1271 tx descriptor needs the tid and we need to convert it from ac */
-static inline int wl1271_tx_ac_to_tid(int ac)
-{
- switch (ac) {
- case 0:
- return 0;
- case 1:
- return 2;
- case 2:
- return 4;
- case 3:
- return 6;
- default:
- return 0;
- }
-}
-
void wl1271_tx_work(struct work_struct *work);
void wl1271_tx_complete(struct wl1271 *wl, u32 count);
void wl1271_tx_flush(struct wl1271 *wl);
diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_mac.c b/trunk/drivers/net/wireless/zd1211rw/zd_mac.c
index d90f0a25b9cf..9d9b263733e6 100644
--- a/trunk/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/trunk/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -869,7 +869,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
}
static int zd_op_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct zd_mac *mac = zd_hw_mac(hw);
@@ -877,22 +877,22 @@ static int zd_op_add_interface(struct ieee80211_hw *hw,
if (mac->type != NL80211_IFTYPE_UNSPECIFIED)
return -EOPNOTSUPP;
- switch (vif->type) {
+ switch (conf->type) {
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
- mac->type = vif->type;
+ mac->type = conf->type;
break;
default:
return -EOPNOTSUPP;
}
- return zd_write_mac_addr(&mac->chip, vif->addr);
+ return zd_write_mac_addr(&mac->chip, conf->mac_addr);
}
static void zd_op_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
struct zd_mac *mac = zd_hw_mac(hw);
mac->type = NL80211_IFTYPE_UNSPECIFIED;
diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c
index 442fc1117326..72d3e437e190 100644
--- a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -1079,15 +1079,11 @@ static int eject_installer(struct usb_interface *intf)
int r;
/* Find bulk out endpoint */
- for (r = 1; r >= 0; r--) {
- endpoint = &iface_desc->endpoint[r].desc;
- if (usb_endpoint_dir_out(endpoint) &&
- usb_endpoint_xfer_bulk(endpoint)) {
- bulk_out_ep = endpoint->bEndpointAddress;
- break;
- }
- }
- if (r == -1) {
+ endpoint = &iface_desc->endpoint[1].desc;
+ if (usb_endpoint_dir_out(endpoint) &&
+ usb_endpoint_xfer_bulk(endpoint)) {
+ bulk_out_ep = endpoint->bEndpointAddress;
+ } else {
dev_err(&udev->dev,
"zd1211rw: Could not find bulk out endpoint\n");
return -ENODEV;
diff --git a/trunk/drivers/ssb/driver_chipcommon_pmu.c b/trunk/drivers/ssb/driver_chipcommon_pmu.c
index 3d551245a4e2..64abd11f6fbb 100644
--- a/trunk/drivers/ssb/driver_chipcommon_pmu.c
+++ b/trunk/drivers/ssb/driver_chipcommon_pmu.c
@@ -332,12 +332,6 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc)
case 0x5354:
ssb_pmu0_pllinit_r0(cc, crystalfreq);
break;
- case 0x4322:
- if (cc->pmu.rev == 2) {
- chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, 0x0000000A);
- chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, 0x380005C0);
- }
- break;
default:
ssb_printk(KERN_ERR PFX
"ERROR: PLL init unknown for device %04X\n",
@@ -423,7 +417,6 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc)
switch (bus->chip_id) {
case 0x4312:
- case 0x4322:
/* We keep the default settings:
* min_msk = 0xCBB
* max_msk = 0x7FFFF
diff --git a/trunk/drivers/ssb/driver_mipscore.c b/trunk/drivers/ssb/driver_mipscore.c
index 97efce184a8f..3c6feed46f6e 100644
--- a/trunk/drivers/ssb/driver_mipscore.c
+++ b/trunk/drivers/ssb/driver_mipscore.c
@@ -270,6 +270,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
set_irq(dev, irq++);
}
break;
+ /* fallthrough */
case SSB_DEV_PCI:
case SSB_DEV_ETHERNET:
case SSB_DEV_ETHERNET_GBIT:
@@ -280,10 +281,6 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
set_irq(dev, irq++);
break;
}
- /* fallthrough */
- case SSB_DEV_EXTIF:
- set_irq(dev, 0);
- break;
}
}
ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n");
diff --git a/trunk/drivers/ssb/ssb_private.h b/trunk/drivers/ssb/ssb_private.h
index 0331139a726f..56054be4d113 100644
--- a/trunk/drivers/ssb/ssb_private.h
+++ b/trunk/drivers/ssb/ssb_private.h
@@ -196,7 +196,7 @@ extern int ssb_devices_thaw(struct ssb_freeze_context *ctx);
#ifdef CONFIG_SSB_B43_PCI_BRIDGE
extern int __init b43_pci_ssb_bridge_init(void);
extern void __exit b43_pci_ssb_bridge_exit(void);
-#else /* CONFIG_SSB_B43_PCI_BRIDGE */
+#else /* CONFIG_SSB_B43_PCI_BRIDGR */
static inline int b43_pci_ssb_bridge_init(void)
{
return 0;
@@ -204,6 +204,6 @@ static inline int b43_pci_ssb_bridge_init(void)
static inline void b43_pci_ssb_bridge_exit(void)
{
}
-#endif /* CONFIG_SSB_B43_PCI_BRIDGE */
+#endif /* CONFIG_SSB_PCIHOST */
#endif /* LINUX_SSB_PRIVATE_H_ */
diff --git a/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211.h
index 462578703d07..3222c22152fb 100644
--- a/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211.h
+++ b/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211.h
@@ -482,6 +482,15 @@ struct ieee80211_header_data {
u16 seq_ctrl;
};
+struct ieee80211_hdr_3addr {
+ u16 frame_ctl;
+ u16 duration_id;
+ u8 addr1[ETH_ALEN];
+ u8 addr2[ETH_ALEN];
+ u8 addr3[ETH_ALEN];
+ u16 seq_ctl;
+} __attribute__ ((packed));
+
struct ieee80211_hdr_4addr {
u16 frame_ctl;
u16 duration_id;
diff --git a/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
index cc9da3713526..334e4c7ec61b 100644
--- a/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
+++ b/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
@@ -203,7 +203,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee
enqueue_mgmt(ieee,skb);
}else{
- header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
+ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
if (ieee->seq_ctrl[0] == 0xFFF)
ieee->seq_ctrl[0] = 0;
@@ -220,7 +220,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee
spin_unlock_irqrestore(&ieee->lock, flags);
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
- header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
if (ieee->seq_ctrl[0] == 0xFFF)
ieee->seq_ctrl[0] = 0;
@@ -246,7 +246,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i
if(single){
- header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
if (ieee->seq_ctrl[0] == 0xFFF)
ieee->seq_ctrl[0] = 0;
@@ -259,7 +259,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i
}else{
- header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
if (ieee->seq_ctrl[0] == 0xFFF)
ieee->seq_ctrl[0] = 0;
@@ -287,7 +287,7 @@ inline struct sk_buff *ieee80211_disassociate_skb(
return NULL;
disass = (struct ieee80211_disassoc_frame *) skb_put(skb,sizeof(struct ieee80211_disassoc_frame));
- disass->header.frame_control = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
+ disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
disass->header.duration_id = 0;
memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
@@ -905,7 +905,7 @@ struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest)
assoc = (struct ieee80211_assoc_response_frame *)
skb_put(skb,sizeof(struct ieee80211_assoc_response_frame));
- assoc->header.frame_control = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
+ assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
memcpy(assoc->header.addr1, dest,ETH_ALEN);
memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
@@ -981,7 +981,7 @@ struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr)
memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
- hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
+ hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
(pwr ? IEEE80211_FCTL_PM:0));
@@ -1084,7 +1084,7 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco
skb_put(skb, sizeof(struct ieee80211_assoc_request_frame));
- hdr->header.frame_control = IEEE80211_STYPE_ASSOC_REQ;
+ hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
hdr->header.duration_id= 37; //FIXME
memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
@@ -1786,11 +1786,11 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
tasklet_schedule(&ieee->ps_task);
- if (WLAN_FC_GET_STYPE(header->frame_control) != IEEE80211_STYPE_PROBE_RESP &&
- WLAN_FC_GET_STYPE(header->frame_control) != IEEE80211_STYPE_BEACON)
+ if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
+ WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
ieee->last_rx_ps_time = jiffies;
- switch (WLAN_FC_GET_STYPE(header->frame_control)) {
+ switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
case IEEE80211_STYPE_ASSOC_RESP:
case IEEE80211_STYPE_REASSOC_RESP:
@@ -2064,7 +2064,7 @@ void ieee80211_wake_queue(struct ieee80211_device *ieee)
header = (struct ieee80211_hdr_3addr *) skb->data;
- header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
if (ieee->seq_ctrl[0] == 0xFFF)
ieee->seq_ctrl[0] = 0;
diff --git a/trunk/drivers/staging/rtl8187se/r8180_core.c b/trunk/drivers/staging/rtl8187se/r8180_core.c
index 7788bc42e9b4..53e654d0d4fa 100644
--- a/trunk/drivers/staging/rtl8187se/r8180_core.c
+++ b/trunk/drivers/staging/rtl8187se/r8180_core.c
@@ -1909,7 +1909,7 @@ rate)
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
int mode;
struct ieee80211_hdr_3addr *h = (struct ieee80211_hdr_3addr *) skb->data;
- short morefrag = (h->frame_control) & IEEE80211_FCTL_MOREFRAGS;
+ short morefrag = (h->frame_ctl) & IEEE80211_FCTL_MOREFRAGS;
unsigned long flags;
int priority;
@@ -2177,7 +2177,7 @@ short rtl8180_tx(struct net_device *dev, u8* txbuf, int len, int priority,
TxDescDuration = ThisFrameTime + aSifsTime + AckTime;
}
- if (!(frag_hdr->frame_control & IEEE80211_FCTL_MOREFRAGS)) {
+ if(!(frag_hdr->frame_ctl & IEEE80211_FCTL_MOREFRAGS)) { //no more fragment
// ThisFrame-ACK.
Duration = aSifsTime + AckTime;
} else { // One or more fragments remained.
diff --git a/trunk/drivers/staging/rtl8192su/ieee80211/ieee80211.h b/trunk/drivers/staging/rtl8192su/ieee80211/ieee80211.h
index 6963e5448f34..f22d024b1c39 100644
--- a/trunk/drivers/staging/rtl8192su/ieee80211/ieee80211.h
+++ b/trunk/drivers/staging/rtl8192su/ieee80211/ieee80211.h
@@ -609,6 +609,16 @@ struct ieee80211_hdr_2addr {
u8 payload[0];
} __attribute__ ((packed));
+struct ieee80211_hdr_3addr {
+ __le16 frame_ctl;
+ __le16 duration_id;
+ u8 addr1[ETH_ALEN];
+ u8 addr2[ETH_ALEN];
+ u8 addr3[ETH_ALEN];
+ __le16 seq_ctl;
+ u8 payload[0];
+} __attribute__ ((packed));
+
struct ieee80211_hdr_4addr {
__le16 frame_ctl;
__le16 duration_id;
@@ -1662,7 +1672,7 @@ static inline u8 *ieee80211_get_payload(struct rtl_ieee80211_hdr *hdr)
case IEEE80211_2ADDR_LEN:
return ((struct ieee80211_hdr_2addr *)hdr)->payload;
case IEEE80211_3ADDR_LEN:
- return (void *)hdr+sizeof(struct ieee80211_hdr_3addr);
+ return ((struct ieee80211_hdr_3addr *)hdr)->payload;
case IEEE80211_4ADDR_LEN:
return ((struct ieee80211_hdr_4addr *)hdr)->payload;
}
diff --git a/trunk/drivers/staging/rtl8192su/ieee80211/ieee80211_r8192s.h b/trunk/drivers/staging/rtl8192su/ieee80211/ieee80211_r8192s.h
index 7d6c3bc143ae..123abcf0f497 100644
--- a/trunk/drivers/staging/rtl8192su/ieee80211/ieee80211_r8192s.h
+++ b/trunk/drivers/staging/rtl8192su/ieee80211/ieee80211_r8192s.h
@@ -201,7 +201,7 @@ typedef union _frameqos {
static inline u8 Frame_QoSTID(u8 *buf)
{
struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)buf;
- u16 fc = le16_to_cpu(hdr->frame_control);
+ u16 fc = le16_to_cpu(hdr->frame_ctl);
return (u8)((frameqos *)(buf +
(((fc & IEEE80211_FCTL_TODS) &&
diff --git a/trunk/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c b/trunk/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c
index 72498e8e0ded..8e56f97a8f57 100644
--- a/trunk/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c
+++ b/trunk/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c
@@ -745,7 +745,7 @@ u8 parse_subframe(struct sk_buff *skb,
struct ieee80211_rxb *rxb,u8* src,u8* dst)
{
struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr* )skb->data;
- u16 fc = le16_to_cpu(hdr->frame_control);
+ u16 fc = le16_to_cpu(hdr->frame_ctl);
u16 LLCOffset= sizeof(struct ieee80211_hdr_3addr);
u16 ChkLength;
@@ -757,7 +757,7 @@ u8 parse_subframe(struct sk_buff *skb,
struct sk_buff *sub_skb;
u8 *data_ptr;
/* just for debug purpose */
- SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctrl));
+ SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctl));
if((IEEE80211_QOS_HAS_SEQ(fc))&&\
(((frameqos *)(skb->data + IEEE80211_3ADDR_LEN))->field.reserved)) {
@@ -2371,7 +2371,7 @@ static inline void ieee80211_process_probe_response(
escape_essid(info_element->data,
info_element->len),
MAC_ARG(beacon->header.addr3),
- WLAN_FC_GET_STYPE(beacon->header.frame_control) ==
+ WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
IEEE80211_STYPE_PROBE_RESP ?
"PROBE RESPONSE" : "BEACON");
return;
@@ -2388,7 +2388,7 @@ static inline void ieee80211_process_probe_response(
return;
if(ieee->bGlobalDomain)
{
- if (WLAN_FC_GET_STYPE(beacon->header.frame_control) == IEEE80211_STYPE_PROBE_RESP)
+ if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP)
{
// Case 1: Country code
if(IS_COUNTRY_IE_VALID(ieee) )
@@ -2455,7 +2455,7 @@ static inline void ieee80211_process_probe_response(
else
ieee->current_network.buseprotection = false;
}
- if(is_beacon(beacon->header.frame_control))
+ if(is_beacon(beacon->header.frame_ctl))
{
if(ieee->state == IEEE80211_LINKED)
ieee->LinkDetectInfo.NumRecvBcnInPeriod++;
@@ -2497,7 +2497,7 @@ static inline void ieee80211_process_probe_response(
escape_essid(network.ssid,
network.ssid_len),
MAC_ARG(network.bssid),
- WLAN_FC_GET_STYPE(beacon->header.frame_control) ==
+ WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
IEEE80211_STYPE_PROBE_RESP ?
"PROBE RESPONSE" : "BEACON");
#endif
@@ -2510,7 +2510,7 @@ static inline void ieee80211_process_probe_response(
escape_essid(target->ssid,
target->ssid_len),
MAC_ARG(target->bssid),
- WLAN_FC_GET_STYPE(beacon->header.frame_control) ==
+ WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
IEEE80211_STYPE_PROBE_RESP ?
"PROBE RESPONSE" : "BEACON");
@@ -2520,7 +2520,7 @@ static inline void ieee80211_process_probe_response(
*/
renew = !time_after(target->last_scanned + ieee->scan_age, jiffies);
//YJ,add,080819,for hidden ap
- if(is_beacon(beacon->header.frame_control) == 0)
+ if(is_beacon(beacon->header.frame_ctl) == 0)
network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags);
//if(strncmp(network.ssid, "linksys-c",9) == 0)
// printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags);
@@ -2536,7 +2536,7 @@ static inline void ieee80211_process_probe_response(
}
spin_unlock_irqrestore(&ieee->lock, flags);
- if (is_beacon(beacon->header.frame_control)&&is_same_network(&ieee->current_network, &network, ieee)&&\
+ if (is_beacon(beacon->header.frame_ctl)&&is_same_network(&ieee->current_network, &network, ieee)&&\
(ieee->state == IEEE80211_LINKED)) {
if(ieee->handle_beacon != NULL) {
ieee->handle_beacon(ieee->dev,beacon,&ieee->current_network);
diff --git a/trunk/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c b/trunk/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c
index 8da0c4c83673..fd8e11252f1b 100644
--- a/trunk/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c
+++ b/trunk/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c
@@ -242,7 +242,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee
if(ieee->queue_stop){
enqueue_mgmt(ieee,skb);
}else{
- header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
+ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
if (ieee->seq_ctrl[0] == 0xFFF)
ieee->seq_ctrl[0] = 0;
@@ -260,7 +260,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee
spin_unlock_irqrestore(&ieee->lock, flags);
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
- header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
if (ieee->seq_ctrl[0] == 0xFFF)
ieee->seq_ctrl[0] = 0;
@@ -302,7 +302,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i
//printk("=============>%s()\n", __FUNCTION__);
if(single){
- header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
if (ieee->seq_ctrl[0] == 0xFFF)
ieee->seq_ctrl[0] = 0;
@@ -315,7 +315,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i
}else{
- header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
if (ieee->seq_ctrl[0] == 0xFFF)
ieee->seq_ctrl[0] = 0;
@@ -347,7 +347,7 @@ inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
skb_reserve(skb, ieee->tx_headroom);
req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request));
- req->header.frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
+ req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
req->header.duration_id = 0; //FIXME: is this OK ?
memset(req->header.addr1, 0xff, ETH_ALEN);
@@ -662,8 +662,8 @@ inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *be
auth = (struct ieee80211_authentication *)
skb_put(skb, sizeof(struct ieee80211_authentication));
- auth->header.frame_control = IEEE80211_STYPE_AUTH;
- if (challengelen) auth->header.frame_control |= IEEE80211_FCTL_WEP;
+ auth->header.frame_ctl = IEEE80211_STYPE_AUTH;
+ if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP;
auth->header.duration_id = 0x013a; //FIXME
@@ -801,7 +801,7 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
- beacon_buf->header.frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
+ beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
beacon_buf->info_element[0].len = ssid_len;
@@ -880,7 +880,7 @@ struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest)
assoc = (struct ieee80211_assoc_response_frame *)
skb_put(skb,sizeof(struct ieee80211_assoc_response_frame));
- assoc->header.frame_control = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
+ assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
memcpy(assoc->header.addr1, dest,ETH_ALEN);
memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
@@ -935,7 +935,7 @@ struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8
memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
memcpy(auth->header.addr1, dest, ETH_ALEN);
- auth->header.frame_control = cpu_to_le16(IEEE80211_STYPE_AUTH);
+ auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
return skb;
@@ -957,7 +957,7 @@ struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr)
memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
- hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
+ hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
(pwr ? IEEE80211_FCTL_PM:0));
@@ -1083,7 +1083,7 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco
skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2);
- hdr->header.frame_control = IEEE80211_STYPE_ASSOC_REQ;
+ hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
hdr->header.duration_id= 37; //FIXME
memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
@@ -1940,13 +1940,13 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
if(!ieee->proto_started)
return 0;
- switch (WLAN_FC_GET_STYPE(header->frame_control)) {
+ switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
case IEEE80211_STYPE_ASSOC_RESP:
case IEEE80211_STYPE_REASSOC_RESP:
IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
- WLAN_FC_GET_STYPE(header->frame_control));
+ WLAN_FC_GET_STYPE(header->frame_ctl));
if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
ieee->iw_mode == IW_MODE_INFRA){
@@ -2088,7 +2088,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
ieee->state == IEEE80211_LINKED &&
ieee->iw_mode == IW_MODE_INFRA){
- printk("==========>received disassoc/deauth(%x) frame, reason code:%x\n",WLAN_FC_GET_STYPE(header->frame_control), ((struct ieee80211_disassoc*)skb->data)->reason);
+ printk("==========>received disassoc/deauth(%x) frame, reason code:%x\n",WLAN_FC_GET_STYPE(header->frame_ctl), ((struct ieee80211_disassoc*)skb->data)->reason);
ieee->state = IEEE80211_ASSOCIATING;
ieee->softmac_stats.reassoc++;
ieee->is_roaming = true;
@@ -2239,7 +2239,7 @@ void ieee80211_wake_queue(struct ieee80211_device *ieee)
header = (struct ieee80211_hdr_3addr *) skb->data;
- header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
if (ieee->seq_ctrl[0] == 0xFFF)
ieee->seq_ctrl[0] = 0;
@@ -2574,7 +2574,7 @@ struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
return NULL;
b = (struct ieee80211_probe_response *) skb->data;
- b->header.frame_control = cpu_to_le16(IEEE80211_STYPE_BEACON);
+ b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
return skb;
@@ -2590,7 +2590,7 @@ struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
return NULL;
b = (struct ieee80211_probe_response *) skb->data;
- b->header.seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+ b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
if (ieee->seq_ctrl[0] == 0xFFF)
ieee->seq_ctrl[0] = 0;
@@ -3139,7 +3139,7 @@ inline struct sk_buff *ieee80211_disassociate_skb(
return NULL;
disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
- disass->header.frame_control = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
+ disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
disass->header.duration_id = 0;
memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
diff --git a/trunk/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c b/trunk/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c
index c6962450e06f..8d12ffca18fa 100644
--- a/trunk/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c
+++ b/trunk/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c
@@ -136,7 +136,7 @@ static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, P
memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
- BAReq->frame_control = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
+ BAReq->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
//tag += sizeof( struct ieee80211_hdr_3addr); //move to action field
tag = (u8*)skb_put(skb, 9);
@@ -221,7 +221,7 @@ static struct sk_buff* ieee80211_DELBA(
memcpy(Delba->addr1, dst, ETH_ALEN);
memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
- Delba->frame_control = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
+ Delba->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
tag = (u8*)skb_put(skb, 6);
diff --git a/trunk/drivers/staging/rtl8192su/r8192U_core.c b/trunk/drivers/staging/rtl8192su/r8192U_core.c
index 2b079fb67d31..66274d7666ff 100644
--- a/trunk/drivers/staging/rtl8192su/r8192U_core.c
+++ b/trunk/drivers/staging/rtl8192su/r8192U_core.c
@@ -6166,7 +6166,7 @@ void rtl8192_process_phyinfo(struct r8192_priv * priv,u8* buffer, struct ieee802
u16 sc ;
unsigned int frag,seq;
hdr = (struct ieee80211_hdr_3addr *)buffer;
- sc = le16_to_cpu(hdr->seq_ctrl);
+ sc = le16_to_cpu(hdr->seq_ctl);
frag = WLAN_GET_SEQ_FRAG(sc);
seq = WLAN_GET_SEQ_SEQ(sc);
//cosa add 04292008 to record the sequence number
@@ -6825,7 +6825,7 @@ void rtl8192SU_TranslateRxSignalStuff(struct sk_buff *skb,
tmp_buf = (u8*)skb->data;// + get_rxpacket_shiftbytes_819xusb(pstats);
hdr = (struct ieee80211_hdr_3addr *)tmp_buf;
- fc = le16_to_cpu(hdr->frame_control);
+ fc = le16_to_cpu(hdr->frame_ctl);
type = WLAN_FC_GET_TYPE(fc);
praddr = hdr->addr1;
diff --git a/trunk/include/linux/ieee80211.h b/trunk/include/linux/ieee80211.h
index 19984958ab7b..163c840437d6 100644
--- a/trunk/include/linux/ieee80211.h
+++ b/trunk/include/linux/ieee80211.h
@@ -120,26 +120,6 @@
#define IEEE80211_QOS_CTL_TID_MASK 0x000F
#define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007
-/* U-APSD queue for WMM IEs sent by AP */
-#define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7)
-
-/* U-APSD queues for WMM IEs sent by STA */
-#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VO (1<<0)
-#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VI (1<<1)
-#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BK (1<<2)
-#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BE (1<<3)
-#define IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK 0x0f
-
-/* U-APSD max SP length for WMM IEs sent by STA */
-#define IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL 0x00
-#define IEEE80211_WMM_IE_STA_QOSINFO_SP_2 0x01
-#define IEEE80211_WMM_IE_STA_QOSINFO_SP_4 0x02
-#define IEEE80211_WMM_IE_STA_QOSINFO_SP_6 0x03
-#define IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK 0x03
-#define IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT 5
-
-#define IEEE80211_HT_CTL_LEN 4
-
struct ieee80211_hdr {
__le16 frame_control;
__le16 duration_id;
@@ -150,25 +130,6 @@ struct ieee80211_hdr {
u8 addr4[6];
} __attribute__ ((packed));
-struct ieee80211_hdr_3addr {
- __le16 frame_control;
- __le16 duration_id;
- u8 addr1[6];
- u8 addr2[6];
- u8 addr3[6];
- __le16 seq_ctrl;
-} __attribute__ ((packed));
-
-struct ieee80211_qos_hdr {
- __le16 frame_control;
- __le16 duration_id;
- u8 addr1[6];
- u8 addr2[6];
- u8 addr3[6];
- __le16 seq_ctrl;
- __le16 qos_ctrl;
-} __attribute__ ((packed));
-
/**
* ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set
* @fc: frame control bytes in little-endian byteorder
@@ -746,10 +707,6 @@ struct ieee80211_mgmt {
u8 action;
u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
} __attribute__ ((packed)) sa_query;
- struct {
- u8 action;
- u8 smps_control;
- } __attribute__ ((packed)) ht_smps;
} u;
} __attribute__ ((packed)) action;
} u;
@@ -814,10 +771,7 @@ struct ieee80211_bar {
/**
* struct ieee80211_mcs_info - MCS information
* @rx_mask: RX mask
- * @rx_highest: highest supported RX rate. If set represents
- * the highest supported RX data rate in units of 1 Mbps.
- * If this field is 0 this value should not be used to
- * consider the highest RX data rate supported.
+ * @rx_highest: highest supported RX rate
* @tx_params: TX parameters
*/
struct ieee80211_mcs_info {
@@ -870,7 +824,6 @@ struct ieee80211_ht_cap {
#define IEEE80211_HT_CAP_LDPC_CODING 0x0001
#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002
#define IEEE80211_HT_CAP_SM_PS 0x000C
-#define IEEE80211_HT_CAP_SM_PS_SHIFT 2
#define IEEE80211_HT_CAP_GRN_FLD 0x0010
#define IEEE80211_HT_CAP_SGI_20 0x0020
#define IEEE80211_HT_CAP_SGI_40 0x0040
@@ -886,7 +839,6 @@ struct ieee80211_ht_cap {
/* 802.11n HT capability AMPDU settings (for ampdu_params_info) */
#define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03
#define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C
-#define IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT 2
/*
* Maximum length of AMPDU that the STA can receive.
@@ -970,17 +922,12 @@ struct ieee80211_ht_info {
#define IEEE80211_MAX_AMPDU_BUF 0x40
-/* Spatial Multiplexing Power Save Modes (for capability) */
+/* Spatial Multiplexing Power Save Modes */
#define WLAN_HT_CAP_SM_PS_STATIC 0
#define WLAN_HT_CAP_SM_PS_DYNAMIC 1
#define WLAN_HT_CAP_SM_PS_INVALID 2
#define WLAN_HT_CAP_SM_PS_DISABLED 3
-/* for SM power control field lower two bits */
-#define WLAN_HT_SMPS_CONTROL_DISABLED 0
-#define WLAN_HT_SMPS_CONTROL_STATIC 1
-#define WLAN_HT_SMPS_CONTROL_DYNAMIC 3
-
/* Authentication algorithms */
#define WLAN_AUTH_OPEN 0
#define WLAN_AUTH_SHARED_KEY 1
@@ -1124,12 +1071,12 @@ enum ieee80211_eid {
WLAN_EID_TIM = 5,
WLAN_EID_IBSS_PARAMS = 6,
WLAN_EID_CHALLENGE = 16,
-
+ /* 802.11d */
WLAN_EID_COUNTRY = 7,
WLAN_EID_HP_PARAMS = 8,
WLAN_EID_HP_TABLE = 9,
WLAN_EID_REQUEST = 10,
-
+ /* 802.11e */
WLAN_EID_QBSS_LOAD = 11,
WLAN_EID_EDCA_PARAM_SET = 12,
WLAN_EID_TSPEC = 13,
@@ -1152,7 +1099,7 @@ enum ieee80211_eid {
WLAN_EID_PREP = 69,
WLAN_EID_PERR = 70,
WLAN_EID_RANN = 49, /* compatible with FreeBSD */
-
+ /* 802.11h */
WLAN_EID_PWR_CONSTRAINT = 32,
WLAN_EID_PWR_CAPABILITY = 33,
WLAN_EID_TPC_REQUEST = 34,
@@ -1163,41 +1110,20 @@ enum ieee80211_eid {
WLAN_EID_MEASURE_REPORT = 39,
WLAN_EID_QUIET = 40,
WLAN_EID_IBSS_DFS = 41,
-
+ /* 802.11g */
WLAN_EID_ERP_INFO = 42,
WLAN_EID_EXT_SUPP_RATES = 50,
-
+ /* 802.11n */
WLAN_EID_HT_CAPABILITY = 45,
WLAN_EID_HT_INFORMATION = 61,
-
+ /* 802.11i */
WLAN_EID_RSN = 48,
- WLAN_EID_MMIE = 76,
+ WLAN_EID_TIMEOUT_INTERVAL = 56,
+ WLAN_EID_MMIE = 76 /* 802.11w */,
WLAN_EID_WPA = 221,
WLAN_EID_GENERIC = 221,
WLAN_EID_VENDOR_SPECIFIC = 221,
- WLAN_EID_QOS_PARAMETER = 222,
-
- WLAN_EID_AP_CHAN_REPORT = 51,
- WLAN_EID_NEIGHBOR_REPORT = 52,
- WLAN_EID_RCPI = 53,
- WLAN_EID_BSS_AVG_ACCESS_DELAY = 63,
- WLAN_EID_ANTENNA_INFO = 64,
- WLAN_EID_RSNI = 65,
- WLAN_EID_MEASUREMENT_PILOT_TX_INFO = 66,
- WLAN_EID_BSS_AVAILABLE_CAPACITY = 67,
- WLAN_EID_BSS_AC_ACCESS_DELAY = 68,
- WLAN_EID_RRM_ENABLED_CAPABILITIES = 70,
- WLAN_EID_MULTIPLE_BSSID = 71,
-
- WLAN_EID_MOBILITY_DOMAIN = 54,
- WLAN_EID_FAST_BSS_TRANSITION = 55,
- WLAN_EID_TIMEOUT_INTERVAL = 56,
- WLAN_EID_RIC_DATA = 57,
- WLAN_EID_RIC_DESCRIPTOR = 75,
-
- WLAN_EID_DSE_REGISTERED_LOCATION = 58,
- WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59,
- WLAN_EID_EXT_CHANSWITCH_ANN = 60,
+ WLAN_EID_QOS_PARAMETER = 222
};
/* Action category code */
@@ -1224,18 +1150,6 @@ enum ieee80211_spectrum_mgmt_actioncode {
WLAN_ACTION_SPCT_CHL_SWITCH = 4,
};
-/* HT action codes */
-enum ieee80211_ht_actioncode {
- WLAN_HT_ACTION_NOTIFY_CHANWIDTH = 0,
- WLAN_HT_ACTION_SMPS = 1,
- WLAN_HT_ACTION_PSMP = 2,
- WLAN_HT_ACTION_PCO_PHASE = 3,
- WLAN_HT_ACTION_CSI = 4,
- WLAN_HT_ACTION_NONCOMPRESSED_BF = 5,
- WLAN_HT_ACTION_COMPRESSED_BF = 6,
- WLAN_HT_ACTION_ASEL_IDX_FEEDBACK = 7,
-};
-
/* Security key length */
enum ieee80211_key_len {
WLAN_KEY_LEN_WEP40 = 5,
diff --git a/trunk/include/linux/nl80211.h b/trunk/include/linux/nl80211.h
index 28ba20fda3e2..da8ea2e19273 100644
--- a/trunk/include/linux/nl80211.h
+++ b/trunk/include/linux/nl80211.h
@@ -3,7 +3,7 @@
/*
* 802.11 netlink interface public header
*
- * Copyright 2006-2010 Johannes Berg
+ * Copyright 2006, 2007, 2008 Johannes Berg
* Copyright 2008 Michael Wu
* Copyright 2008 Luis Carlos Cobo
* Copyright 2008 Michael Buesch
@@ -270,60 +270,6 @@
* @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices
* associated with this wiphy must be down and will follow.
*
- * @NL80211_CMD_REMAIN_ON_CHANNEL: Request to remain awake on the specified
- * channel for the specified amount of time. This can be used to do
- * off-channel operations like transmit a Public Action frame and wait for
- * a response while being associated to an AP on another channel.
- * %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify which
- * radio is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the
- * frequency for the operation and %NL80211_ATTR_WIPHY_CHANNEL_TYPE may be
- * optionally used to specify additional channel parameters.
- * %NL80211_ATTR_DURATION is used to specify the duration in milliseconds
- * to remain on the channel. This command is also used as an event to
- * notify when the requested duration starts (it may take a while for the
- * driver to schedule this time due to other concurrent needs for the
- * radio).
- * When called, this operation returns a cookie (%NL80211_ATTR_COOKIE)
- * that will be included with any events pertaining to this request;
- * the cookie is also used to cancel the request.
- * @NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: This command can be used to cancel a
- * pending remain-on-channel duration if the desired operation has been
- * completed prior to expiration of the originally requested duration.
- * %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify the
- * radio. The %NL80211_ATTR_COOKIE attribute must be given as well to
- * uniquely identify the request.
- * This command is also used as an event to notify when a requested
- * remain-on-channel duration has expired.
- *
- * @NL80211_CMD_SET_TX_BITRATE_MASK: Set the mask of rates to be used in TX
- * rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface
- * and @NL80211_ATTR_TX_RATES the set of allowed rates.
- *
- * @NL80211_CMD_REGISTER_ACTION: Register for receiving certain action frames
- * (via @NL80211_CMD_ACTION) for processing in userspace. This command
- * requires an interface index and a match attribute containing the first
- * few bytes of the frame that should match, e.g. a single byte for only
- * a category match or four bytes for vendor frames including the OUI.
- * The registration cannot be dropped, but is removed automatically
- * when the netlink socket is closed. Multiple registrations can be made.
- * @NL80211_CMD_ACTION: Action frame TX request and RX notification. This
- * command is used both as a request to transmit an Action frame and as an
- * event indicating reception of an Action frame that was not processed in
- * kernel code, but is for us (i.e., which may need to be processed in a
- * user space application). %NL80211_ATTR_FRAME is used to specify the
- * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ (and
- * optionally %NL80211_ATTR_WIPHY_CHANNEL_TYPE) is used to indicate on
- * which channel the frame is to be transmitted or was received. This
- * channel has to be the current channel (remain-on-channel or the
- * operational channel). When called, this operation returns a cookie
- * (%NL80211_ATTR_COOKIE) that will be included with the TX status event
- * pertaining to the TX request.
- * @NL80211_CMD_ACTION_TX_STATUS: Report TX status of an Action frame
- * transmitted with %NL80211_CMD_ACTION. %NL80211_ATTR_COOKIE identifies
- * the TX command and %NL80211_ATTR_FRAME includes the contents of the
- * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged
- * the frame.
- *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -407,18 +353,6 @@ enum nl80211_commands {
NL80211_CMD_DEL_PMKSA,
NL80211_CMD_FLUSH_PMKSA,
- NL80211_CMD_REMAIN_ON_CHANNEL,
- NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
-
- NL80211_CMD_SET_TX_BITRATE_MASK,
-
- NL80211_CMD_REGISTER_ACTION,
- NL80211_CMD_ACTION,
- NL80211_CMD_ACTION_TX_STATUS,
-
- NL80211_CMD_SET_POWER_SAVE,
- NL80211_CMD_GET_POWER_SAVE,
-
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -468,8 +402,6 @@ enum nl80211_commands {
* @NL80211_ATTR_WIPHY_RTS_THRESHOLD: RTS threshold (TX frames with length
* larger than or equal to this use RTS/CTS handshake); allowed range:
* 0..65536, disable with (u32)-1; dot11RTSThreshold; u32
- * @NL80211_ATTR_WIPHY_COVERAGE_CLASS: Coverage Class as defined by IEEE 802.11
- * section 7.3.2.9; dot11CoverageClass; u8
*
* @NL80211_ATTR_IFINDEX: network interface index of the device to operate on
* @NL80211_ATTR_IFNAME: network interface name
@@ -674,23 +606,6 @@ enum nl80211_commands {
* @NL80211_ATTR_MAX_NUM_PMKIDS: maximum number of PMKIDs a firmware can
* cache, a wiphy attribute.
*
- * @NL80211_ATTR_DURATION: Duration of an operation in milliseconds, u32.
- *
- * @NL80211_ATTR_COOKIE: Generic 64-bit cookie to identify objects.
- *
- * @NL80211_ATTR_TX_RATES: Nested set of attributes
- * (enum nl80211_tx_rate_attributes) describing TX rates per band. The
- * enum nl80211_band value is used as the index (nla_type() of the nested
- * data. If a band is not included, it will be configured to allow all
- * rates based on negotiated supported rates information. This attribute
- * is used with %NL80211_CMD_SET_TX_BITRATE_MASK.
- *
- * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain
- * at least one byte, currently used with @NL80211_CMD_REGISTER_ACTION.
- *
- * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was
- * acknowledged by the recipient.
- *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -828,20 +743,6 @@ enum nl80211_attrs {
NL80211_ATTR_PMKID,
NL80211_ATTR_MAX_NUM_PMKIDS,
- NL80211_ATTR_DURATION,
-
- NL80211_ATTR_COOKIE,
-
- NL80211_ATTR_WIPHY_COVERAGE_CLASS,
-
- NL80211_ATTR_TX_RATES,
-
- NL80211_ATTR_FRAME_MATCH,
-
- NL80211_ATTR_ACK,
-
- NL80211_ATTR_PS_STATE,
-
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -1422,20 +1323,13 @@ enum nl80211_channel_type {
* @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16)
* @NL80211_BSS_CAPABILITY: capability field (CPU order, u16)
* @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the
- * raw information elements from the probe response/beacon (bin);
- * if the %NL80211_BSS_BEACON_IES attribute is present, the IEs here are
- * from a Probe Response frame; otherwise they are from a Beacon frame.
- * However, if the driver does not indicate the source of the IEs, these
- * IEs may be from either frame subtype.
+ * raw information elements from the probe response/beacon (bin)
* @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon
* in mBm (100 * dBm) (s32)
* @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon
* in unspecified units, scaled to 0..100 (u8)
* @NL80211_BSS_STATUS: status, if this BSS is "used"
* @NL80211_BSS_SEEN_MS_AGO: age of this BSS entry in ms
- * @NL80211_BSS_BEACON_IES: binary attribute containing the raw information
- * elements from a Beacon frame (bin); not present if no Beacon frame has
- * yet been received
* @__NL80211_BSS_AFTER_LAST: internal
* @NL80211_BSS_MAX: highest BSS attribute
*/
@@ -1451,7 +1345,6 @@ enum nl80211_bss {
NL80211_BSS_SIGNAL_UNSPEC,
NL80211_BSS_STATUS,
NL80211_BSS_SEEN_MS_AGO,
- NL80211_BSS_BEACON_IES,
/* keep last */
__NL80211_BSS_AFTER_LAST,
@@ -1549,38 +1442,4 @@ enum nl80211_key_attributes {
NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1
};
-/**
- * enum nl80211_tx_rate_attributes - TX rate set attributes
- * @__NL80211_TXRATE_INVALID: invalid
- * @NL80211_TXRATE_LEGACY: Legacy (non-MCS) rates allowed for TX rate selection
- * in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with
- * 1 = 500 kbps) but without the IE length restriction (at most
- * %NL80211_MAX_SUPP_RATES in a single array).
- * @__NL80211_TXRATE_AFTER_LAST: internal
- * @NL80211_TXRATE_MAX: highest TX rate attribute
- */
-enum nl80211_tx_rate_attributes {
- __NL80211_TXRATE_INVALID,
- NL80211_TXRATE_LEGACY,
-
- /* keep last */
- __NL80211_TXRATE_AFTER_LAST,
- NL80211_TXRATE_MAX = __NL80211_TXRATE_AFTER_LAST - 1
-};
-
-/**
- * enum nl80211_band - Frequency band
- * @NL80211_BAND_2GHZ - 2.4 GHz ISM band
- * @NL80211_BAND_5GHZ - around 5 GHz band (4.9 - 5.7 GHz)
- */
-enum nl80211_band {
- NL80211_BAND_2GHZ,
- NL80211_BAND_5GHZ,
-};
-
-enum nl80211_ps_state {
- NL80211_PS_DISABLED,
- NL80211_PS_ENABLED,
-};
-
#endif /* __LINUX_NL80211_H */
diff --git a/trunk/include/net/cfg80211.h b/trunk/include/net/cfg80211.h
index 3d134a1fb96b..0884b9a0f778 100644
--- a/trunk/include/net/cfg80211.h
+++ b/trunk/include/net/cfg80211.h
@@ -3,7 +3,7 @@
/*
* 802.11 device and configuration interface
*
- * Copyright 2006-2010 Johannes Berg
+ * Copyright 2006-2009 Johannes Berg
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -39,8 +39,8 @@
* @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7)
*/
enum ieee80211_band {
- IEEE80211_BAND_2GHZ = NL80211_BAND_2GHZ,
- IEEE80211_BAND_5GHZ = NL80211_BAND_5GHZ,
+ IEEE80211_BAND_2GHZ,
+ IEEE80211_BAND_5GHZ,
/* keep last */
IEEE80211_NUM_BANDS
@@ -626,14 +626,8 @@ enum cfg80211_signal_type {
* @beacon_interval: the beacon interval as from the frame
* @capability: the capability field in host byte order
* @information_elements: the information elements (Note that there
- * is no guarantee that these are well-formed!); this is a pointer to
- * either the beacon_ies or proberesp_ies depending on whether Probe
- * Response frame has been received
+ * is no guarantee that these are well-formed!)
* @len_information_elements: total length of the information elements
- * @beacon_ies: the information elements from the last Beacon frame
- * @len_beacon_ies: total length of the beacon_ies
- * @proberesp_ies: the information elements from the last Probe Response frame
- * @len_proberesp_ies: total length of the proberesp_ies
* @signal: signal strength value (type depends on the wiphy's signal_type)
* @free_priv: function pointer to free private data
* @priv: private area for driver use, has at least wiphy->bss_priv_size bytes
@@ -647,10 +641,6 @@ struct cfg80211_bss {
u16 capability;
u8 *information_elements;
size_t len_information_elements;
- u8 *beacon_ies;
- size_t len_beacon_ies;
- u8 *proberesp_ies;
- size_t len_proberesp_ies;
s32 signal;
@@ -847,7 +837,6 @@ enum wiphy_params_flags {
WIPHY_PARAM_RETRY_LONG = 1 << 1,
WIPHY_PARAM_FRAG_THRESHOLD = 1 << 2,
WIPHY_PARAM_RTS_THRESHOLD = 1 << 3,
- WIPHY_PARAM_COVERAGE_CLASS = 1 << 4,
};
/**
@@ -867,11 +856,20 @@ enum tx_power_setting {
* cfg80211_bitrate_mask - masks for bitrate control
*/
struct cfg80211_bitrate_mask {
+/*
+ * As discussed in Berlin, this struct really
+ * should look like this:
+
struct {
u32 legacy;
- /* TODO: add support for masking MCS rates; e.g.: */
- /* u8 mcs[IEEE80211_HT_MCS_MASK_LEN]; */
+ u8 mcs[IEEE80211_HT_MCS_MASK_LEN];
} control[IEEE80211_NUM_BANDS];
+
+ * Since we can always fix in-kernel users, let's keep
+ * it simpler for now:
+ */
+ u32 fixed; /* fixed bitrate, 0 == not fixed */
+ u32 maxrate; /* in kbps, 0 == no limit */
};
/**
* struct cfg80211_pmksa - PMK Security Association
@@ -990,16 +988,6 @@ struct cfg80211_pmksa {
*
* @dump_survey: get site survey information.
*
- * @remain_on_channel: Request the driver to remain awake on the specified
- * channel for the specified duration to complete an off-channel
- * operation (e.g., public action frame exchange). When the driver is
- * ready on the requested channel, it must indicate this with an event
- * notification by calling cfg80211_ready_on_channel().
- * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation.
- * This allows the operation to be terminated prior to timeout based on
- * the duration value.
- * @action: Transmit an action frame
- *
* @testmode_cmd: run a test mode command
*
* @set_pmksa: Cache a PMKID for a BSSID. This is mostly useful for fullmac
@@ -1135,21 +1123,7 @@ struct cfg80211_ops {
struct cfg80211_pmksa *pmksa);
int (*flush_pmksa)(struct wiphy *wiphy, struct net_device *netdev);
- int (*remain_on_channel)(struct wiphy *wiphy,
- struct net_device *dev,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- unsigned int duration,
- u64 *cookie);
- int (*cancel_remain_on_channel)(struct wiphy *wiphy,
- struct net_device *dev,
- u64 cookie);
-
- int (*action)(struct wiphy *wiphy, struct net_device *dev,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- const u8 *buf, size_t len, u64 *cookie);
-
+ /* some temporary stuff to finish wext */
int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,
bool enabled, int timeout);
};
@@ -1200,10 +1174,6 @@ enum wiphy_flags {
WIPHY_FLAG_4ADDR_STATION = BIT(6),
};
-struct mac_address {
- u8 addr[ETH_ALEN];
-};
-
/**
* struct wiphy - wireless hardware description
* @idx: the wiphy index assigned to this item
@@ -1222,28 +1192,12 @@ struct mac_address {
* -1 = fragmentation disabled, only odd values >= 256 used
* @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled
* @net: the network namespace this wiphy currently lives in
- * @perm_addr: permanent MAC address of this device
- * @addr_mask: If the device supports multiple MAC addresses by masking,
- * set this to a mask with variable bits set to 1, e.g. if the last
- * four bits are variable then set it to 00:...:00:0f. The actual
- * variable bits shall be determined by the interfaces added, with
- * interfaces not matching the mask being rejected to be brought up.
- * @n_addresses: number of addresses in @addresses.
- * @addresses: If the device has more than one address, set this pointer
- * to a list of addresses (6 bytes each). The first one will be used
- * by default for perm_addr. In this case, the mask should be set to
- * all-zeroes. In this case it is assumed that the device can handle
- * the same number of arbitrary MAC addresses.
*/
struct wiphy {
/* assign these fields before you register the wiphy */
- /* permanent MAC address(es) */
+ /* permanent MAC address */
u8 perm_addr[ETH_ALEN];
- u8 addr_mask[ETH_ALEN];
-
- u16 n_addresses;
- struct mac_address *addresses;
/* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */
u16 interface_modes;
@@ -1263,7 +1217,6 @@ struct wiphy {
u8 retry_long;
u32 frag_threshold;
u32 rts_threshold;
- u8 coverage_class;
char fw_version[ETHTOOL_BUSINFO_LEN];
u32 hw_version;
@@ -1450,8 +1403,6 @@ struct cfg80211_cached_keys;
* set by driver (if supported) on add_interface BEFORE registering the
* netdev and may otherwise be used by driver read-only, will be update
* by cfg80211 on change_interface
- * @action_registrations: list of registrations for action frames
- * @action_registrations_lock: lock for the list
*/
struct wireless_dev {
struct wiphy *wiphy;
@@ -1461,9 +1412,6 @@ struct wireless_dev {
struct list_head list;
struct net_device *netdev;
- struct list_head action_registrations;
- spinlock_t action_registrations_lock;
-
struct mutex mtx;
struct work_struct cleanup_work;
@@ -1488,9 +1436,6 @@ struct wireless_dev {
struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES];
struct cfg80211_internal_bss *current_bss; /* associated / joined */
- bool ps;
- int ps_timeout;
-
#ifdef CONFIG_CFG80211_WEXT
/* wext data */
struct {
@@ -1502,7 +1447,8 @@ struct wireless_dev {
u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
u8 ssid[IEEE80211_MAX_SSID_LEN];
s8 default_key, default_mgmt_key;
- bool prev_bssid_valid;
+ bool ps, prev_bssid_valid;
+ int ps_timeout;
} wext;
#endif
};
@@ -1573,82 +1519,37 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
* Documentation in Documentation/networking/radiotap-headers.txt
*/
-struct radiotap_align_size {
- uint8_t align:4, size:4;
-};
-
-struct ieee80211_radiotap_namespace {
- const struct radiotap_align_size *align_size;
- int n_bits;
- uint32_t oui;
- uint8_t subns;
-};
-
-struct ieee80211_radiotap_vendor_namespaces {
- const struct ieee80211_radiotap_namespace *ns;
- int n_ns;
-};
-
/**
* struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args
- * @this_arg_index: index of current arg, valid after each successful call
- * to ieee80211_radiotap_iterator_next()
- * @this_arg: pointer to current radiotap arg; it is valid after each
- * call to ieee80211_radiotap_iterator_next() but also after
- * ieee80211_radiotap_iterator_init() where it will point to
- * the beginning of the actual data portion
- * @this_arg_size: length of the current arg, for convenience
- * @current_namespace: pointer to the current namespace definition
- * (or internally %NULL if the current namespace is unknown)
- * @is_radiotap_ns: indicates whether the current namespace is the default
- * radiotap namespace or not
- *
- * @overrides: override standard radiotap fields
- * @n_overrides: number of overrides
- *
- * @_rtheader: pointer to the radiotap header we are walking through
- * @_max_length: length of radiotap header in cpu byte ordering
- * @_arg_index: next argument index
- * @_arg: next argument pointer
- * @_next_bitmap: internal pointer to next present u32
- * @_bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present
- * @_vns: vendor namespace definitions
- * @_next_ns_data: beginning of the next namespace's data
- * @_reset_on_ext: internal; reset the arg index to 0 when going to the
- * next bitmap word
- *
- * Describes the radiotap parser state. Fields prefixed with an underscore
- * must not be used by users of the parser, only by the parser internally.
+ * @rtheader: pointer to the radiotap header we are walking through
+ * @max_length: length of radiotap header in cpu byte ordering
+ * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg
+ * @this_arg: pointer to current radiotap arg
+ * @arg_index: internal next argument index
+ * @arg: internal next argument pointer
+ * @next_bitmap: internal pointer to next present u32
+ * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present
*/
struct ieee80211_radiotap_iterator {
- struct ieee80211_radiotap_header *_rtheader;
- const struct ieee80211_radiotap_vendor_namespaces *_vns;
- const struct ieee80211_radiotap_namespace *current_namespace;
-
- unsigned char *_arg, *_next_ns_data;
- uint32_t *_next_bitmap;
-
- unsigned char *this_arg;
+ struct ieee80211_radiotap_header *rtheader;
+ int max_length;
int this_arg_index;
- int this_arg_size;
-
- int is_radiotap_ns;
+ u8 *this_arg;
- int _max_length;
- int _arg_index;
- uint32_t _bitmap_shifter;
- int _reset_on_ext;
+ int arg_index;
+ u8 *arg;
+ __le32 *next_bitmap;
+ u32 bitmap_shifter;
};
extern int ieee80211_radiotap_iterator_init(
- struct ieee80211_radiotap_iterator *iterator,
- struct ieee80211_radiotap_header *radiotap_header,
- int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns);
+ struct ieee80211_radiotap_iterator *iterator,
+ struct ieee80211_radiotap_header *radiotap_header,
+ int max_length);
extern int ieee80211_radiotap_iterator_next(
- struct ieee80211_radiotap_iterator *iterator);
-
+ struct ieee80211_radiotap_iterator *iterator);
extern const unsigned char rfc1042_header[6];
extern const unsigned char bridge_tunnel_header[6];
@@ -1677,7 +1578,7 @@ unsigned int ieee80211_hdrlen(__le16 fc);
* @addr: the device MAC address
* @iftype: the virtual interface type
*/
-int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
+int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr,
enum nl80211_iftype iftype);
/**
@@ -1688,49 +1589,15 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
* @bssid: the network bssid (used only for iftype STATION and ADHOC)
* @qos: build 802.11 QoS data frame
*/
-int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
+int ieee80211_data_from_8023(struct sk_buff *skb, u8 *addr,
enum nl80211_iftype iftype, u8 *bssid, bool qos);
-/**
- * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame
- *
- * Decode an IEEE 802.11n A-MSDU frame and convert it to a list of
- * 802.3 frames. The @list will be empty if the decode fails. The
- * @skb is consumed after the function returns.
- *
- * @skb: The input IEEE 802.11n A-MSDU frame.
- * @list: The output list of 802.3 frames. It must be allocated and
- * initialized by by the caller.
- * @addr: The device MAC address.
- * @iftype: The device interface type.
- * @extra_headroom: The hardware extra headroom for SKBs in the @list.
- */
-void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
- const u8 *addr, enum nl80211_iftype iftype,
- const unsigned int extra_headroom);
-
/**
* cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
* @skb: the data frame
*/
unsigned int cfg80211_classify8021d(struct sk_buff *skb);
-/**
- * cfg80211_find_ie - find information element in data
- *
- * @eid: element ID
- * @ies: data consisting of IEs
- * @len: length of data
- *
- * This function will return %NULL if the element ID could
- * not be found or if the element is invalid (claims to be
- * longer than the given data), or a pointer to the first byte
- * of the requested element, that is the byte containing the
- * element ID. There are no checks on the element length
- * other than having to fit into the given data.
- */
-const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len);
-
/*
* Regulatory helper functions for wiphys
*/
@@ -2262,79 +2129,5 @@ void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
void cfg80211_disconnected(struct net_device *dev, u16 reason,
u8 *ie, size_t ie_len, gfp_t gfp);
-/**
- * cfg80211_ready_on_channel - notification of remain_on_channel start
- * @dev: network device
- * @cookie: the request cookie
- * @chan: The current channel (from remain_on_channel request)
- * @channel_type: Channel type
- * @duration: Duration in milliseconds that the driver intents to remain on the
- * channel
- * @gfp: allocation flags
- */
-void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- unsigned int duration, gfp_t gfp);
-
-/**
- * cfg80211_remain_on_channel_expired - remain_on_channel duration expired
- * @dev: network device
- * @cookie: the request cookie
- * @chan: The current channel (from remain_on_channel request)
- * @channel_type: Channel type
- * @gfp: allocation flags
- */
-void cfg80211_remain_on_channel_expired(struct net_device *dev,
- u64 cookie,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- gfp_t gfp);
-
-
-/**
- * cfg80211_new_sta - notify userspace about station
- *
- * @dev: the netdev
- * @mac_addr: the station's address
- * @sinfo: the station information
- * @gfp: allocation flags
- */
-void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
- struct station_info *sinfo, gfp_t gfp);
-
-/**
- * cfg80211_rx_action - notification of received, unprocessed Action frame
- * @dev: network device
- * @freq: Frequency on which the frame was received in MHz
- * @buf: Action frame (header + body)
- * @len: length of the frame data
- * @gfp: context flags
- * Returns %true if a user space application is responsible for rejecting the
- * unrecognized Action frame; %false if no such application is registered
- * (i.e., the driver is responsible for rejecting the unrecognized Action
- * frame)
- *
- * This function is called whenever an Action frame is received for a station
- * mode interface, but is not processed in kernel.
- */
-bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf,
- size_t len, gfp_t gfp);
-
-/**
- * cfg80211_action_tx_status - notification of TX status for Action frame
- * @dev: network device
- * @cookie: Cookie returned by cfg80211_ops::action()
- * @buf: Action frame (header + body)
- * @len: length of the frame data
- * @ack: Whether frame was acknowledged
- * @gfp: context flags
- *
- * This function is called whenever an Action frame was requested to be
- * transmitted with cfg80211_ops::action() to report the TX status of the
- * transmission attempt.
- */
-void cfg80211_action_tx_status(struct net_device *dev, u64 cookie,
- const u8 *buf, size_t len, bool ack, gfp_t gfp);
#endif /* __NET_CFG80211_H */
diff --git a/trunk/include/net/ieee80211_radiotap.h b/trunk/include/net/ieee80211_radiotap.h
index af49f8ab7f81..9d3d86aaccbb 100644
--- a/trunk/include/net/ieee80211_radiotap.h
+++ b/trunk/include/net/ieee80211_radiotap.h
@@ -198,10 +198,6 @@ enum ieee80211_radiotap_type {
IEEE80211_RADIOTAP_TX_FLAGS = 15,
IEEE80211_RADIOTAP_RTS_RETRIES = 16,
IEEE80211_RADIOTAP_DATA_RETRIES = 17,
-
- /* valid in every it_present bitmap, even vendor namespaces */
- IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
- IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
IEEE80211_RADIOTAP_EXT = 31
};
diff --git a/trunk/include/net/mac80211.h b/trunk/include/net/mac80211.h
index 80eb7cc42ce9..0bf369752274 100644
--- a/trunk/include/net/mac80211.h
+++ b/trunk/include/net/mac80211.h
@@ -3,7 +3,7 @@
*
* Copyright 2002-2005, Devicescape Software, Inc.
* Copyright 2006-2007 Jiri Benc
- * Copyright 2007-2010 Johannes Berg
+ * Copyright 2007-2008 Johannes Berg
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -107,14 +107,25 @@ enum ieee80211_max_queues {
* 2^n-1 in the range 1..32767]
* @cw_max: maximum contention window [like @cw_min]
* @txop: maximum burst time in units of 32 usecs, 0 meaning disabled
- * @uapsd: is U-APSD mode enabled for the queue
*/
struct ieee80211_tx_queue_params {
u16 txop;
u16 cw_min;
u16 cw_max;
u8 aifs;
- bool uapsd;
+};
+
+/**
+ * struct ieee80211_tx_queue_stats - transmit queue statistics
+ *
+ * @len: number of packets in queue
+ * @limit: queue length limit
+ * @count: number of frames sent
+ */
+struct ieee80211_tx_queue_stats {
+ unsigned int len;
+ unsigned int limit;
+ unsigned int count;
};
struct ieee80211_low_level_stats {
@@ -173,8 +184,7 @@ enum ieee80211_bss_change {
* @use_short_slot: use short slot time (only relevant for ERP);
* if the hardware cannot handle this it must set the
* IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag
- * @dtim_period: num of beacons before the next DTIM, for beaconing,
- * not valid in station mode (cf. hw conf ps_dtim_period)
+ * @dtim_period: num of beacons before the next DTIM, for PSM
* @timestamp: beacon timestamp
* @beacon_int: beacon interval
* @assoc_capability: capabilities taken from assoc resp
@@ -245,6 +255,9 @@ struct ieee80211_bss_conf {
* @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be
* set by rate control algorithms to indicate probe rate, will
* be cleared for fragmented frames (except on the last fragment)
+ * @IEEE80211_TX_INTFL_RCALGO: mac80211 internal flag, do not test or
+ * set this flag in the driver; indicates that the rate control
+ * algorithm was used and should be notified of TX status
* @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211,
* used to indicate that a pending frame requires TX processing before
* it can be sent out.
@@ -259,14 +272,6 @@ struct ieee80211_bss_conf {
* transmit function after the current frame, this can be used
* by drivers to kick the DMA queue only if unset or when the
* queue gets full.
- * @IEEE80211_TX_INTFL_RETRANSMISSION: This frame is being retransmitted
- * after TX status because the destination was asleep, it must not
- * be modified again (no seqno assignment, crypto, etc.)
- * @IEEE80211_TX_INTFL_HAS_RADIOTAP: This frame was injected and still
- * has a radiotap header at skb->data.
- * @IEEE80211_TX_INTFL_NL80211_FRAME_TX: Frame was requested through nl80211
- * MLME command (internal to mac80211 to figure out whether to send TX
- * status to user space)
*/
enum mac80211_tx_control_flags {
IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0),
@@ -282,14 +287,12 @@ enum mac80211_tx_control_flags {
IEEE80211_TX_STAT_AMPDU = BIT(10),
IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11),
IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12),
+ IEEE80211_TX_INTFL_RCALGO = BIT(13),
IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14),
IEEE80211_TX_INTFL_RETRIED = BIT(15),
IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16),
IEEE80211_TX_CTL_PSPOLL_RESPONSE = BIT(17),
IEEE80211_TX_CTL_MORE_FRAMES = BIT(18),
- IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19),
- IEEE80211_TX_INTFL_HAS_RADIOTAP = BIT(20),
- IEEE80211_TX_INTFL_NL80211_FRAME_TX = BIT(21),
};
/**
@@ -568,13 +571,7 @@ struct ieee80211_rx_status {
* @IEEE80211_CONF_MONITOR: there's a monitor interface present -- use this
* to determine for example whether to calculate timestamps for packets
* or not, do not use instead of filter flags!
- * @IEEE80211_CONF_PS: Enable 802.11 power save mode (managed mode only).
- * This is the power save mode defined by IEEE 802.11-2007 section 11.2,
- * meaning that the hardware still wakes up for beacons, is able to
- * transmit frames and receive the possible acknowledgment frames.
- * Not to be confused with hardware specific wakeup/sleep states,
- * driver is responsible for that. See the section "Powersave support"
- * for more.
+ * @IEEE80211_CONF_PS: Enable 802.11 power save mode (managed mode only)
* @IEEE80211_CONF_IDLE: The device is running, but idle; if the flag is set
* the driver should be prepared to handle configuration requests but
* may turn the device off as much as possible. Typically, this flag will
@@ -598,10 +595,8 @@ enum ieee80211_conf_flags {
* @IEEE80211_CONF_CHANGE_CHANNEL: the channel/channel_type changed
* @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed
* @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed
- * @IEEE80211_CONF_CHANGE_SMPS: Spatial multiplexing powersave mode changed
*/
enum ieee80211_conf_changed {
- IEEE80211_CONF_CHANGE_SMPS = BIT(1),
IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2),
IEEE80211_CONF_CHANGE_MONITOR = BIT(3),
IEEE80211_CONF_CHANGE_PS = BIT(4),
@@ -611,25 +606,6 @@ enum ieee80211_conf_changed {
IEEE80211_CONF_CHANGE_IDLE = BIT(8),
};
-/**
- * enum ieee80211_smps_mode - spatial multiplexing power save mode
- *
- * @IEEE80211_SMPS_AUTOMATIC: automatic
- * @IEEE80211_SMPS_OFF: off
- * @IEEE80211_SMPS_STATIC: static
- * @IEEE80211_SMPS_DYNAMIC: dynamic
- * @IEEE80211_SMPS_NUM_MODES: internal, don't use
- */
-enum ieee80211_smps_mode {
- IEEE80211_SMPS_AUTOMATIC,
- IEEE80211_SMPS_OFF,
- IEEE80211_SMPS_STATIC,
- IEEE80211_SMPS_DYNAMIC,
-
- /* keep last */
- IEEE80211_SMPS_NUM_MODES,
-};
-
/**
* struct ieee80211_conf - configuration of the device
*
@@ -643,9 +619,6 @@ enum ieee80211_smps_mode {
* value will be only achievable between DTIM frames, the hardware
* needs to check for the multicast traffic bit in DTIM beacons.
* This variable is valid only when the CONF_PS flag is set.
- * @ps_dtim_period: The DTIM period of the AP we're connected to, for use
- * in power saving. Power saving will not be enabled until a beacon
- * has been received and the DTIM period is known.
* @dynamic_ps_timeout: The dynamic powersave timeout (in ms), see the
* powersave documentation below. This variable is valid only when
* the CONF_PS flag is set.
@@ -661,10 +634,6 @@ enum ieee80211_smps_mode {
* @short_frame_max_tx_count: Maximum number of transmissions for a "short"
* frame, called "dot11ShortRetryLimit" in 802.11, but actually means the
* number of transmissions not the number of retries
- *
- * @smps_mode: spatial multiplexing powersave mode; note that
- * %IEEE80211_SMPS_STATIC is used when the device is not
- * configured for an HT channel
*/
struct ieee80211_conf {
u32 flags;
@@ -672,13 +641,11 @@ struct ieee80211_conf {
int max_sleep_period;
u16 listen_interval;
- u8 ps_dtim_period;
u8 long_frame_max_tx_count, short_frame_max_tx_count;
struct ieee80211_channel *channel;
enum nl80211_channel_type channel_type;
- enum ieee80211_smps_mode smps_mode;
};
/**
@@ -690,14 +657,12 @@ struct ieee80211_conf {
* @type: type of this virtual interface
* @bss_conf: BSS configuration for this interface, either our own
* or the BSS we're associated to
- * @addr: address of this interface
* @drv_priv: data area for driver use, will always be aligned to
* sizeof(void *).
*/
struct ieee80211_vif {
enum nl80211_iftype type;
struct ieee80211_bss_conf bss_conf;
- u8 addr[ETH_ALEN];
/* must be last */
u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
};
@@ -710,6 +675,33 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
return false;
}
+/**
+ * struct ieee80211_if_init_conf - initial configuration of an interface
+ *
+ * @vif: pointer to a driver-use per-interface structure. The pointer
+ * itself is also used for various functions including
+ * ieee80211_beacon_get() and ieee80211_get_buffered_bc().
+ * @type: one of &enum nl80211_iftype constants. Determines the type of
+ * added/removed interface.
+ * @mac_addr: pointer to MAC address of the interface. This pointer is valid
+ * until the interface is removed (i.e. it cannot be used after
+ * remove_interface() callback was called for this interface).
+ *
+ * This structure is used in add_interface() and remove_interface()
+ * callbacks of &struct ieee80211_hw.
+ *
+ * When you allow multiple interfaces to be added to your PHY, take care
+ * that the hardware can actually handle multiple MAC addresses. However,
+ * also take care that when there's no interface left with mac_addr != %NULL
+ * you remove the MAC address from the device to avoid acknowledging packets
+ * in pure monitor mode.
+ */
+struct ieee80211_if_init_conf {
+ enum nl80211_iftype type;
+ struct ieee80211_vif *vif;
+ void *mac_addr;
+};
+
/**
* enum ieee80211_key_alg - key algorithm
* @ALG_WEP: WEP40 or WEP104
@@ -805,7 +797,7 @@ enum set_key_cmd {
* mac80211, any ieee80211_sta pointer you get access to must
* either be protected by rcu_read_lock() explicitly or implicitly,
* or you must take good care to not use such a pointer after a
- * call to your sta_remove callback that removed it.
+ * call to your sta_notify callback that removed it.
*
* @addr: MAC address
* @aid: AID we assigned to the station if we're an AP
@@ -831,8 +823,8 @@ struct ieee80211_sta {
* indicates addition and removal of a station to station table,
* or if a associated station made a power state transition.
*
- * @STA_NOTIFY_ADD: (DEPRECATED) a station was added to the station table
- * @STA_NOTIFY_REMOVE: (DEPRECATED) a station being removed from the station table
+ * @STA_NOTIFY_ADD: a station was added to the station table
+ * @STA_NOTIFY_REMOVE: a station being removed from the station table
* @STA_NOTIFY_SLEEP: a station is now sleeping
* @STA_NOTIFY_AWAKE: a sleeping station woke up
*/
@@ -934,26 +926,6 @@ enum ieee80211_tkip_key_type {
* @IEEE80211_HW_BEACON_FILTER:
* Hardware supports dropping of irrelevant beacon frames to
* avoid waking up cpu.
- *
- * @IEEE80211_HW_SUPPORTS_STATIC_SMPS:
- * Hardware supports static spatial multiplexing powersave,
- * ie. can turn off all but one chain even on HT connections
- * that should be using more chains.
- *
- * @IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS:
- * Hardware supports dynamic spatial multiplexing powersave,
- * ie. can turn off all but one chain and then wake the rest
- * up as required after, for example, rts/cts handshake.
- *
- * @IEEE80211_HW_SUPPORTS_UAPSD:
- * Hardware supports Unscheduled Automatic Power Save Delivery
- * (U-APSD) in managed mode. The mode is configured with
- * conf_tx() operation.
- *
- * @IEEE80211_HW_REPORTS_TX_ACK_STATUS:
- * Hardware can provide ack status reports of Tx frames to
- * the stack.
- *
*/
enum ieee80211_hw_flags {
IEEE80211_HW_HAS_RATE_CONTROL = 1<<0,
@@ -971,10 +943,6 @@ enum ieee80211_hw_flags {
IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<12,
IEEE80211_HW_MFP_CAPABLE = 1<<13,
IEEE80211_HW_BEACON_FILTER = 1<<14,
- IEEE80211_HW_SUPPORTS_STATIC_SMPS = 1<<15,
- IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS = 1<<16,
- IEEE80211_HW_SUPPORTS_UAPSD = 1<<17,
- IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18,
};
/**
@@ -1153,24 +1121,18 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
*
* mac80211 has support for various powersave implementations.
*
- * First, it can support hardware that handles all powersaving by itself,
- * such hardware should simply set the %IEEE80211_HW_SUPPORTS_PS hardware
- * flag. In that case, it will be told about the desired powersave mode
- * with the %IEEE80211_CONF_PS flag depending on the association status.
- * The hardware must take care of sending nullfunc frames when necessary,
- * i.e. when entering and leaving powersave mode. The hardware is required
- * to look at the AID in beacons and signal to the AP that it woke up when
- * it finds traffic directed to it.
- *
- * %IEEE80211_CONF_PS flag enabled means that the powersave mode defined in
- * IEEE 802.11-2007 section 11.2 is enabled. This is not to be confused
- * with hardware wakeup and sleep states. Driver is responsible for waking
- * up the hardware before issueing commands to the hardware and putting it
- * back to sleep at approriate times.
- *
- * When PS is enabled, hardware needs to wakeup for beacons and receive the
- * buffered multicast/broadcast frames after the beacon. Also it must be
- * possible to send frames and receive the acknowledment frame.
+ * First, it can support hardware that handles all powersaving by
+ * itself, such hardware should simply set the %IEEE80211_HW_SUPPORTS_PS
+ * hardware flag. In that case, it will be told about the desired
+ * powersave mode depending on the association status, and the driver
+ * must take care of sending nullfunc frames when necessary, i.e. when
+ * entering and leaving powersave mode. The driver is required to look at
+ * the AID in beacons and signal to the AP that it woke up when it finds
+ * traffic directed to it. This mode supports dynamic PS by simply
+ * enabling/disabling PS.
+ *
+ * Additionally, such hardware may set the %IEEE80211_HW_SUPPORTS_DYNAMIC_PS
+ * flag to indicate that it can support dynamic PS mode itself (see below).
*
* Other hardware designs cannot send nullfunc frames by themselves and also
* need software support for parsing the TIM bitmap. This is also supported
@@ -1178,35 +1140,14 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
* %IEEE80211_HW_PS_NULLFUNC_STACK flags. The hardware is of course still
* required to pass up beacons. The hardware is still required to handle
* waking up for multicast traffic; if it cannot the driver must handle that
- * as best as it can, mac80211 is too slow to do that.
- *
- * Dynamic powersave is an extension to normal powersave in which the
- * hardware stays awake for a user-specified period of time after sending a
- * frame so that reply frames need not be buffered and therefore delayed to
- * the next wakeup. It's compromise of getting good enough latency when
- * there's data traffic and still saving significantly power in idle
- * periods.
- *
- * Dynamic powersave is supported by simply mac80211 enabling and disabling
- * PS based on traffic. Driver needs to only set %IEEE80211_HW_SUPPORTS_PS
- * flag and mac80211 will handle everything automatically. Additionally,
- * hardware having support for the dynamic PS feature may set the
- * %IEEE80211_HW_SUPPORTS_DYNAMIC_PS flag to indicate that it can support
- * dynamic PS mode itself. The driver needs to look at the
- * @dynamic_ps_timeout hardware configuration value and use it that value
- * whenever %IEEE80211_CONF_PS is set. In this case mac80211 will disable
- * dynamic PS feature in stack and will just keep %IEEE80211_CONF_PS
- * enabled whenever user has enabled powersave.
- *
- * Driver informs U-APSD client support by enabling
- * %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the
- * uapsd paramater in conf_tx() operation. Hardware needs to send the QoS
- * Nullfunc frames and stay awake until the service period has ended. To
- * utilize U-APSD, dynamic powersave is disabled for voip AC and all frames
- * from that AC are transmitted with powersave enabled.
- *
- * Note: U-APSD client mode is not yet supported with
- * %IEEE80211_HW_PS_NULLFUNC_STACK.
+ * as best as it can, mac80211 is too slow.
+ *
+ * Dynamic powersave mode is an extension to normal powersave mode in which
+ * the hardware stays awake for a user-specified period of time after sending
+ * a frame so that reply frames need not be buffered and therefore delayed
+ * to the next wakeup. This can either be supported by hardware, in which case
+ * the driver needs to look at the @dynamic_ps_timeout hardware configuration
+ * value, or by the stack if all nullfunc handling is in the stack.
*/
/**
@@ -1269,31 +1210,6 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
* signal strength threshold checking.
*/
-/**
- * DOC: Spatial multiplexing power save
- *
- * SMPS (Spatial multiplexing power save) is a mechanism to conserve
- * power in an 802.11n implementation. For details on the mechanism
- * and rationale, please refer to 802.11 (as amended by 802.11n-2009)
- * "11.2.3 SM power save".
- *
- * The mac80211 implementation is capable of sending action frames
- * to update the AP about the station's SMPS mode, and will instruct
- * the driver to enter the specific mode. It will also announce the
- * requested SMPS mode during the association handshake. Hardware
- * support for this feature is required, and can be indicated by
- * hardware flags.
- *
- * The default mode will be "automatic", which nl80211/cfg80211
- * defines to be dynamic SMPS in (regular) powersave, and SMPS
- * turned off otherwise.
- *
- * To support this feature, the driver must set the appropriate
- * hardware support flags, and handle the SMPS flag to the config()
- * operation. It will then with this mechanism be instructed to
- * enter the requested SMPS mode while associated to an HT AP.
- */
-
/**
* DOC: Frame filtering
*
@@ -1431,7 +1347,7 @@ enum ieee80211_ampdu_mlme_action {
* When the device is started it should not have a MAC address
* to avoid acknowledging frames before a non-monitor device
* is added.
- * Must be implemented and can sleep.
+ * Must be implemented.
*
* @stop: Called after last netdevice attached to the hardware
* is disabled. This should turn off the hardware (at least
@@ -1439,7 +1355,7 @@ enum ieee80211_ampdu_mlme_action {
* May be called right after add_interface if that rejects
* an interface. If you added any work onto the mac80211 workqueue
* you should ensure to cancel it on this callback.
- * Must be implemented and can sleep.
+ * Must be implemented.
*
* @add_interface: Called when a netdevice attached to the hardware is
* enabled. Because it is not called for monitor mode devices, @start
@@ -1449,7 +1365,7 @@ enum ieee80211_ampdu_mlme_action {
* interface is given in the conf parameter.
* The callback may refuse to add an interface by returning a
* negative error code (which will be seen in userspace.)
- * Must be implemented and can sleep.
+ * Must be implemented.
*
* @remove_interface: Notifies a driver that an interface is going down.
* The @stop callback is called after this if it is the last interface
@@ -1458,20 +1374,19 @@ enum ieee80211_ampdu_mlme_action {
* must be cleared so the device no longer acknowledges packets,
* the mac_addr member of the conf structure is, however, set to the
* MAC address of the device going away.
- * Hence, this callback must be implemented. It can sleep.
+ * Hence, this callback must be implemented.
*
* @config: Handler for configuration requests. IEEE 802.11 code calls this
* function to change hardware configuration, e.g., channel.
* This function should never fail but returns a negative error code
- * if it does. The callback can sleep.
+ * if it does.
*
* @bss_info_changed: Handler for configuration requests related to BSS
* parameters that may vary during BSS's lifespan, and may affect low
* level driver (e.g. assoc/disassoc status, erp parameters).
* This function should not be used if no BSS has been set, unless
* for association indication. The @changed parameter indicates which
- * of the bss parameters has changed when a call is made. The callback
- * can sleep.
+ * 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
@@ -1479,22 +1394,20 @@ enum ieee80211_ampdu_mlme_action {
*
* @configure_filter: Configure the device's RX filter.
* See the section "Frame filtering" for more information.
- * This callback must be implemented and can sleep.
+ * This callback must be implemented.
*
* @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit
* must be set or cleared for a given STA. Must be atomic.
*
* @set_key: See the section "Hardware crypto acceleration"
- * This callback is only called between add_interface and
- * remove_interface calls, i.e. while the given virtual interface
+ * This callback can sleep, and is only called between add_interface
+ * and remove_interface calls, i.e. while the given virtual interface
* is enabled.
* Returns a negative error code if the key can't be added.
- * The callback can sleep.
*
* @update_tkip_key: See the section "Hardware crypto acceleration"
* This callback will be called in the context of Rx. Called for drivers
* which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY.
- * The callback must be atomic.
*
* @hw_scan: Ask the hardware to service the scan request, no need to start
* the scan state machine in stack. The scan must honour the channel
@@ -1508,64 +1421,53 @@ enum ieee80211_ampdu_mlme_action {
* When the scan finishes, ieee80211_scan_completed() must be called;
* note that it also must be called when the scan cannot finish due to
* any error unless this callback returned a negative error code.
- * The callback can sleep.
*
* @sw_scan_start: Notifier function that is called just before a software scan
* is started. Can be NULL, if the driver doesn't need this notification.
- * The callback can sleep.
*
- * @sw_scan_complete: Notifier function that is called just after a
- * software scan finished. Can be NULL, if the driver doesn't need
- * this notification.
- * The callback can sleep.
+ * @sw_scan_complete: Notifier function that is called just after a software scan
+ * finished. Can be NULL, if the driver doesn't need this notification.
*
* @get_stats: Return low-level statistics.
* Returns zero if statistics are available.
- * The callback can sleep.
*
* @get_tkip_seq: If your device implements TKIP encryption in hardware this
* callback should be provided to read the TKIP transmit IVs (both IV32
* and IV16) for the given key from hardware.
- * The callback must be atomic.
*
* @set_rts_threshold: Configuration of RTS threshold (if device needs it)
- * The callback can sleep.
- *
- * @sta_add: Notifies low level driver about addition of an associated station,
- * AP, IBSS/WDS/mesh peer etc. This callback can sleep.
- *
- * @sta_remove: Notifies low level driver about removal of an associated
- * station, AP, IBSS/WDS/mesh peer etc. This callback can sleep.
*
- * @sta_notify: Notifies low level driver about power state transition of an
- * associated station, AP, IBSS/WDS/mesh peer etc. Must be atomic.
+ * @sta_notify: Notifies low level driver about addition, removal or power
+ * state transition of an associated station, AP, IBSS/WDS/mesh peer etc.
+ * Must be atomic.
*
* @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
* bursting) for a hardware TX queue.
* Returns a negative error code on failure.
- * The callback can sleep.
+ *
+ * @get_tx_stats: Get statistics of the current TX queue status. This is used
+ * to get number of currently queued packets (queue length), maximum queue
+ * size (limit), and total number of packets sent using each TX queue
+ * (count). The 'stats' pointer points to an array that has hw->queues
+ * items.
*
* @get_tsf: Get the current TSF timer value from firmware/hardware. Currently,
* this is only used for IBSS mode BSSID merging and debugging. Is not a
* required function.
- * The callback can sleep.
*
* @set_tsf: Set the TSF timer to the specified value in the firmware/hardware.
* Currently, this is only used for IBSS mode debugging. Is not a
* required function.
- * The callback can sleep.
*
* @reset_tsf: Reset the TSF timer and allow firmware/hardware to synchronize
* with other STAs in the IBSS. This is only used in IBSS mode. This
* function is optional if the firmware/hardware takes full care of
* TSF synchronization.
- * The callback can sleep.
*
* @tx_last_beacon: Determine whether the last IBSS beacon was sent by us.
* This is needed only for IBSS mode and the result of this function is
* used to determine whether to reply to Probe Requests.
* Returns non-zero if this device sent the last beacon.
- * The callback can sleep.
*
* @ampdu_action: Perform a certain A-MPDU action
* The RA/TID combination determines the destination and TID we want
@@ -1574,32 +1476,21 @@ enum ieee80211_ampdu_mlme_action {
* is the first frame we expect to perform the action on. Notice
* that TX/RX_STOP can pass NULL for this parameter.
* Returns a negative error code on failure.
- * The callback must be atomic.
*
* @rfkill_poll: Poll rfkill hardware state. If you need this, you also
* need to set wiphy->rfkill_poll to %true before registration,
* and need to call wiphy_rfkill_set_hw_state() in the callback.
- * The callback can sleep.
- *
- * @set_coverage_class: Set slot time for given coverage class as specified
- * in IEEE 802.11-2007 section 17.3.8.6 and modify ACK timeout
- * accordingly. This callback is not required and may sleep.
*
* @testmode_cmd: Implement a cfg80211 test mode command.
- * The callback can sleep.
- *
- * @flush: Flush all pending frames from the hardware queue, making sure
- * that the hardware queues are empty. If the parameter @drop is set
- * to %true, pending frames may be dropped. The callback can sleep.
*/
struct ieee80211_ops {
int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
int (*start)(struct ieee80211_hw *hw);
void (*stop)(struct ieee80211_hw *hw);
int (*add_interface)(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
+ struct ieee80211_if_init_conf *conf);
void (*remove_interface)(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
+ struct ieee80211_if_init_conf *conf);
int (*config)(struct ieee80211_hw *hw, u32 changed);
void (*bss_info_changed)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -1617,10 +1508,8 @@ struct ieee80211_ops {
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key);
void (*update_tkip_key)(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_key_conf *conf,
- struct ieee80211_sta *sta,
- u32 iv32, u16 *phase1key);
+ struct ieee80211_key_conf *conf, const u8 *address,
+ u32 iv32, u16 *phase1key);
int (*hw_scan)(struct ieee80211_hw *hw,
struct cfg80211_scan_request *req);
void (*sw_scan_start)(struct ieee80211_hw *hw);
@@ -1630,14 +1519,12 @@ struct ieee80211_ops {
void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx,
u32 *iv32, u16 *iv16);
int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value);
- int (*sta_add)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
- int (*sta_remove)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum sta_notify_cmd, struct ieee80211_sta *sta);
int (*conf_tx)(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params);
+ int (*get_tx_stats)(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats);
u64 (*get_tsf)(struct ieee80211_hw *hw);
void (*set_tsf)(struct ieee80211_hw *hw, u64 tsf);
void (*reset_tsf)(struct ieee80211_hw *hw);
@@ -1648,11 +1535,9 @@ struct ieee80211_ops {
struct ieee80211_sta *sta, u16 tid, u16 *ssn);
void (*rfkill_poll)(struct ieee80211_hw *hw);
- void (*set_coverage_class)(struct ieee80211_hw *hw, u8 coverage_class);
#ifdef CONFIG_NL80211_TESTMODE
int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len);
#endif
- void (*flush)(struct ieee80211_hw *hw, bool drop);
};
/**
@@ -1892,7 +1777,7 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
/**
* ieee80211_beacon_get_tim - beacon generation function
* @hw: pointer obtained from ieee80211_alloc_hw().
- * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
* @tim_offset: pointer to variable that will receive the TIM IE offset.
* Set to 0 if invalid (in non-AP modes).
* @tim_length: pointer to variable that will receive the TIM IE length,
@@ -1920,7 +1805,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
/**
* ieee80211_beacon_get - beacon generation function
* @hw: pointer obtained from ieee80211_alloc_hw().
- * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
*
* See ieee80211_beacon_get_tim().
*/
@@ -1930,57 +1815,10 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
return ieee80211_beacon_get_tim(hw, vif, NULL, NULL);
}
-/**
- * ieee80211_pspoll_get - retrieve a PS Poll template
- * @hw: pointer obtained from ieee80211_alloc_hw().
- * @vif: &struct ieee80211_vif pointer from the add_interface callback.
- *
- * Creates a PS Poll a template which can, for example, uploaded to
- * hardware. The template must be updated after association so that correct
- * AID, BSSID and MAC address is used.
- *
- * Note: Caller (or hardware) is responsible for setting the
- * &IEEE80211_FCTL_PM bit.
- */
-struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
-
-/**
- * ieee80211_nullfunc_get - retrieve a nullfunc template
- * @hw: pointer obtained from ieee80211_alloc_hw().
- * @vif: &struct ieee80211_vif pointer from the add_interface callback.
- *
- * Creates a Nullfunc template which can, for example, uploaded to
- * hardware. The template must be updated after association so that correct
- * BSSID and address is used.
- *
- * Note: Caller (or hardware) is responsible for setting the
- * &IEEE80211_FCTL_PM bit as well as Duration and Sequence Control fields.
- */
-struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
-
-/**
- * ieee80211_probereq_get - retrieve a Probe Request template
- * @hw: pointer obtained from ieee80211_alloc_hw().
- * @vif: &struct ieee80211_vif pointer from the add_interface callback.
- * @ssid: SSID buffer
- * @ssid_len: length of SSID
- * @ie: buffer containing all IEs except SSID for the template
- * @ie_len: length of the IE buffer
- *
- * Creates a Probe Request template which can, for example, be uploaded to
- * hardware.
- */
-struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *ssid, size_t ssid_len,
- const u8 *ie, size_t ie_len);
-
/**
* ieee80211_rts_get - RTS frame generation function
* @hw: pointer obtained from ieee80211_alloc_hw().
- * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
* @frame: pointer to the frame that is going to be protected by the RTS.
* @frame_len: the frame length (in octets).
* @frame_txctl: &struct ieee80211_tx_info of the frame.
@@ -1999,7 +1837,7 @@ void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
/**
* ieee80211_rts_duration - Get the duration field for an RTS frame
* @hw: pointer obtained from ieee80211_alloc_hw().
- * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
* @frame_len: the length of the frame that is going to be protected by the RTS.
* @frame_txctl: &struct ieee80211_tx_info of the frame.
*
@@ -2014,7 +1852,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
/**
* ieee80211_ctstoself_get - CTS-to-self frame generation function
* @hw: pointer obtained from ieee80211_alloc_hw().
- * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
* @frame: pointer to the frame that is going to be protected by the CTS-to-self.
* @frame_len: the frame length (in octets).
* @frame_txctl: &struct ieee80211_tx_info of the frame.
@@ -2034,7 +1872,7 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
/**
* ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame
* @hw: pointer obtained from ieee80211_alloc_hw().
- * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
* @frame_len: the length of the frame that is going to be protected by the CTS-to-self.
* @frame_txctl: &struct ieee80211_tx_info of the frame.
*
@@ -2050,7 +1888,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
/**
* ieee80211_generic_frame_duration - Calculate the duration field for a frame
* @hw: pointer obtained from ieee80211_alloc_hw().
- * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
* @frame_len: the length of the frame.
* @rate: the rate at which the frame is going to be transmitted.
*
@@ -2065,7 +1903,7 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
/**
* ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames
* @hw: pointer as obtained from ieee80211_alloc_hw().
- * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
*
* Function for accessing buffered broadcast and multicast frames. If
* hardware/firmware does not implement buffering of broadcast/multicast
@@ -2233,7 +2071,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *sta, u16 tid);
/**
* ieee80211_start_tx_ba_cb - low level driver ready to aggregate.
- * @vif: &struct ieee80211_vif pointer from the add_interface callback
+ * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf
* @ra: receiver address of the BA session recipient.
* @tid: the TID to BA on.
*
@@ -2244,7 +2082,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid);
/**
* ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate.
- * @vif: &struct ieee80211_vif pointer from the add_interface callback
+ * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf
* @ra: receiver address of the BA session recipient.
* @tid: the TID to BA on.
*
@@ -2272,7 +2110,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *sta, u16 tid,
/**
* ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate.
- * @vif: &struct ieee80211_vif pointer from the add_interface callback
+ * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf
* @ra: receiver address of the BA session recipient.
* @tid: the desired TID to BA on.
*
@@ -2283,7 +2121,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid);
/**
* ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate.
- * @vif: &struct ieee80211_vif pointer from the add_interface callback
+ * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf
* @ra: receiver address of the BA session recipient.
* @tid: the desired TID to BA on.
*
@@ -2362,7 +2200,7 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
/**
* ieee80211_beacon_loss - inform hardware does not receive beacons
*
- * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
*
* When beacon filtering is enabled with IEEE80211_HW_BEACON_FILTERING and
* IEEE80211_CONF_PS is set, the driver needs to inform whenever the
@@ -2396,12 +2234,8 @@ enum rate_control_changed {
* @short_preamble: whether mac80211 will request short-preamble transmission
* if the selected rate supports it
* @max_rate_idx: user-requested maximum rate (not MCS for now)
- * (deprecated; this will be removed once drivers get updated to use
- * rate_idx_mask)
- * @rate_idx_mask: user-requested rate mask (not MCS for now)
* @skb: the skb that will be transmitted, the control information in it needs
* to be filled in
- * @ap: whether this frame is sent out in AP mode
*/
struct ieee80211_tx_rate_control {
struct ieee80211_hw *hw;
@@ -2411,8 +2245,6 @@ struct ieee80211_tx_rate_control {
struct ieee80211_tx_rate reported_rate;
bool rts, short_preamble;
u8 max_rate_idx;
- u32 rate_idx_mask;
- bool ap;
};
struct rate_control_ops {
diff --git a/trunk/include/net/regulatory.h b/trunk/include/net/regulatory.h
index f873ee37f7e4..47995b81c5d7 100644
--- a/trunk/include/net/regulatory.h
+++ b/trunk/include/net/regulatory.h
@@ -39,7 +39,6 @@ enum environment_cap {
* 00 - World regulatory domain
* 99 - built by driver but a specific alpha2 cannot be determined
* 98 - result of an intersection between two regulatory domains
- * 97 - regulatory domain has not yet been configured
* @intersect: indicates whether the wireless core should intersect
* the requested regulatory domain with the presently set regulatory
* domain.
diff --git a/trunk/include/pcmcia/device_id.h b/trunk/include/pcmcia/device_id.h
index 63e5b8f6b7dd..c33ea08352b8 100644
--- a/trunk/include/pcmcia/device_id.h
+++ b/trunk/include/pcmcia/device_id.h
@@ -34,11 +34,6 @@
.prod_id = { NULL, (v2), NULL, NULL }, \
.prod_id_hash = { 0, (vh2), 0, 0 }, }
-#define PCMCIA_DEVICE_PROD_ID3(v3, vh3) { \
- .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID3, \
- .prod_id = { NULL, NULL, (v3), NULL }, \
- .prod_id_hash = { 0, 0, (vh3), 0 }, }
-
#define PCMCIA_DEVICE_PROD_ID12(v1, v2, vh1, vh2) { \
.match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \
PCMCIA_DEV_ID_MATCH_PROD_ID2, \
diff --git a/trunk/net/mac80211/Kconfig b/trunk/net/mac80211/Kconfig
index a952b7f8c648..a10d508b07e1 100644
--- a/trunk/net/mac80211/Kconfig
+++ b/trunk/net/mac80211/Kconfig
@@ -96,6 +96,18 @@ menuconfig MAC80211_DEBUG_MENU
---help---
This option collects various mac80211 debug settings.
+config MAC80211_DEBUG_PACKET_ALIGNMENT
+ bool "Enable packet alignment debugging"
+ depends on MAC80211_DEBUG_MENU
+ ---help---
+ This option is recommended for driver authors and strongly
+ discouraged for everybody else, it will trigger a warning
+ when a driver hands mac80211 a buffer that is aligned in
+ a way that will cause problems with the IP stack on some
+ architectures.
+
+ Say N unless you're writing a mac80211 based driver.
+
config MAC80211_NOINLINE
bool "Do not inline TX/RX handlers"
depends on MAC80211_DEBUG_MENU
diff --git a/trunk/net/mac80211/Makefile b/trunk/net/mac80211/Makefile
index 04420291e7ad..298cfcc1bf8d 100644
--- a/trunk/net/mac80211/Makefile
+++ b/trunk/net/mac80211/Makefile
@@ -6,10 +6,10 @@ mac80211-y := \
sta_info.o \
wep.o \
wpa.o \
- scan.o offchannel.o \
+ scan.o \
ht.o agg-tx.o agg-rx.o \
ibss.o \
- mlme.o work.o \
+ mlme.o \
iface.o \
rate.o \
michael.o \
diff --git a/trunk/net/mac80211/agg-rx.c b/trunk/net/mac80211/agg-rx.c
index a978e666ed6f..51c7dc3c4c3b 100644
--- a/trunk/net/mac80211/agg-rx.c
+++ b/trunk/net/mac80211/agg-rx.c
@@ -41,7 +41,8 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
sta->sta.addr, tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */
- if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP,
+ if (drv_ampdu_action(local, &sta->sdata->vif,
+ IEEE80211_AMPDU_RX_STOP,
&sta->sta, tid, NULL))
printk(KERN_DEBUG "HW problem - can not stop rx "
"aggregation for tid %d\n", tid);
@@ -82,11 +83,12 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid,
u16 initiator, u16 reason)
{
+ struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
rcu_read_lock();
- sta = sta_info_get(sdata, ra);
+ sta = sta_info_get(local, ra);
if (!sta) {
rcu_read_unlock();
return;
@@ -134,7 +136,7 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
if (!skb) {
printk(KERN_DEBUG "%s: failed to allocate buffer "
- "for addba resp frame\n", sdata->name);
+ "for addba resp frame\n", sdata->dev->name);
return;
}
@@ -142,10 +144,10 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
memset(mgmt, 0, 24);
memcpy(mgmt->da, da, ETH_ALEN);
- memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+ memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
if (sdata->vif.type == NL80211_IFTYPE_AP ||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
+ memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
else if (sdata->vif.type == NL80211_IFTYPE_STATION)
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
@@ -279,7 +281,8 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
goto end;
}
- ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START,
+ ret = drv_ampdu_action(local, &sta->sdata->vif,
+ IEEE80211_AMPDU_RX_START,
&sta->sta, tid, &start_seq_num);
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret);
diff --git a/trunk/net/mac80211/agg-tx.c b/trunk/net/mac80211/agg-tx.c
index 5538e1b4a697..5e3a7eccef5a 100644
--- a/trunk/net/mac80211/agg-tx.c
+++ b/trunk/net/mac80211/agg-tx.c
@@ -58,17 +58,17 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
if (!skb) {
printk(KERN_ERR "%s: failed to allocate buffer "
- "for addba request frame\n", sdata->name);
+ "for addba request frame\n", sdata->dev->name);
return;
}
skb_reserve(skb, local->hw.extra_tx_headroom);
mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
memset(mgmt, 0, 24);
memcpy(mgmt->da, da, ETH_ALEN);
- memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+ memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
if (sdata->vif.type == NL80211_IFTYPE_AP ||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
+ memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
else if (sdata->vif.type == NL80211_IFTYPE_STATION)
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
@@ -104,7 +104,7 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1
skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom);
if (!skb) {
printk(KERN_ERR "%s: failed to allocate buffer for "
- "bar frame\n", sdata->name);
+ "bar frame\n", sdata->dev->name);
return;
}
skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -113,7 +113,7 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1
bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
IEEE80211_STYPE_BACK_REQ);
memcpy(bar->ra, ra, ETH_ALEN);
- memcpy(bar->ta, sdata->vif.addr, ETH_ALEN);
+ memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN);
bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL;
bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA;
bar_control |= (u16)(tid << 12);
@@ -144,7 +144,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
*state = HT_AGG_STATE_REQ_STOP_BA_MSK |
(initiator << HT_AGG_STATE_INITIATOR_SHIFT);
- ret = drv_ampdu_action(local, sta->sdata,
+ ret = drv_ampdu_action(local, &sta->sdata->vif,
IEEE80211_AMPDU_TX_STOP,
&sta->sta, tid, NULL);
@@ -179,8 +179,7 @@ static void sta_addba_resp_timer_expired(unsigned long data)
/* check if the TID waits for addBA response */
spin_lock_bh(&sta->lock);
- if ((*state & (HT_ADDBA_REQUESTED_MSK | HT_ADDBA_RECEIVED_MSK |
- HT_AGG_STATE_REQ_STOP_BA_MSK)) !=
+ if ((*state & (HT_ADDBA_REQUESTED_MSK | HT_ADDBA_RECEIVED_MSK)) !=
HT_ADDBA_REQUESTED_MSK) {
spin_unlock_bh(&sta->lock);
*state = HT_AGG_STATE_IDLE;
@@ -237,14 +236,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
sdata->vif.type != NL80211_IFTYPE_AP)
return -EINVAL;
- if (test_sta_flags(sta, WLAN_STA_DISASSOC)) {
-#ifdef CONFIG_MAC80211_HT_DEBUG
- printk(KERN_DEBUG "Disassociation is in progress. "
- "Denying BA session request\n");
-#endif
- return -EINVAL;
- }
-
if (test_sta_flags(sta, WLAN_STA_SUSPEND)) {
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Suspend in progress. "
@@ -310,9 +301,10 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
* call back right away, it must see that the flow has begun */
*state |= HT_ADDBA_REQUESTED_MSK;
- start_seq_num = sta->tid_seq[tid] >> 4;
+ start_seq_num = sta->tid_seq[tid];
- ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START,
+ ret = drv_ampdu_action(local, &sdata->vif,
+ IEEE80211_AMPDU_TX_START,
pubsta, tid, &start_seq_num);
if (ret) {
@@ -428,7 +420,7 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
ieee80211_agg_splice_finish(local, sta, tid);
spin_unlock(&local->ampdu_lock);
- drv_ampdu_action(local, sta->sdata,
+ drv_ampdu_action(local, &sta->sdata->vif,
IEEE80211_AMPDU_TX_OPERATIONAL,
&sta->sta, tid, NULL);
}
@@ -449,7 +441,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
}
rcu_read_lock();
- sta = sta_info_get(sdata, ra);
+ sta = sta_info_get(local, ra);
if (!sta) {
rcu_read_unlock();
#ifdef CONFIG_MAC80211_HT_DEBUG
@@ -497,7 +489,7 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
#ifdef CONFIG_MAC80211_HT_DEBUG
if (net_ratelimit())
printk(KERN_WARNING "%s: Not enough memory, "
- "dropping start BA session", sdata->name);
+ "dropping start BA session", skb->dev->name);
#endif
return;
}
@@ -572,7 +564,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
#endif /* CONFIG_MAC80211_HT_DEBUG */
rcu_read_lock();
- sta = sta_info_get(sdata, ra);
+ sta = sta_info_get(local, ra);
if (!sta) {
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Could not find station: %pM\n", ra);
@@ -629,7 +621,7 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
#ifdef CONFIG_MAC80211_HT_DEBUG
if (net_ratelimit())
printk(KERN_WARNING "%s: Not enough memory, "
- "dropping stop BA session", sdata->name);
+ "dropping stop BA session", skb->dev->name);
#endif
return;
}
diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c
index b7116ef84a3b..9ae1a4760b58 100644
--- a/trunk/net/mac80211/cfg.c
+++ b/trunk/net/mac80211/cfg.c
@@ -1,7 +1,7 @@
/*
* mac80211 configuration hooks for cfg80211
*
- * Copyright 2006-2010 Johannes Berg
+ * Copyright 2006, 2007 Johannes Berg
*
* This file is GPLv2 as found in COPYING.
*/
@@ -78,15 +78,17 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
enum nl80211_iftype type, u32 *flags,
struct vif_params *params)
{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_sub_if_data *sdata;
int ret;
- if (ieee80211_sdata_running(sdata))
+ if (netif_running(dev))
return -EBUSY;
if (!nl80211_params_check(type, params))
return -EINVAL;
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
ret = ieee80211_if_change_type(sdata, type);
if (ret)
return ret;
@@ -148,7 +150,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
rcu_read_lock();
if (mac_addr) {
- sta = sta_info_get_bss(sdata, mac_addr);
+ sta = sta_info_get(sdata->local, mac_addr);
if (!sta) {
ieee80211_key_free(key);
err = -ENOENT;
@@ -179,7 +181,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
if (mac_addr) {
ret = -ENOENT;
- sta = sta_info_get_bss(sdata, mac_addr);
+ sta = sta_info_get(sdata->local, mac_addr);
if (!sta)
goto out_unlock;
@@ -226,7 +228,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
rcu_read_lock();
if (mac_addr) {
- sta = sta_info_get_bss(sdata, mac_addr);
+ sta = sta_info_get(sdata->local, mac_addr);
if (!sta)
goto out;
@@ -413,13 +415,15 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
u8 *mac, struct station_info *sinfo)
{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct sta_info *sta;
int ret = -ENOENT;
rcu_read_lock();
- sta = sta_info_get_bss(sdata, mac);
+ /* XXX: verify sta->dev == dev */
+
+ sta = sta_info_get(local, mac);
if (sta) {
ret = 0;
sta_set_sinfo(sta, sinfo);
@@ -515,8 +519,6 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
if (old)
memcpy(new->tail, old->tail, new_tail_len);
- sdata->vif.bss_conf.dtim_period = new->dtim_period;
-
rcu_assign_pointer(sdata->u.ap.beacon, new);
synchronize_rcu();
@@ -730,7 +732,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
} else
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (compare_ether_addr(mac, sdata->vif.addr) == 0)
+ if (compare_ether_addr(mac, dev->dev_addr) == 0)
return -EINVAL;
if (is_multicast_ether_addr(mac))
@@ -749,7 +751,9 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
sdata->vif.type == NL80211_IFTYPE_AP;
- err = sta_info_insert_rcu(sta);
+ rcu_read_lock();
+
+ err = sta_info_insert(sta);
if (err) {
rcu_read_unlock();
return err;
@@ -768,13 +772,27 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata;
+ struct sta_info *sta;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (mac)
- return sta_info_destroy_addr_bss(sdata, mac);
+ if (mac) {
+ rcu_read_lock();
+
+ /* XXX: get sta belonging to dev */
+ sta = sta_info_get(local, mac);
+ if (!sta) {
+ rcu_read_unlock();
+ return -ENOENT;
+ }
+
+ sta_info_unlink(&sta);
+ rcu_read_unlock();
+
+ sta_info_destroy(sta);
+ } else
+ sta_info_flush(local, sdata);
- sta_info_flush(local, sdata);
return 0;
}
@@ -783,14 +801,14 @@ static int ieee80211_change_station(struct wiphy *wiphy,
u8 *mac,
struct station_parameters *params)
{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = wiphy_priv(wiphy);
struct sta_info *sta;
struct ieee80211_sub_if_data *vlansdata;
rcu_read_lock();
- sta = sta_info_get_bss(sdata, mac);
+ /* XXX: get sta belonging to dev */
+ sta = sta_info_get(local, mac);
if (!sta) {
rcu_read_unlock();
return -ENOENT;
@@ -829,6 +847,7 @@ static int ieee80211_change_station(struct wiphy *wiphy,
static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
u8 *dst, u8 *next_hop)
{
+ struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata;
struct mesh_path *mpath;
struct sta_info *sta;
@@ -837,7 +856,7 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
rcu_read_lock();
- sta = sta_info_get(sdata, next_hop);
+ sta = sta_info_get(local, next_hop);
if (!sta) {
rcu_read_unlock();
return -ENOENT;
@@ -876,6 +895,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy,
struct net_device *dev,
u8 *dst, u8 *next_hop)
{
+ struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata;
struct mesh_path *mpath;
struct sta_info *sta;
@@ -884,7 +904,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy,
rcu_read_lock();
- sta = sta_info_get(sdata, next_hop);
+ sta = sta_info_get(local, next_hop);
if (!sta) {
rcu_read_unlock();
return -ENOENT;
@@ -1072,13 +1092,6 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
params->use_short_preamble;
changed |= BSS_CHANGED_ERP_PREAMBLE;
}
-
- if (!sdata->vif.bss_conf.use_short_slot &&
- sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) {
- sdata->vif.bss_conf.use_short_slot = true;
- changed |= BSS_CHANGED_ERP_SLOT;
- }
-
if (params->use_short_slot_time >= 0) {
sdata->vif.bss_conf.use_short_slot =
params->use_short_slot_time;
@@ -1122,13 +1135,6 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
p.cw_max = params->cwmax;
p.cw_min = params->cwmin;
p.txop = params->txop;
-
- /*
- * Setting tx queue params disables u-apsd because it's only
- * called in master mode.
- */
- p.uapsd = false;
-
if (drv_conf_tx(local, params->queue, &p)) {
printk(KERN_DEBUG "%s: failed to set TX queue "
"parameters for queue %d\n",
@@ -1231,13 +1237,6 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
struct ieee80211_local *local = wiphy_priv(wiphy);
int err;
- if (changed & WIPHY_PARAM_COVERAGE_CLASS) {
- err = drv_set_coverage_class(local, wiphy->coverage_class);
-
- if (err)
- return err;
- }
-
if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
err = drv_set_rts_threshold(local, wiphy->rts_threshold);
@@ -1325,50 +1324,6 @@ static int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len)
}
#endif
-int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
- enum ieee80211_smps_mode smps_mode)
-{
- const u8 *ap;
- enum ieee80211_smps_mode old_req;
- int err;
-
- old_req = sdata->u.mgd.req_smps;
- sdata->u.mgd.req_smps = smps_mode;
-
- if (old_req == smps_mode &&
- smps_mode != IEEE80211_SMPS_AUTOMATIC)
- return 0;
-
- /*
- * If not associated, or current association is not an HT
- * association, there's no need to send an action frame.
- */
- if (!sdata->u.mgd.associated ||
- sdata->local->oper_channel_type == NL80211_CHAN_NO_HT) {
- mutex_lock(&sdata->local->iflist_mtx);
- ieee80211_recalc_smps(sdata->local, sdata);
- mutex_unlock(&sdata->local->iflist_mtx);
- return 0;
- }
-
- ap = sdata->u.mgd.associated->bssid;
-
- if (smps_mode == IEEE80211_SMPS_AUTOMATIC) {
- if (sdata->u.mgd.powersave)
- smps_mode = IEEE80211_SMPS_DYNAMIC;
- else
- smps_mode = IEEE80211_SMPS_OFF;
- }
-
- /* send SM PS frame to AP */
- err = ieee80211_send_smps_action(sdata, smps_mode,
- ap, ap);
- if (err)
- sdata->u.mgd.req_smps = old_req;
-
- return err;
-}
-
static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
bool enabled, int timeout)
{
@@ -1389,11 +1344,6 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
sdata->u.mgd.powersave = enabled;
conf->dynamic_ps_timeout = timeout;
- /* no change, but if automatic follow powersave */
- mutex_lock(&sdata->u.mgd.mtx);
- __ieee80211_request_smps(sdata, sdata->u.mgd.req_smps);
- mutex_unlock(&sdata->u.mgd.mtx);
-
if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
@@ -1409,52 +1359,39 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- int i;
-
- /*
- * This _could_ be supported by providing a hook for
- * drivers for this function, but at this point it
- * doesn't seem worth bothering.
- */
- if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)
- return -EOPNOTSUPP;
-
-
- for (i = 0; i < IEEE80211_NUM_BANDS; i++)
- sdata->rc_rateidx_mask[i] = mask->control[i].legacy;
+ int i, err = -EINVAL;
+ u32 target_rate;
+ struct ieee80211_supported_band *sband;
- return 0;
-}
+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-static int ieee80211_remain_on_channel(struct wiphy *wiphy,
- struct net_device *dev,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- unsigned int duration,
- u64 *cookie)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
+ * target_rate = X, rate->fixed = 1 means only rate X
+ * target_rate = X, rate->fixed = 0 means all rates <= X */
+ sdata->max_ratectrl_rateidx = -1;
+ sdata->force_unicast_rateidx = -1;
- return ieee80211_wk_remain_on_channel(sdata, chan, channel_type,
- duration, cookie);
-}
+ if (mask->fixed)
+ target_rate = mask->fixed / 100;
+ else if (mask->maxrate)
+ target_rate = mask->maxrate / 100;
+ else
+ return 0;
-static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
- struct net_device *dev,
- u64 cookie)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ for (i=0; i< sband->n_bitrates; i++) {
+ struct ieee80211_rate *brate = &sband->bitrates[i];
+ int this_rate = brate->bitrate;
- return ieee80211_wk_cancel_remain_on_channel(sdata, cookie);
-}
+ if (target_rate == this_rate) {
+ sdata->max_ratectrl_rateidx = i;
+ if (mask->fixed)
+ sdata->force_unicast_rateidx = i;
+ err = 0;
+ break;
+ }
+ }
-static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- const u8 *buf, size_t len, u64 *cookie)
-{
- return ieee80211_mgd_action(IEEE80211_DEV_TO_SUB_IF(dev), chan,
- channel_type, buf, len, cookie);
+ return err;
}
struct cfg80211_ops mac80211_config_ops = {
@@ -1503,7 +1440,4 @@ struct cfg80211_ops mac80211_config_ops = {
CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
.set_power_mgmt = ieee80211_set_power_mgmt,
.set_bitrate_mask = ieee80211_set_bitrate_mask,
- .remain_on_channel = ieee80211_remain_on_channel,
- .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel,
- .action = ieee80211_action,
};
diff --git a/trunk/net/mac80211/debugfs.c b/trunk/net/mac80211/debugfs.c
index 637929b65ccc..e4b54093d41b 100644
--- a/trunk/net/mac80211/debugfs.c
+++ b/trunk/net/mac80211/debugfs.c
@@ -158,130 +158,6 @@ static const struct file_operations noack_ops = {
.open = mac80211_open_file_generic
};
-static ssize_t uapsd_queues_read(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ieee80211_local *local = file->private_data;
- int res;
- char buf[10];
-
- res = scnprintf(buf, sizeof(buf), "0x%x\n", local->uapsd_queues);
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, res);
-}
-
-static ssize_t uapsd_queues_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ieee80211_local *local = file->private_data;
- unsigned long val;
- char buf[10];
- size_t len;
- int ret;
-
- len = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, len))
- return -EFAULT;
- buf[len] = '\0';
-
- ret = strict_strtoul(buf, 0, &val);
-
- if (ret)
- return -EINVAL;
-
- if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
- return -ERANGE;
-
- local->uapsd_queues = val;
-
- return count;
-}
-
-static const struct file_operations uapsd_queues_ops = {
- .read = uapsd_queues_read,
- .write = uapsd_queues_write,
- .open = mac80211_open_file_generic
-};
-
-static ssize_t uapsd_max_sp_len_read(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ieee80211_local *local = file->private_data;
- int res;
- char buf[10];
-
- res = scnprintf(buf, sizeof(buf), "0x%x\n", local->uapsd_max_sp_len);
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, res);
-}
-
-static ssize_t uapsd_max_sp_len_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ieee80211_local *local = file->private_data;
- unsigned long val;
- char buf[10];
- size_t len;
- int ret;
-
- len = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, len))
- return -EFAULT;
- buf[len] = '\0';
-
- ret = strict_strtoul(buf, 0, &val);
-
- if (ret)
- return -EINVAL;
-
- if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
- return -ERANGE;
-
- local->uapsd_max_sp_len = val;
-
- return count;
-}
-
-static const struct file_operations uapsd_max_sp_len_ops = {
- .read = uapsd_max_sp_len_read,
- .write = uapsd_max_sp_len_write,
- .open = mac80211_open_file_generic
-};
-
-static ssize_t channel_type_read(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ieee80211_local *local = file->private_data;
- const char *buf;
-
- switch (local->hw.conf.channel_type) {
- case NL80211_CHAN_NO_HT:
- buf = "no ht\n";
- break;
- case NL80211_CHAN_HT20:
- buf = "ht20\n";
- break;
- case NL80211_CHAN_HT40MINUS:
- buf = "ht40-\n";
- break;
- case NL80211_CHAN_HT40PLUS:
- buf = "ht40+\n";
- break;
- default:
- buf = "???";
- break;
- }
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
-}
-
-static const struct file_operations channel_type_ops = {
- .read = channel_type_read,
- .open = mac80211_open_file_generic
-};
-
static ssize_t queues_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -438,9 +314,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
DEBUGFS_ADD(queues);
DEBUGFS_ADD_MODE(reset, 0200);
DEBUGFS_ADD(noack);
- DEBUGFS_ADD(uapsd_queues);
- DEBUGFS_ADD(uapsd_max_sp_len);
- DEBUGFS_ADD(channel_type);
statsd = debugfs_create_dir("statistics", phyd);
diff --git a/trunk/net/mac80211/debugfs_key.c b/trunk/net/mac80211/debugfs_key.c
index d12e743cb4e1..e0f5224630da 100644
--- a/trunk/net/mac80211/debugfs_key.c
+++ b/trunk/net/mac80211/debugfs_key.c
@@ -56,7 +56,7 @@ KEY_CONF_FILE(keyidx, D);
KEY_CONF_FILE(hw_key_idx, D);
KEY_FILE(flags, X);
KEY_FILE(tx_rx_count, D);
-KEY_READ(ifindex, sdata->name, IFNAMSIZ + 2, "%s\n");
+KEY_READ(ifindex, sdata->dev->ifindex, 20, "%d\n");
KEY_OPS(ifindex);
static ssize_t key_algorithm_read(struct file *file,
diff --git a/trunk/net/mac80211/debugfs_netdev.c b/trunk/net/mac80211/debugfs_netdev.c
index 9affe2cd185f..472b2039906c 100644
--- a/trunk/net/mac80211/debugfs_netdev.c
+++ b/trunk/net/mac80211/debugfs_netdev.c
@@ -41,30 +41,6 @@ static ssize_t ieee80211_if_read(
return ret;
}
-static ssize_t ieee80211_if_write(
- struct ieee80211_sub_if_data *sdata,
- const char __user *userbuf,
- size_t count, loff_t *ppos,
- ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int))
-{
- u8 *buf;
- ssize_t ret = -ENODEV;
-
- buf = kzalloc(count, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- if (copy_from_user(buf, userbuf, count))
- return -EFAULT;
-
- rtnl_lock();
- if (sdata->dev->reg_state == NETREG_REGISTERED)
- ret = (*write)(sdata, buf, count);
- rtnl_unlock();
-
- return ret;
-}
-
#define IEEE80211_IF_FMT(name, field, format_string) \
static ssize_t ieee80211_if_fmt_##name( \
const struct ieee80211_sub_if_data *sdata, char *buf, \
@@ -95,7 +71,7 @@ static ssize_t ieee80211_if_fmt_##name( \
return scnprintf(buf, buflen, "%pM\n", sdata->field); \
}
-#define __IEEE80211_IF_FILE(name, _write) \
+#define __IEEE80211_IF_FILE(name) \
static ssize_t ieee80211_if_read_##name(struct file *file, \
char __user *userbuf, \
size_t count, loff_t *ppos) \
@@ -106,99 +82,22 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \
} \
static const struct file_operations name##_ops = { \
.read = ieee80211_if_read_##name, \
- .write = (_write), \
.open = mac80211_open_file_generic, \
}
-#define __IEEE80211_IF_FILE_W(name) \
-static ssize_t ieee80211_if_write_##name(struct file *file, \
- const char __user *userbuf, \
- size_t count, loff_t *ppos) \
-{ \
- return ieee80211_if_write(file->private_data, userbuf, count, \
- ppos, ieee80211_if_parse_##name); \
-} \
-__IEEE80211_IF_FILE(name, ieee80211_if_write_##name)
-
-
#define IEEE80211_IF_FILE(name, field, format) \
IEEE80211_IF_FMT_##format(name, field) \
- __IEEE80211_IF_FILE(name, NULL)
+ __IEEE80211_IF_FILE(name)
/* common attributes */
IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
-IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ],
- HEX);
-IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ],
- HEX);
+IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC);
+IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC);
/* STA attributes */
IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
IEEE80211_IF_FILE(aid, u.mgd.aid, DEC);
-
-static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
- enum ieee80211_smps_mode smps_mode)
-{
- struct ieee80211_local *local = sdata->local;
- int err;
-
- if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) &&
- smps_mode == IEEE80211_SMPS_STATIC)
- return -EINVAL;
-
- /* auto should be dynamic if in PS mode */
- if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) &&
- (smps_mode == IEEE80211_SMPS_DYNAMIC ||
- smps_mode == IEEE80211_SMPS_AUTOMATIC))
- return -EINVAL;
-
- /* supported only on managed interfaces for now */
- if (sdata->vif.type != NL80211_IFTYPE_STATION)
- return -EOPNOTSUPP;
-
- mutex_lock(&local->iflist_mtx);
- err = __ieee80211_request_smps(sdata, smps_mode);
- mutex_unlock(&local->iflist_mtx);
-
- return err;
-}
-
-static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = {
- [IEEE80211_SMPS_AUTOMATIC] = "auto",
- [IEEE80211_SMPS_OFF] = "off",
- [IEEE80211_SMPS_STATIC] = "static",
- [IEEE80211_SMPS_DYNAMIC] = "dynamic",
-};
-
-static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata,
- char *buf, int buflen)
-{
- if (sdata->vif.type != NL80211_IFTYPE_STATION)
- return -EOPNOTSUPP;
-
- return snprintf(buf, buflen, "request: %s\nused: %s\n",
- smps_modes[sdata->u.mgd.req_smps],
- smps_modes[sdata->u.mgd.ap_smps]);
-}
-
-static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata,
- const char *buf, int buflen)
-{
- enum ieee80211_smps_mode mode;
-
- for (mode = 0; mode < IEEE80211_SMPS_NUM_MODES; mode++) {
- if (strncmp(buf, smps_modes[mode], buflen) == 0) {
- int err = ieee80211_set_smps(sdata, mode);
- if (!err)
- return buflen;
- return err;
- }
- }
-
- return -EINVAL;
-}
-
-__IEEE80211_IF_FILE_W(smps);
+IEEE80211_IF_FILE(capab, u.mgd.capab, HEX);
/* AP attributes */
IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
@@ -210,7 +109,7 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast(
return scnprintf(buf, buflen, "%u\n",
skb_queue_len(&sdata->u.ap.ps_bc_buf));
}
-__IEEE80211_IF_FILE(num_buffered_multicast, NULL);
+__IEEE80211_IF_FILE(num_buffered_multicast);
/* WDS attributes */
IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
@@ -255,50 +154,46 @@ IEEE80211_IF_FILE(dot11MeshHWMPRootMode,
#endif
-#define DEBUGFS_ADD(name) \
+#define DEBUGFS_ADD(name, type) \
debugfs_create_file(#name, 0400, sdata->debugfs.dir, \
sdata, &name##_ops);
-#define DEBUGFS_ADD_MODE(name, mode) \
- debugfs_create_file(#name, mode, sdata->debugfs.dir, \
- sdata, &name##_ops);
-
static void add_sta_files(struct ieee80211_sub_if_data *sdata)
{
- DEBUGFS_ADD(drop_unencrypted);
- DEBUGFS_ADD(rc_rateidx_mask_2ghz);
- DEBUGFS_ADD(rc_rateidx_mask_5ghz);
+ DEBUGFS_ADD(drop_unencrypted, sta);
+ DEBUGFS_ADD(force_unicast_rateidx, sta);
+ DEBUGFS_ADD(max_ratectrl_rateidx, sta);
- DEBUGFS_ADD(bssid);
- DEBUGFS_ADD(aid);
- DEBUGFS_ADD_MODE(smps, 0600);
+ DEBUGFS_ADD(bssid, sta);
+ DEBUGFS_ADD(aid, sta);
+ DEBUGFS_ADD(capab, sta);
}
static void add_ap_files(struct ieee80211_sub_if_data *sdata)
{
- DEBUGFS_ADD(drop_unencrypted);
- DEBUGFS_ADD(rc_rateidx_mask_2ghz);
- DEBUGFS_ADD(rc_rateidx_mask_5ghz);
+ DEBUGFS_ADD(drop_unencrypted, ap);
+ DEBUGFS_ADD(force_unicast_rateidx, ap);
+ DEBUGFS_ADD(max_ratectrl_rateidx, ap);
- DEBUGFS_ADD(num_sta_ps);
- DEBUGFS_ADD(dtim_count);
- DEBUGFS_ADD(num_buffered_multicast);
+ DEBUGFS_ADD(num_sta_ps, ap);
+ DEBUGFS_ADD(dtim_count, ap);
+ DEBUGFS_ADD(num_buffered_multicast, ap);
}
static void add_wds_files(struct ieee80211_sub_if_data *sdata)
{
- DEBUGFS_ADD(drop_unencrypted);
- DEBUGFS_ADD(rc_rateidx_mask_2ghz);
- DEBUGFS_ADD(rc_rateidx_mask_5ghz);
+ DEBUGFS_ADD(drop_unencrypted, wds);
+ DEBUGFS_ADD(force_unicast_rateidx, wds);
+ DEBUGFS_ADD(max_ratectrl_rateidx, wds);
- DEBUGFS_ADD(peer);
+ DEBUGFS_ADD(peer, wds);
}
static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
{
- DEBUGFS_ADD(drop_unencrypted);
- DEBUGFS_ADD(rc_rateidx_mask_2ghz);
- DEBUGFS_ADD(rc_rateidx_mask_5ghz);
+ DEBUGFS_ADD(drop_unencrypted, vlan);
+ DEBUGFS_ADD(force_unicast_rateidx, vlan);
+ DEBUGFS_ADD(max_ratectrl_rateidx, vlan);
}
static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
@@ -385,11 +280,16 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
}
}
+static int notif_registered;
+
void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
{
char buf[10+IFNAMSIZ];
- sprintf(buf, "netdev:%s", sdata->name);
+ if (!notif_registered)
+ return;
+
+ sprintf(buf, "netdev:%s", sdata->dev->name);
sdata->debugfs.dir = debugfs_create_dir(buf,
sdata->local->hw.wiphy->debugfsdir);
add_files(sdata);
@@ -404,18 +304,58 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
sdata->debugfs.dir = NULL;
}
-void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
+static int netdev_notify(struct notifier_block *nb,
+ unsigned long state,
+ void *ndev)
{
+ struct net_device *dev = ndev;
struct dentry *dir;
- char buf[10 + IFNAMSIZ];
+ struct ieee80211_sub_if_data *sdata;
+ char buf[10+IFNAMSIZ];
+
+ if (state != NETDEV_CHANGENAME)
+ return 0;
+
+ if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
+ return 0;
+
+ if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
+ return 0;
+
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
dir = sdata->debugfs.dir;
if (!dir)
- return;
+ return 0;
- sprintf(buf, "netdev:%s", sdata->name);
+ sprintf(buf, "netdev:%s", dev->name);
if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf))
printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs "
"dir to %s\n", buf);
+
+ return 0;
+}
+
+static struct notifier_block mac80211_debugfs_netdev_notifier = {
+ .notifier_call = netdev_notify,
+};
+
+void ieee80211_debugfs_netdev_init(void)
+{
+ int err;
+
+ err = register_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
+ if (err) {
+ printk(KERN_ERR
+ "mac80211: failed to install netdev notifier,"
+ " disabling per-netdev debugfs!\n");
+ } else
+ notif_registered = 1;
+}
+
+void ieee80211_debugfs_netdev_exit(void)
+{
+ unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
+ notif_registered = 0;
}
diff --git a/trunk/net/mac80211/debugfs_netdev.h b/trunk/net/mac80211/debugfs_netdev.h
index 79025e79f4d6..7af731f0b731 100644
--- a/trunk/net/mac80211/debugfs_netdev.h
+++ b/trunk/net/mac80211/debugfs_netdev.h
@@ -6,7 +6,8 @@
#ifdef CONFIG_MAC80211_DEBUGFS
void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata);
-void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata);
+void ieee80211_debugfs_netdev_init(void);
+void ieee80211_debugfs_netdev_exit(void);
#else
static inline void ieee80211_debugfs_add_netdev(
struct ieee80211_sub_if_data *sdata)
@@ -14,8 +15,10 @@ static inline void ieee80211_debugfs_add_netdev(
static inline void ieee80211_debugfs_remove_netdev(
struct ieee80211_sub_if_data *sdata)
{}
-static inline void ieee80211_debugfs_rename_netdev(
- struct ieee80211_sub_if_data *sdata)
+static inline void ieee80211_debugfs_netdev_init(void)
+{}
+
+static inline void ieee80211_debugfs_netdev_exit(void)
{}
#endif
diff --git a/trunk/net/mac80211/debugfs_sta.c b/trunk/net/mac80211/debugfs_sta.c
index d92800bb2d2f..3f41608c8081 100644
--- a/trunk/net/mac80211/debugfs_sta.c
+++ b/trunk/net/mac80211/debugfs_sta.c
@@ -44,7 +44,7 @@ static const struct file_operations sta_ ##name## _ops = { \
STA_OPS(name)
STA_FILE(aid, sta.aid, D);
-STA_FILE(dev, sdata->name, S);
+STA_FILE(dev, sdata->dev->name, S);
STA_FILE(rx_packets, rx_packets, LU);
STA_FILE(tx_packets, tx_packets, LU);
STA_FILE(rx_bytes, rx_bytes, LU);
@@ -120,38 +120,36 @@ STA_OPS(last_seq_ctrl);
static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- char buf[64 + STA_TID_NUM * 40], *p = buf;
+ char buf[30 + STA_TID_NUM * 70], *p = buf;
int i;
struct sta_info *sta = file->private_data;
spin_lock_bh(&sta->lock);
- p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n",
+ p += scnprintf(p, sizeof(buf)+buf-p, "next dialog_token is %#02x\n",
sta->ampdu_mlme.dialog_token_allocator + 1);
- p += scnprintf(p, sizeof(buf) + buf - p,
- "TID\t\tRX\tDTKN\tSSN\t\tTX\tDTKN\tSSN\tpending\n");
for (i = 0; i < STA_TID_NUM; i++) {
- p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i);
- p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x",
+ p += scnprintf(p, sizeof(buf)+buf-p, "TID %02d:", i);
+ p += scnprintf(p, sizeof(buf)+buf-p, " RX=%x",
sta->ampdu_mlme.tid_state_rx[i]);
- p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
+ p += scnprintf(p, sizeof(buf)+buf-p, "/DTKN=%#.2x",
sta->ampdu_mlme.tid_state_rx[i] ?
sta->ampdu_mlme.tid_rx[i]->dialog_token : 0);
- p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x",
+ p += scnprintf(p, sizeof(buf)+buf-p, "/SSN=%#.3x",
sta->ampdu_mlme.tid_state_rx[i] ?
sta->ampdu_mlme.tid_rx[i]->ssn : 0);
- p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x",
+ p += scnprintf(p, sizeof(buf)+buf-p, " TX=%x",
sta->ampdu_mlme.tid_state_tx[i]);
- p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
+ p += scnprintf(p, sizeof(buf)+buf-p, "/DTKN=%#.2x",
sta->ampdu_mlme.tid_state_tx[i] ?
sta->ampdu_mlme.tid_tx[i]->dialog_token : 0);
- p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x",
+ p += scnprintf(p, sizeof(buf)+buf-p, "/SSN=%#.3x",
sta->ampdu_mlme.tid_state_tx[i] ?
sta->ampdu_mlme.tid_tx[i]->ssn : 0);
- p += scnprintf(p, sizeof(buf) + buf - p, "\t%03d",
+ p += scnprintf(p, sizeof(buf)+buf-p, "/pending=%03d",
sta->ampdu_mlme.tid_state_tx[i] ?
skb_queue_len(&sta->ampdu_mlme.tid_tx[i]->pending) : 0);
- p += scnprintf(p, sizeof(buf) + buf - p, "\n");
+ p += scnprintf(p, sizeof(buf)+buf-p, "\n");
}
spin_unlock_bh(&sta->lock);
@@ -162,12 +160,7 @@ STA_OPS(agg_status);
static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
-#define PRINT_HT_CAP(_cond, _str) \
- do { \
- if (_cond) \
- p += scnprintf(p, sizeof(buf)+buf-p, "\t" _str "\n"); \
- } while (0)
- char buf[512], *p = buf;
+ char buf[200], *p = buf;
int i;
struct sta_info *sta = file->private_data;
struct ieee80211_sta_ht_cap *htc = &sta->sta.ht_cap;
@@ -175,64 +168,15 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
p += scnprintf(p, sizeof(buf) + buf - p, "ht %ssupported\n",
htc->ht_supported ? "" : "not ");
if (htc->ht_supported) {
- p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.4x\n", htc->cap);
-
- PRINT_HT_CAP((htc->cap & BIT(0)), "RX LDCP");
- PRINT_HT_CAP((htc->cap & BIT(1)), "HT20/HT40");
- PRINT_HT_CAP(!(htc->cap & BIT(1)), "HT20");
-
- PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 0, "Static SM Power Save");
- PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 1, "Dynamic SM Power Save");
- PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 3, "SM Power Save disabled");
-
- PRINT_HT_CAP((htc->cap & BIT(4)), "RX Greenfield");
- PRINT_HT_CAP((htc->cap & BIT(5)), "RX HT20 SGI");
- PRINT_HT_CAP((htc->cap & BIT(6)), "RX HT40 SGI");
- PRINT_HT_CAP((htc->cap & BIT(7)), "TX STBC");
-
- PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 0, "No RX STBC");
- PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 1, "RX STBC 1-stream");
- PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 2, "RX STBC 2-streams");
- PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 3, "RX STBC 3-streams");
-
- PRINT_HT_CAP((htc->cap & BIT(10)), "HT Delayed Block Ack");
-
- PRINT_HT_CAP((htc->cap & BIT(11)), "Max AMSDU length: "
- "3839 bytes");
- PRINT_HT_CAP(!(htc->cap & BIT(11)), "Max AMSDU length: "
- "7935 bytes");
-
- /*
- * For beacons and probe response this would mean the BSS
- * does or does not allow the usage of DSSS/CCK HT40.
- * Otherwise it means the STA does or does not use
- * DSSS/CCK HT40.
- */
- PRINT_HT_CAP((htc->cap & BIT(12)), "DSSS/CCK HT40");
- PRINT_HT_CAP(!(htc->cap & BIT(12)), "No DSSS/CCK HT40");
-
- /* BIT(13) is reserved */
-
- PRINT_HT_CAP((htc->cap & BIT(14)), "40 MHz Intolerant");
-
- PRINT_HT_CAP((htc->cap & BIT(15)), "L-SIG TXOP protection");
-
+ p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.2x\n", htc->cap);
p += scnprintf(p, sizeof(buf)+buf-p, "ampdu factor/density: %d/%d\n",
htc->ampdu_factor, htc->ampdu_density);
p += scnprintf(p, sizeof(buf)+buf-p, "MCS mask:");
-
for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
p += scnprintf(p, sizeof(buf)+buf-p, " %.2x",
htc->mcs.rx_mask[i]);
- p += scnprintf(p, sizeof(buf)+buf-p, "\n");
-
- /* If not set this is meaningless */
- if (le16_to_cpu(htc->mcs.rx_highest)) {
- p += scnprintf(p, sizeof(buf)+buf-p,
- "MCS rx highest: %d Mbps\n",
- le16_to_cpu(htc->mcs.rx_highest));
- }
-
+ p += scnprintf(p, sizeof(buf)+buf-p, "\nMCS rx highest: %d\n",
+ le16_to_cpu(htc->mcs.rx_highest));
p += scnprintf(p, sizeof(buf)+buf-p, "MCS tx params: %x\n",
htc->mcs.tx_params);
}
diff --git a/trunk/net/mac80211/driver-ops.h b/trunk/net/mac80211/driver-ops.h
index c3d844093a2f..921dd9c9ff62 100644
--- a/trunk/net/mac80211/driver-ops.h
+++ b/trunk/net/mac80211/driver-ops.h
@@ -14,8 +14,6 @@ static inline int drv_start(struct ieee80211_local *local)
{
int ret;
- might_sleep();
-
local->started = true;
smp_mb();
ret = local->ops->start(&local->hw);
@@ -25,8 +23,6 @@ static inline int drv_start(struct ieee80211_local *local)
static inline void drv_stop(struct ieee80211_local *local)
{
- might_sleep();
-
local->ops->stop(&local->hw);
trace_drv_stop(local);
@@ -40,47 +36,35 @@ static inline void drv_stop(struct ieee80211_local *local)
}
static inline int drv_add_interface(struct ieee80211_local *local,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
- int ret;
-
- might_sleep();
-
- ret = local->ops->add_interface(&local->hw, vif);
- trace_drv_add_interface(local, vif_to_sdata(vif), ret);
+ int ret = local->ops->add_interface(&local->hw, conf);
+ trace_drv_add_interface(local, conf->mac_addr, conf->vif, ret);
return ret;
}
static inline void drv_remove_interface(struct ieee80211_local *local,
- struct ieee80211_vif *vif)
+ struct ieee80211_if_init_conf *conf)
{
- might_sleep();
-
- local->ops->remove_interface(&local->hw, vif);
- trace_drv_remove_interface(local, vif_to_sdata(vif));
+ local->ops->remove_interface(&local->hw, conf);
+ trace_drv_remove_interface(local, conf->mac_addr, conf->vif);
}
static inline int drv_config(struct ieee80211_local *local, u32 changed)
{
- int ret;
-
- might_sleep();
-
- ret = local->ops->config(&local->hw, changed);
+ int ret = local->ops->config(&local->hw, changed);
trace_drv_config(local, changed, ret);
return ret;
}
static inline void drv_bss_info_changed(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info,
u32 changed)
{
- might_sleep();
-
if (local->ops->bss_info_changed)
- local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed);
- trace_drv_bss_info_changed(local, sdata, info, changed);
+ local->ops->bss_info_changed(&local->hw, vif, info, changed);
+ trace_drv_bss_info_changed(local, vif, info, changed);
}
static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
@@ -122,53 +106,36 @@ static inline int drv_set_tim(struct ieee80211_local *local,
}
static inline int drv_set_key(struct ieee80211_local *local,
- enum set_key_cmd cmd,
- struct ieee80211_sub_if_data *sdata,
+ enum set_key_cmd cmd, struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key)
{
- int ret;
-
- might_sleep();
-
- ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key);
- trace_drv_set_key(local, cmd, sdata, sta, key, ret);
+ int ret = local->ops->set_key(&local->hw, cmd, vif, sta, key);
+ trace_drv_set_key(local, cmd, vif, sta, key, ret);
return ret;
}
static inline void drv_update_tkip_key(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
struct ieee80211_key_conf *conf,
- struct sta_info *sta, u32 iv32,
+ const u8 *address, u32 iv32,
u16 *phase1key)
{
- struct ieee80211_sta *ista = NULL;
-
- if (sta)
- ista = &sta->sta;
-
if (local->ops->update_tkip_key)
- local->ops->update_tkip_key(&local->hw, &sdata->vif, conf,
- ista, iv32, phase1key);
- trace_drv_update_tkip_key(local, sdata, conf, ista, iv32);
+ local->ops->update_tkip_key(&local->hw, conf, address,
+ iv32, phase1key);
+ trace_drv_update_tkip_key(local, conf, address, iv32);
}
static inline int drv_hw_scan(struct ieee80211_local *local,
struct cfg80211_scan_request *req)
{
- int ret;
-
- might_sleep();
-
- ret = local->ops->hw_scan(&local->hw, req);
+ int ret = local->ops->hw_scan(&local->hw, req);
trace_drv_hw_scan(local, req, ret);
return ret;
}
static inline void drv_sw_scan_start(struct ieee80211_local *local)
{
- might_sleep();
-
if (local->ops->sw_scan_start)
local->ops->sw_scan_start(&local->hw);
trace_drv_sw_scan_start(local);
@@ -176,8 +143,6 @@ static inline void drv_sw_scan_start(struct ieee80211_local *local)
static inline void drv_sw_scan_complete(struct ieee80211_local *local)
{
- might_sleep();
-
if (local->ops->sw_scan_complete)
local->ops->sw_scan_complete(&local->hw);
trace_drv_sw_scan_complete(local);
@@ -188,8 +153,6 @@ static inline int drv_get_stats(struct ieee80211_local *local,
{
int ret = -EOPNOTSUPP;
- might_sleep();
-
if (local->ops->get_stats)
ret = local->ops->get_stats(&local->hw, stats);
trace_drv_get_stats(local, stats, ret);
@@ -209,93 +172,43 @@ static inline int drv_set_rts_threshold(struct ieee80211_local *local,
u32 value)
{
int ret = 0;
-
- might_sleep();
-
if (local->ops->set_rts_threshold)
ret = local->ops->set_rts_threshold(&local->hw, value);
trace_drv_set_rts_threshold(local, value, ret);
return ret;
}
-static inline int drv_set_coverage_class(struct ieee80211_local *local,
- u8 value)
-{
- int ret = 0;
- might_sleep();
-
- if (local->ops->set_coverage_class)
- local->ops->set_coverage_class(&local->hw, value);
- else
- ret = -EOPNOTSUPP;
-
- trace_drv_set_coverage_class(local, value, ret);
- return ret;
-}
-
static inline void drv_sta_notify(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_vif *vif,
enum sta_notify_cmd cmd,
struct ieee80211_sta *sta)
{
if (local->ops->sta_notify)
- local->ops->sta_notify(&local->hw, &sdata->vif, cmd, sta);
- trace_drv_sta_notify(local, sdata, cmd, sta);
-}
-
-static inline int drv_sta_add(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct ieee80211_sta *sta)
-{
- int ret = 0;
-
- might_sleep();
-
- if (local->ops->sta_add)
- ret = local->ops->sta_add(&local->hw, &sdata->vif, sta);
- else if (local->ops->sta_notify)
- local->ops->sta_notify(&local->hw, &sdata->vif,
- STA_NOTIFY_ADD, sta);
-
- trace_drv_sta_add(local, sdata, sta, ret);
-
- return ret;
-}
-
-static inline void drv_sta_remove(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct ieee80211_sta *sta)
-{
- might_sleep();
-
- if (local->ops->sta_remove)
- local->ops->sta_remove(&local->hw, &sdata->vif, sta);
- else if (local->ops->sta_notify)
- local->ops->sta_notify(&local->hw, &sdata->vif,
- STA_NOTIFY_REMOVE, sta);
-
- trace_drv_sta_remove(local, sdata, sta);
+ local->ops->sta_notify(&local->hw, vif, cmd, sta);
+ trace_drv_sta_notify(local, vif, cmd, sta);
}
static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
int ret = -EOPNOTSUPP;
-
- might_sleep();
-
if (local->ops->conf_tx)
ret = local->ops->conf_tx(&local->hw, queue, params);
trace_drv_conf_tx(local, queue, params, ret);
return ret;
}
+static inline int drv_get_tx_stats(struct ieee80211_local *local,
+ struct ieee80211_tx_queue_stats *stats)
+{
+ int ret = local->ops->get_tx_stats(&local->hw, stats);
+ trace_drv_get_tx_stats(local, stats, ret);
+ return ret;
+}
+
static inline u64 drv_get_tsf(struct ieee80211_local *local)
{
u64 ret = -1ULL;
-
- might_sleep();
-
if (local->ops->get_tsf)
ret = local->ops->get_tsf(&local->hw);
trace_drv_get_tsf(local, ret);
@@ -304,8 +217,6 @@ static inline u64 drv_get_tsf(struct ieee80211_local *local)
static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf)
{
- might_sleep();
-
if (local->ops->set_tsf)
local->ops->set_tsf(&local->hw, tsf);
trace_drv_set_tsf(local, tsf);
@@ -313,8 +224,6 @@ static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf)
static inline void drv_reset_tsf(struct ieee80211_local *local)
{
- might_sleep();
-
if (local->ops->reset_tsf)
local->ops->reset_tsf(&local->hw);
trace_drv_reset_tsf(local);
@@ -323,9 +232,6 @@ static inline void drv_reset_tsf(struct ieee80211_local *local)
static inline int drv_tx_last_beacon(struct ieee80211_local *local)
{
int ret = 1;
-
- might_sleep();
-
if (local->ops->tx_last_beacon)
ret = local->ops->tx_last_beacon(&local->hw);
trace_drv_tx_last_beacon(local, ret);
@@ -333,34 +239,23 @@ static inline int drv_tx_last_beacon(struct ieee80211_local *local)
}
static inline int drv_ampdu_action(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid,
u16 *ssn)
{
int ret = -EOPNOTSUPP;
if (local->ops->ampdu_action)
- ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action,
+ ret = local->ops->ampdu_action(&local->hw, vif, action,
sta, tid, ssn);
- trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, ret);
+ trace_drv_ampdu_action(local, vif, action, sta, tid, ssn, ret);
return ret;
}
static inline void drv_rfkill_poll(struct ieee80211_local *local)
{
- might_sleep();
-
if (local->ops->rfkill_poll)
local->ops->rfkill_poll(&local->hw);
}
-
-static inline void drv_flush(struct ieee80211_local *local, bool drop)
-{
- might_sleep();
-
- trace_drv_flush(local, drop);
- if (local->ops->flush)
- local->ops->flush(&local->hw, drop);
-}
#endif /* __MAC80211_DRIVER_OPS */
diff --git a/trunk/net/mac80211/driver-trace.h b/trunk/net/mac80211/driver-trace.h
index 41baf730a5c7..da8497ef7063 100644
--- a/trunk/net/mac80211/driver-trace.h
+++ b/trunk/net/mac80211/driver-trace.h
@@ -25,12 +25,10 @@ static inline void trace_ ## name(proto) {}
#define STA_PR_FMT " sta:%pM"
#define STA_PR_ARG __entry->sta_addr
-#define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, sdata) \
- __string(vif_name, sdata->dev ? sdata->dev->name : "")
-#define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \
- __assign_str(vif_name, sdata->dev ? sdata->dev->name : "")
-#define VIF_PR_FMT " vif:%s(%d)"
-#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type
+#define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, vif)
+#define VIF_ASSIGN __entry->vif_type = vif ? vif->type : 0; __entry->vif = vif
+#define VIF_PR_FMT " vif:%p(%d)"
+#define VIF_PR_ARG __entry->vif, __entry->vif_type
TRACE_EVENT(drv_start,
TP_PROTO(struct ieee80211_local *local, int ret),
@@ -72,10 +70,11 @@ TRACE_EVENT(drv_stop,
TRACE_EVENT(drv_add_interface,
TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
+ const u8 *addr,
+ struct ieee80211_vif *vif,
int ret),
- TP_ARGS(local, sdata, ret),
+ TP_ARGS(local, addr, vif, ret),
TP_STRUCT__entry(
LOCAL_ENTRY
@@ -87,7 +86,7 @@ TRACE_EVENT(drv_add_interface,
TP_fast_assign(
LOCAL_ASSIGN;
VIF_ASSIGN;
- memcpy(__entry->addr, sdata->vif.addr, 6);
+ memcpy(__entry->addr, addr, 6);
__entry->ret = ret;
),
@@ -98,9 +97,10 @@ TRACE_EVENT(drv_add_interface,
);
TRACE_EVENT(drv_remove_interface,
- TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata),
+ TP_PROTO(struct ieee80211_local *local,
+ const u8 *addr, struct ieee80211_vif *vif),
- TP_ARGS(local, sdata),
+ TP_ARGS(local, addr, vif),
TP_STRUCT__entry(
LOCAL_ENTRY
@@ -111,7 +111,7 @@ TRACE_EVENT(drv_remove_interface,
TP_fast_assign(
LOCAL_ASSIGN;
VIF_ASSIGN;
- memcpy(__entry->addr, sdata->vif.addr, 6);
+ memcpy(__entry->addr, addr, 6);
),
TP_printk(
@@ -140,7 +140,6 @@ TRACE_EVENT(drv_config,
__field(u8, short_frame_max_tx_count)
__field(int, center_freq)
__field(int, channel_type)
- __field(int, smps)
),
TP_fast_assign(
@@ -156,7 +155,6 @@ TRACE_EVENT(drv_config,
__entry->short_frame_max_tx_count = local->hw.conf.short_frame_max_tx_count;
__entry->center_freq = local->hw.conf.channel->center_freq;
__entry->channel_type = local->hw.conf.channel_type;
- __entry->smps = local->hw.conf.smps_mode;
),
TP_printk(
@@ -167,11 +165,11 @@ TRACE_EVENT(drv_config,
TRACE_EVENT(drv_bss_info_changed,
TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info,
u32 changed),
- TP_ARGS(local, sdata, info, changed),
+ TP_ARGS(local, vif, info, changed),
TP_STRUCT__entry(
LOCAL_ENTRY
@@ -295,11 +293,11 @@ TRACE_EVENT(drv_set_tim,
TRACE_EVENT(drv_set_key,
TP_PROTO(struct ieee80211_local *local,
- enum set_key_cmd cmd, struct ieee80211_sub_if_data *sdata,
+ enum set_key_cmd cmd, struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key, int ret),
- TP_ARGS(local, cmd, sdata, sta, key, ret),
+ TP_ARGS(local, cmd, vif, sta, key, ret),
TP_STRUCT__entry(
LOCAL_ENTRY
@@ -331,29 +329,26 @@ TRACE_EVENT(drv_set_key,
TRACE_EVENT(drv_update_tkip_key,
TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
struct ieee80211_key_conf *conf,
- struct ieee80211_sta *sta, u32 iv32),
+ const u8 *address, u32 iv32),
- TP_ARGS(local, sdata, conf, sta, iv32),
+ TP_ARGS(local, conf, address, iv32),
TP_STRUCT__entry(
LOCAL_ENTRY
- VIF_ENTRY
- STA_ENTRY
+ __array(u8, addr, 6)
__field(u32, iv32)
),
TP_fast_assign(
LOCAL_ASSIGN;
- VIF_ASSIGN;
- STA_ASSIGN;
+ memcpy(__entry->addr, address, 6);
__entry->iv32 = iv32;
),
TP_printk(
- LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " iv32:%#x",
- LOCAL_PR_ARG,VIF_PR_ARG,STA_PR_ARG, __entry->iv32
+ LOCAL_PR_FMT " addr:%pM iv32:%#x",
+ LOCAL_PR_ARG, __entry->addr, __entry->iv32
)
);
@@ -494,36 +489,13 @@ TRACE_EVENT(drv_set_rts_threshold,
)
);
-TRACE_EVENT(drv_set_coverage_class,
- TP_PROTO(struct ieee80211_local *local, u8 value, int ret),
-
- TP_ARGS(local, value, ret),
-
- TP_STRUCT__entry(
- LOCAL_ENTRY
- __field(u8, value)
- __field(int, ret)
- ),
-
- TP_fast_assign(
- LOCAL_ASSIGN;
- __entry->ret = ret;
- __entry->value = value;
- ),
-
- TP_printk(
- LOCAL_PR_FMT " value:%d ret:%d",
- LOCAL_PR_ARG, __entry->value, __entry->ret
- )
-);
-
TRACE_EVENT(drv_sta_notify,
TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_vif *vif,
enum sta_notify_cmd cmd,
struct ieee80211_sta *sta),
- TP_ARGS(local, sdata, cmd, sta),
+ TP_ARGS(local, vif, cmd, sta),
TP_STRUCT__entry(
LOCAL_ENTRY
@@ -545,88 +517,59 @@ TRACE_EVENT(drv_sta_notify,
)
);
-TRACE_EVENT(drv_sta_add,
- TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct ieee80211_sta *sta, int ret),
+TRACE_EVENT(drv_conf_tx,
+ TP_PROTO(struct ieee80211_local *local, u16 queue,
+ const struct ieee80211_tx_queue_params *params,
+ int ret),
- TP_ARGS(local, sdata, sta, ret),
+ TP_ARGS(local, queue, params, ret),
TP_STRUCT__entry(
LOCAL_ENTRY
- VIF_ENTRY
- STA_ENTRY
+ __field(u16, queue)
+ __field(u16, txop)
+ __field(u16, cw_min)
+ __field(u16, cw_max)
+ __field(u8, aifs)
__field(int, ret)
),
TP_fast_assign(
LOCAL_ASSIGN;
- VIF_ASSIGN;
- STA_ASSIGN;
+ __entry->queue = queue;
__entry->ret = ret;
+ __entry->txop = params->txop;
+ __entry->cw_max = params->cw_max;
+ __entry->cw_min = params->cw_min;
+ __entry->aifs = params->aifs;
),
TP_printk(
- LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " ret:%d",
- LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->ret
+ LOCAL_PR_FMT " queue:%d ret:%d",
+ LOCAL_PR_ARG, __entry->queue, __entry->ret
)
);
-TRACE_EVENT(drv_sta_remove,
+TRACE_EVENT(drv_get_tx_stats,
TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct ieee80211_sta *sta),
-
- TP_ARGS(local, sdata, sta),
-
- TP_STRUCT__entry(
- LOCAL_ENTRY
- VIF_ENTRY
- STA_ENTRY
- ),
-
- TP_fast_assign(
- LOCAL_ASSIGN;
- VIF_ASSIGN;
- STA_ASSIGN;
- ),
-
- TP_printk(
- LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT,
- LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG
- )
-);
-
-TRACE_EVENT(drv_conf_tx,
- TP_PROTO(struct ieee80211_local *local, u16 queue,
- const struct ieee80211_tx_queue_params *params,
+ struct ieee80211_tx_queue_stats *stats,
int ret),
- TP_ARGS(local, queue, params, ret),
+ TP_ARGS(local, stats, ret),
TP_STRUCT__entry(
LOCAL_ENTRY
- __field(u16, queue)
- __field(u16, txop)
- __field(u16, cw_min)
- __field(u16, cw_max)
- __field(u8, aifs)
__field(int, ret)
),
TP_fast_assign(
LOCAL_ASSIGN;
- __entry->queue = queue;
__entry->ret = ret;
- __entry->txop = params->txop;
- __entry->cw_max = params->cw_max;
- __entry->cw_min = params->cw_min;
- __entry->aifs = params->aifs;
),
TP_printk(
- LOCAL_PR_FMT " queue:%d ret:%d",
- LOCAL_PR_ARG, __entry->queue, __entry->ret
+ LOCAL_PR_FMT " ret:%d",
+ LOCAL_PR_ARG, __entry->ret
)
);
@@ -713,12 +656,12 @@ TRACE_EVENT(drv_tx_last_beacon,
TRACE_EVENT(drv_ampdu_action,
TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid,
u16 *ssn, int ret),
- TP_ARGS(local, sdata, action, sta, tid, ssn, ret),
+ TP_ARGS(local, vif, action, sta, tid, ssn, ret),
TP_STRUCT__entry(
LOCAL_ENTRY
@@ -745,27 +688,6 @@ TRACE_EVENT(drv_ampdu_action,
LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret
)
);
-
-TRACE_EVENT(drv_flush,
- TP_PROTO(struct ieee80211_local *local, bool drop),
-
- TP_ARGS(local, drop),
-
- TP_STRUCT__entry(
- LOCAL_ENTRY
- __field(bool, drop)
- ),
-
- TP_fast_assign(
- LOCAL_ASSIGN;
- __entry->drop = drop;
- ),
-
- TP_printk(
- LOCAL_PR_FMT " drop:%d",
- LOCAL_PR_ARG, __entry->drop
- )
-);
#endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
#undef TRACE_INCLUDE_PATH
diff --git a/trunk/net/mac80211/ht.c b/trunk/net/mac80211/ht.c
index bb677a73b7c9..d7dcee680728 100644
--- a/trunk/net/mac80211/ht.c
+++ b/trunk/net/mac80211/ht.c
@@ -125,7 +125,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
if (!skb) {
printk(KERN_ERR "%s: failed to allocate buffer "
- "for delba frame\n", sdata->name);
+ "for delba frame\n", sdata->dev->name);
return;
}
@@ -133,10 +133,10 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
memset(mgmt, 0, 24);
memcpy(mgmt->da, da, ETH_ALEN);
- memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+ memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
if (sdata->vif.type == NL80211_IFTYPE_AP ||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
+ memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
else if (sdata->vif.type == NL80211_IFTYPE_STATION)
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
@@ -185,50 +185,3 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
spin_unlock_bh(&sta->lock);
}
}
-
-int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
- enum ieee80211_smps_mode smps, const u8 *da,
- const u8 *bssid)
-{
- struct ieee80211_local *local = sdata->local;
- struct sk_buff *skb;
- struct ieee80211_mgmt *action_frame;
-
- /* 27 = header + category + action + smps mode */
- skb = dev_alloc_skb(27 + local->hw.extra_tx_headroom);
- if (!skb)
- return -ENOMEM;
-
- skb_reserve(skb, local->hw.extra_tx_headroom);
- action_frame = (void *)skb_put(skb, 27);
- memcpy(action_frame->da, da, ETH_ALEN);
- memcpy(action_frame->sa, sdata->dev->dev_addr, ETH_ALEN);
- memcpy(action_frame->bssid, bssid, ETH_ALEN);
- action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
- IEEE80211_STYPE_ACTION);
- action_frame->u.action.category = WLAN_CATEGORY_HT;
- action_frame->u.action.u.ht_smps.action = WLAN_HT_ACTION_SMPS;
- switch (smps) {
- case IEEE80211_SMPS_AUTOMATIC:
- case IEEE80211_SMPS_NUM_MODES:
- WARN_ON(1);
- case IEEE80211_SMPS_OFF:
- action_frame->u.action.u.ht_smps.smps_control =
- WLAN_HT_SMPS_CONTROL_DISABLED;
- break;
- case IEEE80211_SMPS_STATIC:
- action_frame->u.action.u.ht_smps.smps_control =
- WLAN_HT_SMPS_CONTROL_STATIC;
- break;
- case IEEE80211_SMPS_DYNAMIC:
- action_frame->u.action.u.ht_smps.smps_control =
- WLAN_HT_SMPS_CONTROL_DYNAMIC;
- break;
- }
-
- /* we'll do more on status of this frame */
- IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
- ieee80211_tx_skb(sdata, skb);
-
- return 0;
-}
diff --git a/trunk/net/mac80211/ibss.c b/trunk/net/mac80211/ibss.c
index f3e942486749..22f0c2aa7a89 100644
--- a/trunk/net/mac80211/ibss.c
+++ b/trunk/net/mac80211/ibss.c
@@ -117,7 +117,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_PROBE_RESP);
memset(mgmt->da, 0xff, ETH_ALEN);
- memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+ memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN);
mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_int);
mgmt->u.beacon.timestamp = cpu_to_le64(tsf);
@@ -187,17 +187,15 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
struct ieee80211_bss *bss)
{
- struct cfg80211_bss *cbss =
- container_of((void *)bss, struct cfg80211_bss, priv);
struct ieee80211_supported_band *sband;
u32 basic_rates;
int i, j;
- u16 beacon_int = cbss->beacon_interval;
+ u16 beacon_int = bss->cbss.beacon_interval;
if (beacon_int < 10)
beacon_int = 10;
- sband = sdata->local->hw.wiphy->bands[cbss->channel->band];
+ sband = sdata->local->hw.wiphy->bands[bss->cbss.channel->band];
basic_rates = 0;
@@ -214,12 +212,12 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
}
}
- __ieee80211_sta_join_ibss(sdata, cbss->bssid,
+ __ieee80211_sta_join_ibss(sdata, bss->cbss.bssid,
beacon_int,
- cbss->channel,
+ bss->cbss.channel,
basic_rates,
- cbss->capability,
- cbss->tsf);
+ bss->cbss.capability,
+ bss->cbss.tsf);
}
static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
@@ -231,7 +229,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_local *local = sdata->local;
int freq;
- struct cfg80211_bss *cbss;
struct ieee80211_bss *bss;
struct sta_info *sta;
struct ieee80211_channel *channel;
@@ -255,7 +252,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
rcu_read_lock();
- sta = sta_info_get(sdata, mgmt->sa);
+ sta = sta_info_get(local, mgmt->sa);
if (sta) {
u32 prev_rates;
@@ -269,18 +266,16 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
printk(KERN_DEBUG "%s: updated supp_rates set "
"for %pM based on beacon info (0x%llx | "
"0x%llx -> 0x%llx)\n",
- sdata->name,
+ sdata->dev->name,
sta->sta.addr,
(unsigned long long) prev_rates,
(unsigned long long) supp_rates,
(unsigned long long) sta->sta.supp_rates[band]);
#endif
- rcu_read_unlock();
- } else {
- rcu_read_unlock();
- ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
- supp_rates, GFP_KERNEL);
- }
+ } else
+ ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates);
+
+ rcu_read_unlock();
}
bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems,
@@ -288,23 +283,25 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
if (!bss)
return;
- cbss = container_of((void *)bss, struct cfg80211_bss, priv);
-
/* was just updated in ieee80211_bss_info_update */
- beacon_timestamp = cbss->tsf;
+ beacon_timestamp = bss->cbss.tsf;
/* check if we need to merge IBSS */
+ /* merge only on beacons (???) */
+ if (!beacon)
+ goto put_bss;
+
/* we use a fixed BSSID */
- if (sdata->u.ibss.fixed_bssid)
+ if (sdata->u.ibss.bssid)
goto put_bss;
/* not an IBSS */
- if (!(cbss->capability & WLAN_CAPABILITY_IBSS))
+ if (!(bss->cbss.capability & WLAN_CAPABILITY_IBSS))
goto put_bss;
/* different channel */
- if (cbss->channel != local->oper_channel)
+ if (bss->cbss.channel != local->oper_channel)
goto put_bss;
/* different SSID */
@@ -314,7 +311,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
goto put_bss;
/* same BSSID */
- if (memcmp(cbss->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0)
+ if (memcmp(bss->cbss.bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0)
goto put_bss;
if (rx_status->flag & RX_FLAG_TSFT) {
@@ -367,11 +364,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
#ifdef CONFIG_MAC80211_IBSS_DEBUG
printk(KERN_DEBUG "%s: beacon TSF higher than "
"local TSF - IBSS merge with BSSID %pM\n",
- sdata->name, mgmt->bssid);
+ sdata->dev->name, mgmt->bssid);
#endif
ieee80211_sta_join_ibss(sdata, bss);
- ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
- supp_rates, GFP_KERNEL);
+ ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates);
}
put_bss:
@@ -384,8 +380,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
* must be callable in atomic context.
*/
struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
- u8 *bssid,u8 *addr, u32 supp_rates,
- gfp_t gfp)
+ u8 *bssid,u8 *addr, u32 supp_rates)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;
@@ -399,7 +394,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
if (net_ratelimit())
printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n",
- sdata->name, addr);
+ sdata->dev->name, addr);
return NULL;
}
@@ -411,10 +406,10 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: Adding new IBSS station %pM (dev=%s)\n",
- wiphy_name(local->hw.wiphy), addr, sdata->name);
+ wiphy_name(local->hw.wiphy), addr, sdata->dev->name);
#endif
- sta = sta_info_alloc(sdata, addr, gfp);
+ sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
if (!sta)
return NULL;
@@ -426,9 +421,9 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
rate_control_rate_init(sta);
- /* If it fails, maybe we raced another insertion? */
if (sta_info_insert(sta))
- return sta_info_get(sdata, addr);
+ return NULL;
+
return sta;
}
@@ -454,9 +449,6 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
return active;
}
-/*
- * This function is called with state == IEEE80211_IBSS_MLME_JOINED
- */
static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
{
@@ -478,7 +470,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
return;
printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
- "IBSS networks with same SSID (merge)\n", sdata->name);
+ "IBSS networks with same SSID (merge)\n", sdata->dev->name);
ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len);
}
@@ -500,13 +492,13 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
* random number generator get different BSSID. */
get_random_bytes(bssid, ETH_ALEN);
for (i = 0; i < ETH_ALEN; i++)
- bssid[i] ^= sdata->vif.addr[i];
+ bssid[i] ^= sdata->dev->dev_addr[i];
bssid[0] &= ~0x01;
bssid[0] |= 0x02;
}
printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n",
- sdata->name, bssid);
+ sdata->dev->name, bssid);
sband = local->hw.wiphy->bands[ifibss->channel->band];
@@ -522,15 +514,11 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
capability, 0);
}
-/*
- * This function is called with state == IEEE80211_IBSS_MLME_SEARCH
- */
-
static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;
- struct cfg80211_bss *cbss;
+ struct ieee80211_bss *bss;
struct ieee80211_channel *chan = NULL;
const u8 *bssid = NULL;
int active_ibss;
@@ -539,7 +527,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
active_ibss = ieee80211_sta_active_ibss(sdata);
#ifdef CONFIG_MAC80211_IBSS_DEBUG
printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
- sdata->name, active_ibss);
+ sdata->dev->name, active_ibss);
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
if (active_ibss)
@@ -554,23 +542,21 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
chan = ifibss->channel;
if (!is_zero_ether_addr(ifibss->bssid))
bssid = ifibss->bssid;
- cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid,
- ifibss->ssid, ifibss->ssid_len,
- WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_PRIVACY,
- capability);
-
- if (cbss) {
- struct ieee80211_bss *bss;
+ bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan, bssid,
+ ifibss->ssid, ifibss->ssid_len,
+ WLAN_CAPABILITY_IBSS |
+ WLAN_CAPABILITY_PRIVACY,
+ capability);
- bss = (void *)cbss->priv;
+ if (bss) {
#ifdef CONFIG_MAC80211_IBSS_DEBUG
printk(KERN_DEBUG " sta_find_ibss: selected %pM current "
- "%pM\n", cbss->bssid, ifibss->bssid);
+ "%pM\n", bss->cbss.bssid, ifibss->bssid);
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM"
" based on configured SSID\n",
- sdata->name, cbss->bssid);
+ sdata->dev->name, bss->cbss.bssid);
ieee80211_sta_join_ibss(sdata, bss);
ieee80211_rx_bss_put(local, bss);
@@ -582,14 +568,18 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
/* Selected IBSS not found in current scan results - try to scan */
- if (time_after(jiffies, ifibss->last_scan_completed +
+ if (ifibss->state == IEEE80211_IBSS_MLME_JOINED &&
+ !ieee80211_sta_active_ibss(sdata)) {
+ mod_timer(&ifibss->timer,
+ round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
+ } else if (time_after(jiffies, ifibss->last_scan_completed +
IEEE80211_SCAN_INTERVAL)) {
printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
- "join\n", sdata->name);
+ "join\n", sdata->dev->name);
ieee80211_request_internal_scan(sdata, ifibss->ssid,
ifibss->ssid_len);
- } else {
+ } else if (ifibss->state != IEEE80211_IBSS_MLME_JOINED) {
int interval = IEEE80211_SCAN_INTERVAL;
if (time_after(jiffies, ifibss->ibss_join_req +
@@ -599,7 +589,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
return;
}
printk(KERN_DEBUG "%s: IBSS not allowed on"
- " %d MHz\n", sdata->name,
+ " %d MHz\n", sdata->dev->name,
local->hw.conf.channel->center_freq);
/* No IBSS found - decrease scan interval and continue
@@ -607,6 +597,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
interval = IEEE80211_SCAN_INTERVAL_SLOW;
}
+ ifibss->state = IEEE80211_IBSS_MLME_SEARCH;
mod_timer(&ifibss->timer,
round_jiffies(jiffies + interval));
}
@@ -632,7 +623,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
#ifdef CONFIG_MAC80211_IBSS_DEBUG
printk(KERN_DEBUG "%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM"
" (tx_last_beacon=%d)\n",
- sdata->name, mgmt->sa, mgmt->da,
+ sdata->dev->name, mgmt->sa, mgmt->da,
mgmt->bssid, tx_last_beacon);
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
@@ -650,7 +641,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
#ifdef CONFIG_MAC80211_IBSS_DEBUG
printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq "
"from %pM\n",
- sdata->name, mgmt->sa);
+ sdata->dev->name, mgmt->sa);
#endif
return;
}
@@ -670,7 +661,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
memcpy(resp->da, mgmt->sa, ETH_ALEN);
#ifdef CONFIG_MAC80211_IBSS_DEBUG
printk(KERN_DEBUG "%s: Sending ProbeResp to %pM\n",
- sdata->name, resp->da);
+ sdata->dev->name, resp->da);
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
ieee80211_tx_skb(sdata, skb);
@@ -684,7 +675,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
size_t baselen;
struct ieee802_11_elems elems;
- if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN))
+ if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
return; /* ignore ProbeResp to foreign address */
baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
@@ -757,7 +748,7 @@ static void ieee80211_ibss_work(struct work_struct *work)
if (WARN_ON(local->suspended))
return;
- if (!ieee80211_sdata_running(sdata))
+ if (!netif_running(sdata->dev))
return;
if (local->scanning)
@@ -840,7 +831,7 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
mutex_lock(&local->iflist_mtx);
list_for_each_entry(sdata, &local->interfaces, list) {
- if (!ieee80211_sdata_running(sdata))
+ if (!netif_running(sdata->dev))
continue;
if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
continue;
diff --git a/trunk/net/mac80211/ieee80211_i.h b/trunk/net/mac80211/ieee80211_i.h
index 241533e1bc03..91dc8636d644 100644
--- a/trunk/net/mac80211/ieee80211_i.h
+++ b/trunk/net/mac80211/ieee80211_i.h
@@ -2,7 +2,7 @@
* Copyright 2002-2005, Instant802 Networks, Inc.
* Copyright 2005, Devicescape Software, Inc.
* Copyright 2006-2007 Jiri Benc
- * Copyright 2007-2010 Johannes Berg
+ * Copyright 2007-2008 Johannes Berg
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -58,15 +58,6 @@ struct ieee80211_local;
#define TU_TO_EXP_TIME(x) (jiffies + usecs_to_jiffies((x) * 1024))
-#define IEEE80211_DEFAULT_UAPSD_QUEUES \
- (IEEE80211_WMM_IE_STA_QOSINFO_AC_BK | \
- IEEE80211_WMM_IE_STA_QOSINFO_AC_BE | \
- IEEE80211_WMM_IE_STA_QOSINFO_AC_VI | \
- IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
-
-#define IEEE80211_DEFAULT_MAX_SP_LEN \
- IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL
-
struct ieee80211_fragment_entry {
unsigned long first_frag_time;
unsigned int seq;
@@ -80,6 +71,9 @@ struct ieee80211_fragment_entry {
struct ieee80211_bss {
+ /* Yes, this is a hack */
+ struct cfg80211_bss cbss;
+
/* don't want to look up all the time */
size_t ssid_len;
u8 ssid[IEEE80211_MAX_SSID_LEN];
@@ -87,7 +81,6 @@ struct ieee80211_bss {
u8 dtim_period;
bool wmm_used;
- bool uapsd_supported;
unsigned long last_probe_resp;
@@ -147,6 +140,7 @@ typedef unsigned __bitwise__ ieee80211_tx_result;
struct ieee80211_tx_data {
struct sk_buff *skb;
+ struct net_device *dev;
struct ieee80211_local *local;
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
@@ -234,77 +228,31 @@ struct mesh_preq_queue {
u8 flags;
};
-enum ieee80211_work_type {
- IEEE80211_WORK_ABORT,
- IEEE80211_WORK_DIRECT_PROBE,
- IEEE80211_WORK_AUTH,
- IEEE80211_WORK_ASSOC,
- IEEE80211_WORK_REMAIN_ON_CHANNEL,
+enum ieee80211_mgd_state {
+ IEEE80211_MGD_STATE_IDLE,
+ IEEE80211_MGD_STATE_PROBE,
+ IEEE80211_MGD_STATE_AUTH,
+ IEEE80211_MGD_STATE_ASSOC,
};
-/**
- * enum work_done_result - indicates what to do after work was done
- *
- * @WORK_DONE_DESTROY: This work item is no longer needed, destroy.
- * @WORK_DONE_REQUEUE: This work item was reset to be reused, and
- * should be requeued.
- */
-enum work_done_result {
- WORK_DONE_DESTROY,
- WORK_DONE_REQUEUE,
-};
-
-struct ieee80211_work {
+struct ieee80211_mgd_work {
struct list_head list;
-
- struct rcu_head rcu_head;
-
- struct ieee80211_sub_if_data *sdata;
-
- enum work_done_result (*done)(struct ieee80211_work *wk,
- struct sk_buff *skb);
-
- struct ieee80211_channel *chan;
- enum nl80211_channel_type chan_type;
-
+ struct ieee80211_bss *bss;
+ int ie_len;
+ u8 prev_bssid[ETH_ALEN];
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+ u8 ssid_len;
unsigned long timeout;
- enum ieee80211_work_type type;
-
- u8 filter_ta[ETH_ALEN];
+ enum ieee80211_mgd_state state;
+ u16 auth_alg, auth_transaction;
- bool started;
+ int tries;
- union {
- struct {
- int tries;
- u16 algorithm, transaction;
- u8 ssid[IEEE80211_MAX_SSID_LEN];
- u8 ssid_len;
- u8 key[WLAN_KEY_LEN_WEP104];
- u8 key_len, key_idx;
- bool privacy;
- } probe_auth;
- struct {
- struct cfg80211_bss *bss;
- const u8 *supp_rates;
- const u8 *ht_information_ie;
- enum ieee80211_smps_mode smps;
- int tries;
- u16 capability;
- u8 prev_bssid[ETH_ALEN];
- u8 ssid[IEEE80211_MAX_SSID_LEN];
- u8 ssid_len;
- u8 supp_rates_len;
- bool wmm_used, use_11n, uapsd_used;
- } assoc;
- struct {
- u32 duration;
- } remain;
- };
+ u8 key[WLAN_KEY_LEN_WEP104];
+ u8 key_len, key_idx;
- int ie_len;
/* must be last */
- u8 ie[0];
+ u8 ie[0]; /* for auth or assoc frame, not probe */
};
/* flags used in struct ieee80211_if_managed.flags */
@@ -312,11 +260,15 @@ enum ieee80211_sta_flags {
IEEE80211_STA_BEACON_POLL = BIT(0),
IEEE80211_STA_CONNECTION_POLL = BIT(1),
IEEE80211_STA_CONTROL_PORT = BIT(2),
+ IEEE80211_STA_WMM_ENABLED = BIT(3),
IEEE80211_STA_DISABLE_11N = BIT(4),
IEEE80211_STA_CSA_RECEIVED = BIT(5),
IEEE80211_STA_MFP_ENABLED = BIT(6),
- IEEE80211_STA_UAPSD_ENABLED = BIT(7),
- IEEE80211_STA_NULLFUNC_ACKED = BIT(8),
+};
+
+/* flags for MLME request */
+enum ieee80211_sta_request {
+ IEEE80211_STA_REQ_SCAN,
};
struct ieee80211_if_managed {
@@ -333,18 +285,21 @@ struct ieee80211_if_managed {
int probe_send_count;
struct mutex mtx;
- struct cfg80211_bss *associated;
+ struct ieee80211_bss *associated;
+ struct ieee80211_mgd_work *old_associate_work;
+ struct list_head work_list;
u8 bssid[ETH_ALEN];
u16 aid;
+ u16 capab;
struct sk_buff_head skb_queue;
unsigned long timers_running; /* used for quiesce/restart */
bool powersave; /* powersave requested for this iface */
- enum ieee80211_smps_mode req_smps, /* requested smps mode */
- ap_smps; /* smps mode AP thinks we're in */
+
+ unsigned long request;
unsigned int flags;
@@ -478,8 +433,6 @@ struct ieee80211_sub_if_data {
int drop_unencrypted;
- char name[IFNAMSIZ];
-
/*
* keep track of whether the HT opmode (stored in
* vif.bss_info.ht_operation_mode) is valid.
@@ -505,8 +458,8 @@ struct ieee80211_sub_if_data {
*/
struct ieee80211_if_ap *bss;
- /* bitmap of allowed (non-MCS) rate indexes for rate control */
- u32 rc_rateidx_mask[IEEE80211_NUM_BANDS];
+ int force_unicast_rateidx; /* forced TX rateidx for unicast frames */
+ int max_ratectrl_rateidx; /* max TX rateidx for rate control */
union {
struct ieee80211_if_ap ap;
@@ -611,15 +564,6 @@ struct ieee80211_local {
const struct ieee80211_ops *ops;
- /*
- * work stuff, potentially off-channel (in the future)
- */
- struct mutex work_mtx;
- struct list_head work_list;
- struct timer_list work_timer;
- struct work_struct work_work;
- struct sk_buff_head work_skb_queue;
-
/*
* private workqueue to mac80211. mac80211 makes this accessible
* via ieee80211_queue_work()
@@ -642,9 +586,6 @@ struct ieee80211_local {
/* used for uploading changed mc list */
struct work_struct reconfig_filter;
- /* used to reconfigure hardware SM PS */
- struct work_struct recalc_smps;
-
/* aggregated multicast list */
struct dev_addr_list *mc_list;
int mc_count;
@@ -689,18 +630,15 @@ struct ieee80211_local {
/* Station data */
/*
- * The mutex only protects the list and counter,
- * reads are done in RCU.
- * Additionally, the lock protects the hash table,
- * the pending list and each BSS's TIM bitmap.
+ * The lock only protects the list, hash, timer and counter
+ * against manipulation, reads are done in RCU. Additionally,
+ * the lock protects each BSS's TIM bitmap.
*/
- struct mutex sta_mtx;
spinlock_t sta_lock;
unsigned long num_sta;
- struct list_head sta_list, sta_pending_list;
+ struct list_head sta_list;
struct sta_info *sta_hash[STA_HASH_SIZE];
struct timer_list sta_cleanup;
- struct work_struct sta_finish_work;
int sta_generation;
struct sk_buff_head pending[IEEE80211_MAX_QUEUES];
@@ -751,10 +689,6 @@ struct ieee80211_local {
enum nl80211_channel_type oper_channel_type;
struct ieee80211_channel *oper_channel, *csa_channel;
- /* Temporary remain-on-channel for off-channel operations */
- struct ieee80211_channel *tmp_channel;
- enum nl80211_channel_type tmp_channel_type;
-
/* SNMP counters */
/* dot11CountersTable */
u32 dot11TransmittedFragmentCount;
@@ -774,6 +708,10 @@ struct ieee80211_local {
assoc_led_name[32], radio_led_name[32];
#endif
+#ifdef CONFIG_MAC80211_DEBUGFS
+ struct work_struct sta_debugfs_add;
+#endif
+
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
/* TX/RX handler statistics */
unsigned int tx_handlers_drop;
@@ -807,22 +745,8 @@ struct ieee80211_local {
int wifi_wme_noack_test;
unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
- /*
- * Bitmask of enabled u-apsd queues,
- * IEEE80211_WMM_IE_STA_QOSINFO_AC_BE & co. Needs a new association
- * to take effect.
- */
- unsigned int uapsd_queues;
-
- /*
- * Maximum number of buffered frames AP can deliver during a
- * service period, IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL or similar.
- * Needs a new association to take effect.
- */
- unsigned int uapsd_max_sp_len;
-
bool pspolling;
- bool offchannel_ps_enabled;
+ bool scan_ps_enabled;
/*
* PS can only be enabled when we have exactly one managed
* interface (and monitors) in PS, this then points there.
@@ -836,8 +760,6 @@ struct ieee80211_local {
int user_power_level; /* in dBm */
int power_constr_level; /* in dBm */
- enum ieee80211_smps_mode smps_mode;
-
struct work_struct restart_work;
#ifdef CONFIG_MAC80211_DEBUGFS
@@ -952,8 +874,6 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
void ieee80211_configure_filter(struct ieee80211_local *local);
u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata);
-extern bool ieee80211_disable_40mhz_24ghz;
-
/* STA code */
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata);
int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
@@ -966,10 +886,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
struct cfg80211_disassoc_request *req,
void *cookie);
-int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- const u8 *buf, size_t len, u64 *cookie);
ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
void ieee80211_send_pspoll(struct ieee80211_local *local,
@@ -989,8 +905,7 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata);
ieee80211_rx_result
ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
- u8 *bssid, u8 *addr, u32 supp_rates,
- gfp_t gfp);
+ u8 *bssid, u8 *addr, u32 supp_rates);
int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
struct cfg80211_ibss_params *params);
int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata);
@@ -1022,15 +937,7 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
void ieee80211_rx_bss_put(struct ieee80211_local *local,
struct ieee80211_bss *bss);
-/* off-channel helpers */
-void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local);
-void ieee80211_offchannel_stop_station(struct ieee80211_local *local);
-void ieee80211_offchannel_return(struct ieee80211_local *local,
- bool enable_beaconing);
-
/* interface handling */
-int ieee80211_iface_init(void);
-void ieee80211_iface_exit(void);
int ieee80211_if_add(struct ieee80211_local *local, const char *name,
struct net_device **new_dev, enum nl80211_iftype type,
struct vif_params *params);
@@ -1041,11 +948,6 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local);
u32 __ieee80211_recalc_idle(struct ieee80211_local *local);
void ieee80211_recalc_idle(struct ieee80211_local *local);
-static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
-{
- return netif_running(sdata->dev);
-}
-
/* tx handling */
void ieee80211_clear_tx_pending(struct ieee80211_local *local);
void ieee80211_tx_pending(unsigned long data);
@@ -1074,9 +976,6 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1
void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
const u8 *da, u16 tid,
u16 initiator, u16 reason_code);
-int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
- enum ieee80211_smps_mode smps, const u8 *da,
- const u8 *bssid);
void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da,
u16 tid, u16 initiator, u16 reason);
@@ -1187,28 +1086,6 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
struct ieee802_11_elems *elems,
enum ieee80211_band band);
-int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
- enum ieee80211_smps_mode smps_mode);
-void ieee80211_recalc_smps(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *forsdata);
-
-size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
- const u8 *ids, int n_ids, size_t offset);
-size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
-
-/* internal work items */
-void ieee80211_work_init(struct ieee80211_local *local);
-void ieee80211_add_work(struct ieee80211_work *wk);
-void free_work(struct ieee80211_work *wk);
-void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata);
-ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb);
-int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- unsigned int duration, u64 *cookie);
-int ieee80211_wk_cancel_remain_on_channel(
- struct ieee80211_sub_if_data *sdata, u64 cookie);
#ifdef CONFIG_MAC80211_NOINLINE
#define debug_noinline noinline
diff --git a/trunk/net/mac80211/iface.c b/trunk/net/mac80211/iface.c
index 0793d7a8d743..32abae3ce32a 100644
--- a/trunk/net/mac80211/iface.c
+++ b/trunk/net/mac80211/iface.c
@@ -62,23 +62,6 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
-static int ieee80211_change_mac(struct net_device *dev, void *addr)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct sockaddr *sa = addr;
- int ret;
-
- if (ieee80211_sdata_running(sdata))
- return -EBUSY;
-
- ret = eth_mac_addr(dev, sa);
-
- if (ret == 0)
- memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
-
- return ret;
-}
-
static inline int identical_mac_addr_allowed(int type1, int type2)
{
return type1 == NL80211_IFTYPE_MONITOR ||
@@ -99,6 +82,7 @@ static int ieee80211_open(struct net_device *dev)
struct ieee80211_sub_if_data *nsdata;
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
+ struct ieee80211_if_init_conf conf;
u32 changed = 0;
int res;
u32 hw_reconf_flags = 0;
@@ -113,7 +97,7 @@ static int ieee80211_open(struct net_device *dev)
list_for_each_entry(nsdata, &local->interfaces, list) {
struct net_device *ndev = nsdata->dev;
- if (ndev != dev && ieee80211_sdata_running(nsdata)) {
+ if (ndev != dev && netif_running(ndev)) {
/*
* Allow only a single IBSS interface to be up at any
* time. This is restricted because beacon distribution
@@ -199,7 +183,7 @@ static int ieee80211_open(struct net_device *dev)
struct net_device *ndev = nsdata->dev;
/*
- * No need to check running since we do not allow
+ * No need to check netif_running since we do not allow
* it to start up with this invalid address.
*/
if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) {
@@ -250,7 +234,10 @@ static int ieee80211_open(struct net_device *dev)
ieee80211_configure_filter(local);
break;
default:
- res = drv_add_interface(local, &sdata->vif);
+ conf.vif = &sdata->vif;
+ conf.type = sdata->vif.type;
+ conf.mac_addr = dev->dev_addr;
+ res = drv_add_interface(local, &conf);
if (res)
goto err_stop;
@@ -333,7 +320,7 @@ static int ieee80211_open(struct net_device *dev)
return 0;
err_del_interface:
- drv_remove_interface(local, &sdata->vif);
+ drv_remove_interface(local, &conf);
err_stop:
if (!local->open_count)
drv_stop(local);
@@ -348,6 +335,7 @@ static int ieee80211_stop(struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
+ struct ieee80211_if_init_conf conf;
struct sta_info *sta;
unsigned long flags;
struct sk_buff *skb, *tmp;
@@ -359,11 +347,6 @@ static int ieee80211_stop(struct net_device *dev)
*/
netif_tx_stop_all_queues(dev);
- /*
- * Purge work for this interface.
- */
- ieee80211_work_purge(sdata);
-
/*
* Now delete all active aggregation sessions.
*/
@@ -531,9 +514,12 @@ static int ieee80211_stop(struct net_device *dev)
BSS_CHANGED_BEACON_ENABLED);
}
+ conf.vif = &sdata->vif;
+ conf.type = sdata->vif.type;
+ conf.mac_addr = dev->dev_addr;
/* disable all keys for as long as this netdev is down */
ieee80211_disable_keys(sdata);
- drv_remove_interface(local, &sdata->vif);
+ drv_remove_interface(local, &conf);
}
sdata->bss = NULL;
@@ -673,7 +659,7 @@ static const struct net_device_ops ieee80211_dataif_ops = {
.ndo_start_xmit = ieee80211_subif_start_xmit,
.ndo_set_multicast_list = ieee80211_set_multicast_list,
.ndo_change_mtu = ieee80211_change_mtu,
- .ndo_set_mac_address = ieee80211_change_mac,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_select_queue = ieee80211_netdev_select_queue,
};
@@ -695,12 +681,8 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev,
hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
- if (!ieee80211_is_data(hdr->frame_control)) {
- skb->priority = 7;
- return ieee802_1d_to_ac[skb->priority];
- }
if (!ieee80211_is_data_qos(hdr->frame_control)) {
- skb->priority = 0;
+ skb->priority = 7;
return ieee802_1d_to_ac[skb->priority];
}
@@ -797,7 +779,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
* and goes into the requested mode.
*/
- if (ieee80211_sdata_running(sdata))
+ if (netif_running(sdata->dev))
return -EBUSY;
/* Purge and reset type-dependent state. */
@@ -851,8 +833,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
/* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */
sdata = netdev_priv(ndev);
ndev->ieee80211_ptr = &sdata->wdev;
- memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN);
- memcpy(sdata->name, ndev->name, IFNAMSIZ);
/* initialise type-independent data */
sdata->wdev.wiphy = local->hw.wiphy;
@@ -864,12 +844,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
INIT_LIST_HEAD(&sdata->key_list);
- for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
- struct ieee80211_supported_band *sband;
- sband = local->hw.wiphy->bands[i];
- sdata->rc_rateidx_mask[i] =
- sband ? (1 << sband->n_bitrates) - 1 : 0;
- }
+ sdata->force_unicast_rateidx = -1;
+ sdata->max_ratectrl_rateidx = -1;
/* setup type-dependent data */
ieee80211_setup_sdata(sdata, type);
@@ -962,8 +938,6 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local)
wiphy_name(local->hw.wiphy));
#endif
- drv_flush(local, false);
-
local->hw.conf.flags |= IEEE80211_CONF_IDLE;
return IEEE80211_CONF_CHANGE_IDLE;
}
@@ -973,18 +947,16 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
struct ieee80211_sub_if_data *sdata;
int count = 0;
- if (!list_empty(&local->work_list))
- return ieee80211_idle_off(local, "working");
-
if (local->scanning)
return ieee80211_idle_off(local, "scanning");
list_for_each_entry(sdata, &local->interfaces, list) {
- if (!ieee80211_sdata_running(sdata))
+ if (!netif_running(sdata->dev))
continue;
/* do not count disabled managed interfaces */
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
- !sdata->u.mgd.associated)
+ !sdata->u.mgd.associated &&
+ list_empty(&sdata->u.mgd.work_list))
continue;
/* do not count unused IBSS interfaces */
if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
@@ -1012,41 +984,3 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)
if (chg)
ieee80211_hw_config(local, chg);
}
-
-static int netdev_notify(struct notifier_block *nb,
- unsigned long state,
- void *ndev)
-{
- struct net_device *dev = ndev;
- struct ieee80211_sub_if_data *sdata;
-
- if (state != NETDEV_CHANGENAME)
- return 0;
-
- if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
- return 0;
-
- if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
- return 0;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- memcpy(sdata->name, dev->name, IFNAMSIZ);
-
- ieee80211_debugfs_rename_netdev(sdata);
- return 0;
-}
-
-static struct notifier_block mac80211_netdev_notifier = {
- .notifier_call = netdev_notify,
-};
-
-int ieee80211_iface_init(void)
-{
- return register_netdevice_notifier(&mac80211_netdev_notifier);
-}
-
-void ieee80211_iface_exit(void)
-{
- unregister_netdevice_notifier(&mac80211_netdev_notifier);
-}
diff --git a/trunk/net/mac80211/key.c b/trunk/net/mac80211/key.c
index 8160d9c5372e..659a42d529e3 100644
--- a/trunk/net/mac80211/key.c
+++ b/trunk/net/mac80211/key.c
@@ -139,7 +139,7 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
struct ieee80211_sub_if_data,
u.ap);
- ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf);
+ ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf);
if (!ret) {
spin_lock_bh(&todo_lock);
@@ -181,7 +181,7 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
struct ieee80211_sub_if_data,
u.ap);
- ret = drv_set_key(key->local, DISABLE_KEY, sdata,
+ ret = drv_set_key(key->local, DISABLE_KEY, &sdata->vif,
sta, &key->conf);
if (ret)
@@ -421,7 +421,7 @@ void ieee80211_key_link(struct ieee80211_key *key,
*/
/* same here, the AP could be using QoS */
- ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid);
+ ap = sta_info_get(key->local, key->sdata->u.mgd.bssid);
if (ap) {
if (test_sta_flags(ap, WLAN_STA_WME))
key->conf.flags |=
@@ -443,7 +443,7 @@ void ieee80211_key_link(struct ieee80211_key *key,
add_todo(old_key, KEY_FLAG_TODO_DELETE);
add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS);
- if (ieee80211_sdata_running(sdata))
+ if (netif_running(sdata->dev))
add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD);
spin_unlock_irqrestore(&sdata->local->key_lock, flags);
@@ -509,7 +509,7 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
{
ASSERT_RTNL();
- if (WARN_ON(!ieee80211_sdata_running(sdata)))
+ if (WARN_ON(!netif_running(sdata->dev)))
return;
ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD);
diff --git a/trunk/net/mac80211/key.h b/trunk/net/mac80211/key.h
index bdc2968c2bbe..a49f93b79e92 100644
--- a/trunk/net/mac80211/key.h
+++ b/trunk/net/mac80211/key.h
@@ -59,17 +59,11 @@ enum ieee80211_internal_key_flags {
KEY_FLAG_TODO_DEFMGMTKEY = BIT(6),
};
-enum ieee80211_internal_tkip_state {
- TKIP_STATE_NOT_INIT,
- TKIP_STATE_PHASE1_DONE,
- TKIP_STATE_PHASE1_HW_UPLOADED,
-};
-
struct tkip_ctx {
u32 iv32;
u16 iv16;
u16 p1k[5];
- enum ieee80211_internal_tkip_state state;
+ int initialized;
};
struct ieee80211_key {
diff --git a/trunk/net/mac80211/main.c b/trunk/net/mac80211/main.c
index ec8f767ba95b..0d2d94881f1f 100644
--- a/trunk/net/mac80211/main.c
+++ b/trunk/net/mac80211/main.c
@@ -17,6 +17,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -31,12 +32,7 @@
#include "led.h"
#include "cfg.h"
#include "debugfs.h"
-
-
-bool ieee80211_disable_40mhz_24ghz;
-module_param(ieee80211_disable_40mhz_24ghz, bool, 0644);
-MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz,
- "Disable 40MHz support in the 2.4GHz band");
+#include "debugfs_netdev.h"
void ieee80211_configure_filter(struct ieee80211_local *local)
{
@@ -106,9 +102,6 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
if (scan_chan) {
chan = scan_chan;
channel_type = NL80211_CHAN_NO_HT;
- } else if (local->tmp_channel) {
- chan = scan_chan = local->tmp_channel;
- channel_type = local->tmp_channel_type;
} else {
chan = local->oper_channel;
channel_type = local->oper_channel_type;
@@ -121,18 +114,6 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
changed |= IEEE80211_CONF_CHANGE_CHANNEL;
}
- if (!conf_is_ht(&local->hw.conf)) {
- /*
- * mac80211.h documents that this is only valid
- * when the channel is set to an HT type, and
- * that otherwise STATIC is used.
- */
- local->hw.conf.smps_mode = IEEE80211_SMPS_STATIC;
- } else if (local->hw.conf.smps_mode != local->smps_mode) {
- local->hw.conf.smps_mode = local->smps_mode;
- changed |= IEEE80211_CONF_CHANGE_SMPS;
- }
-
if (scan_chan)
power = chan->max_power;
else
@@ -192,7 +173,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
else if (sdata->vif.type == NL80211_IFTYPE_AP)
- sdata->vif.bss_conf.bssid = sdata->vif.addr;
+ sdata->vif.bss_conf.bssid = sdata->dev->dev_addr;
else if (ieee80211_vif_is_mesh(&sdata->vif)) {
sdata->vif.bss_conf.bssid = zero;
} else {
@@ -214,7 +195,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
}
if (changed & BSS_CHANGED_BEACON_ENABLED) {
- if (local->quiescing || !ieee80211_sdata_running(sdata) ||
+ if (local->quiescing || !netif_running(sdata->dev) ||
test_bit(SCAN_SW_SCANNING, &local->scanning)) {
sdata->vif.bss_conf.enable_beacon = false;
} else {
@@ -242,7 +223,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
}
}
- drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed);
+ drv_bss_info_changed(local, &sdata->vif,
+ &sdata->vif.bss_conf, changed);
}
u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
@@ -317,16 +299,6 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
}
EXPORT_SYMBOL(ieee80211_restart_hw);
-static void ieee80211_recalc_smps_work(struct work_struct *work)
-{
- struct ieee80211_local *local =
- container_of(work, struct ieee80211_local, recalc_smps);
-
- mutex_lock(&local->iflist_mtx);
- ieee80211_recalc_smps(local, NULL);
- mutex_unlock(&local->iflist_mtx);
-}
-
struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
const struct ieee80211_ops *ops)
{
@@ -361,7 +333,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
WIPHY_FLAG_4ADDR_STATION;
wiphy->privid = mac80211_wiphy_privid;
- wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
+ /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */
+ wiphy->bss_priv_size = sizeof(struct ieee80211_bss) -
+ sizeof(struct cfg80211_bss);
local = wiphy_priv(wiphy);
@@ -384,8 +358,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
local->user_power_level = -1;
- local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
- local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
INIT_LIST_HEAD(&local->interfaces);
mutex_init(&local->iflist_mtx);
@@ -397,13 +369,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
- ieee80211_work_init(local);
-
INIT_WORK(&local->restart_work, ieee80211_restart_work);
INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
- INIT_WORK(&local->recalc_smps, ieee80211_recalc_smps_work);
- local->smps_mode = IEEE80211_SMPS_OFF;
INIT_WORK(&local->dynamic_ps_enable_work,
ieee80211_dynamic_ps_enable_work);
@@ -493,10 +461,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;
- WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)
- && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK),
- "U-APSD not supported with HW_PS_NULLFUNC_STACK\n");
-
/*
* Calculate scan IE length -- we need this to alloc
* memory and to subtract from the driver limit. It
@@ -710,19 +674,11 @@ static int __init ieee80211_init(void)
ret = rc80211_pid_init();
if (ret)
- goto err_pid;
+ return ret;
- ret = ieee80211_iface_init();
- if (ret)
- goto err_netdev;
+ ieee80211_debugfs_netdev_init();
return 0;
- err_netdev:
- rc80211_pid_exit();
- err_pid:
- rc80211_minstrel_exit();
-
- return ret;
}
static void __exit ieee80211_exit(void)
@@ -739,7 +695,7 @@ static void __exit ieee80211_exit(void)
if (mesh_allocated)
ieee80211s_stop();
- ieee80211_iface_exit();
+ ieee80211_debugfs_netdev_exit();
}
diff --git a/trunk/net/mac80211/mesh.c b/trunk/net/mac80211/mesh.c
index 61080c5fad50..6a4331429598 100644
--- a/trunk/net/mac80211/mesh.c
+++ b/trunk/net/mac80211/mesh.c
@@ -457,7 +457,7 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: running mesh housekeeping\n",
- sdata->name);
+ sdata->dev->name);
#endif
ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT);
@@ -565,7 +565,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
/* ignore ProbeResp to foreign address */
if (stype == IEEE80211_STYPE_PROBE_RESP &&
- compare_ether_addr(mgmt->da, sdata->vif.addr))
+ compare_ether_addr(mgmt->da, sdata->dev->dev_addr))
return;
baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
@@ -645,7 +645,7 @@ static void ieee80211_mesh_work(struct work_struct *work)
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct sk_buff *skb;
- if (!ieee80211_sdata_running(sdata))
+ if (!netif_running(sdata->dev))
return;
if (local->scanning)
diff --git a/trunk/net/mac80211/mesh_hwmp.c b/trunk/net/mac80211/mesh_hwmp.c
index ce84237ebad3..d28acb6b1f81 100644
--- a/trunk/net/mac80211/mesh_hwmp.c
+++ b/trunk/net/mac80211/mesh_hwmp.c
@@ -128,9 +128,9 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
IEEE80211_STYPE_ACTION);
memcpy(mgmt->da, da, ETH_ALEN);
- memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+ memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
/* BSSID == SA */
- memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
+ memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
mgmt->u.action.category = MESH_PATH_SEL_CATEGORY;
mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION;
@@ -222,7 +222,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
IEEE80211_STYPE_ACTION);
memcpy(mgmt->da, ra, ETH_ALEN);
- memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+ memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
/* BSSID is left zeroed, wildcard value */
mgmt->u.action.category = MESH_PATH_SEL_CATEGORY;
mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION;
@@ -335,7 +335,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
bool process = true;
rcu_read_lock();
- sta = sta_info_get(sdata, mgmt->sa);
+ sta = sta_info_get(local, mgmt->sa);
if (!sta) {
rcu_read_unlock();
return 0;
@@ -374,7 +374,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
new_metric = MAX_METRIC;
exp_time = TU_TO_EXP_TIME(orig_lifetime);
- if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0) {
+ if (memcmp(orig_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) {
/* This MP is the originator, we are not interested in this
* frame, except for updating transmitter's path info.
*/
@@ -486,7 +486,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
mhwmp_dbg("received PREQ from %pM\n", orig_addr);
- if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) {
+ if (memcmp(target_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) {
mhwmp_dbg("PREQ is for us\n");
forward = false;
reply = true;
@@ -579,7 +579,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
* replies
*/
target_addr = PREP_IE_TARGET_ADDR(prep_elem);
- if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0)
+ if (memcmp(target_addr, sdata->dev->dev_addr, ETH_ALEN) == 0)
/* destination, no forwarding required */
return;
@@ -890,7 +890,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
target_flags = MP_F_RF;
spin_unlock_bh(&mpath->state_lock);
- mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr,
+ mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr,
cpu_to_le32(ifmsh->sn), target_flags, mpath->dst,
cpu_to_le32(mpath->sn), broadcast_addr, 0,
ttl, cpu_to_le32(lifetime), 0,
@@ -939,7 +939,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
if (time_after(jiffies,
mpath->exp_time -
msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) &&
- !memcmp(sdata->vif.addr, hdr->addr4, ETH_ALEN) &&
+ !memcmp(sdata->dev->dev_addr, hdr->addr4, ETH_ALEN) &&
!(mpath->flags & MESH_PATH_RESOLVING) &&
!(mpath->flags & MESH_PATH_FIXED)) {
mesh_queue_preq(mpath,
@@ -1010,7 +1010,7 @@ mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr,
+ mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->dev->dev_addr,
cpu_to_le32(++ifmsh->sn),
0, NULL, 0, broadcast_addr,
0, MESH_TTL, 0, 0, 0, sdata);
diff --git a/trunk/net/mac80211/mesh_pathtbl.c b/trunk/net/mac80211/mesh_pathtbl.c
index fbef678f64c8..a8da23905c70 100644
--- a/trunk/net/mac80211/mesh_pathtbl.c
+++ b/trunk/net/mac80211/mesh_pathtbl.c
@@ -260,7 +260,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
int err = 0;
u32 hash_idx;
- if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0)
+ if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
/* never add ourselves as neighbours */
return -ENOTSUPP;
@@ -377,7 +377,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
int err = 0;
u32 hash_idx;
- if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0)
+ if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
/* never add ourselves as neighbours */
return -ENOTSUPP;
@@ -605,7 +605,7 @@ void mesh_path_discard_frame(struct sk_buff *skb,
struct mesh_path *mpath;
u32 sn = 0;
- if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) {
+ if (memcmp(hdr->addr4, sdata->dev->dev_addr, ETH_ALEN) != 0) {
u8 *ra, *da;
da = hdr->addr3;
diff --git a/trunk/net/mac80211/mesh_plink.c b/trunk/net/mac80211/mesh_plink.c
index bc4e20e57ff5..0f7c6e6a4248 100644
--- a/trunk/net/mac80211/mesh_plink.c
+++ b/trunk/net/mac80211/mesh_plink.c
@@ -102,7 +102,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
if (local->num_sta >= MESH_MAX_PLINKS)
return NULL;
- sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL);
+ sta = sta_info_alloc(sdata, hw_addr, GFP_ATOMIC);
if (!sta)
return NULL;
@@ -169,7 +169,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
memcpy(mgmt->da, da, ETH_ALEN);
- memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+ memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
/* BSSID is left zeroed, wildcard value */
mgmt->u.action.category = MESH_PLINK_CATEGORY;
mgmt->u.action.u.plink_action.action_code = action;
@@ -234,14 +234,14 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data
rcu_read_lock();
- sta = sta_info_get(sdata, hw_addr);
+ sta = sta_info_get(local, hw_addr);
if (!sta) {
- rcu_read_unlock();
-
sta = mesh_plink_alloc(sdata, hw_addr, rates);
- if (!sta)
+ if (!sta) {
+ rcu_read_unlock();
return;
- if (sta_info_insert_rcu(sta)) {
+ }
+ if (sta_info_insert(sta)) {
rcu_read_unlock();
return;
}
@@ -455,7 +455,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
rcu_read_lock();
- sta = sta_info_get(sdata, mgmt->sa);
+ sta = sta_info_get(local, mgmt->sa);
if (!sta && ftype != PLINK_OPEN) {
mpl_dbg("Mesh plink: cls or cnf from unknown peer\n");
rcu_read_unlock();
@@ -485,11 +485,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
} else if (!sta) {
/* ftype == PLINK_OPEN */
u32 rates;
-
- rcu_read_unlock();
-
if (!mesh_plink_free_count(sdata)) {
mpl_dbg("Mesh plink error: no more free plinks\n");
+ rcu_read_unlock();
return;
}
@@ -497,9 +495,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
sta = mesh_plink_alloc(sdata, mgmt->sa, rates);
if (!sta) {
mpl_dbg("Mesh plink error: plink table full\n");
+ rcu_read_unlock();
return;
}
- if (sta_info_insert_rcu(sta)) {
+ if (sta_info_insert(sta)) {
rcu_read_unlock();
return;
}
diff --git a/trunk/net/mac80211/mlme.c b/trunk/net/mac80211/mlme.c
index 41812a15eea0..05a18f43e1bf 100644
--- a/trunk/net/mac80211/mlme.c
+++ b/trunk/net/mac80211/mlme.c
@@ -27,6 +27,10 @@
#include "rate.h"
#include "led.h"
+#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
+#define IEEE80211_AUTH_MAX_TRIES 3
+#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
+#define IEEE80211_ASSOC_MAX_TRIES 3
#define IEEE80211_MAX_PROBE_TRIES 5
/*
@@ -71,8 +75,11 @@ enum rx_mgmt_action {
/* caller must call cfg80211_send_disassoc() */
RX_MGMT_CFG80211_DISASSOC,
- /* caller must tell cfg80211 about internal error */
- RX_MGMT_CFG80211_ASSOC_ERROR,
+ /* caller must call cfg80211_auth_timeout() & free work */
+ RX_MGMT_CFG80211_AUTH_TO,
+
+ /* caller must call cfg80211_assoc_timeout() & free work */
+ RX_MGMT_CFG80211_ASSOC_TO,
};
/* utils */
@@ -115,6 +122,27 @@ static int ecw2cw(int ecw)
return (1 << ecw) - 1;
}
+static int ieee80211_compatible_rates(struct ieee80211_bss *bss,
+ struct ieee80211_supported_band *sband,
+ u32 *rates)
+{
+ int i, j, count;
+ *rates = 0;
+ count = 0;
+ for (i = 0; i < bss->supp_rates_len; i++) {
+ int rate = (bss->supp_rates[i] & 0x7F) * 5;
+
+ for (j = 0; j < sband->n_bitrates; j++)
+ if (sband->bitrates[j].bitrate == rate) {
+ *rates |= BIT(j);
+ count++;
+ break;
+ }
+ }
+
+ return count;
+}
+
/*
* ieee80211_enable_ht should be called only after the operating band
* has been determined as ht configuration depends on the hw's
@@ -174,7 +202,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
ieee80211_hw_config(local, 0);
rcu_read_lock();
- sta = sta_info_get(sdata, bssid);
+ sta = sta_info_get(local, bssid);
if (sta)
rate_control_rate_update(local, sband, sta,
IEEE80211_RC_HT_CHANGED);
@@ -200,6 +228,209 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
/* frame sending functions */
+static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk)
+{
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ struct ieee80211_local *local = sdata->local;
+ struct sk_buff *skb;
+ struct ieee80211_mgmt *mgmt;
+ u8 *pos;
+ const u8 *ies, *ht_ie;
+ int i, len, count, rates_len, supp_rates_len;
+ u16 capab;
+ int wmm = 0;
+ struct ieee80211_supported_band *sband;
+ u32 rates = 0;
+
+ skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+ sizeof(*mgmt) + 200 + wk->ie_len +
+ wk->ssid_len);
+ if (!skb) {
+ printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
+ "frame\n", sdata->dev->name);
+ return;
+ }
+ skb_reserve(skb, local->hw.extra_tx_headroom);
+
+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+
+ capab = ifmgd->capab;
+
+ if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) {
+ if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
+ capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
+ if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
+ capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
+ }
+
+ if (wk->bss->cbss.capability & WLAN_CAPABILITY_PRIVACY)
+ capab |= WLAN_CAPABILITY_PRIVACY;
+ if (wk->bss->wmm_used)
+ wmm = 1;
+
+ /* get all rates supported by the device and the AP as
+ * some APs don't like getting a superset of their rates
+ * in the association request (e.g. D-Link DAP 1353 in
+ * b-only mode) */
+ rates_len = ieee80211_compatible_rates(wk->bss, sband, &rates);
+
+ if ((wk->bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
+ (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
+ capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
+
+ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+ memset(mgmt, 0, 24);
+ memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN);
+ memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
+ memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN);
+
+ if (!is_zero_ether_addr(wk->prev_bssid)) {
+ skb_put(skb, 10);
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_REASSOC_REQ);
+ mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
+ mgmt->u.reassoc_req.listen_interval =
+ cpu_to_le16(local->hw.conf.listen_interval);
+ memcpy(mgmt->u.reassoc_req.current_ap, wk->prev_bssid,
+ ETH_ALEN);
+ } else {
+ skb_put(skb, 4);
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_ASSOC_REQ);
+ mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
+ mgmt->u.assoc_req.listen_interval =
+ cpu_to_le16(local->hw.conf.listen_interval);
+ }
+
+ /* SSID */
+ ies = pos = skb_put(skb, 2 + wk->ssid_len);
+ *pos++ = WLAN_EID_SSID;
+ *pos++ = wk->ssid_len;
+ memcpy(pos, wk->ssid, wk->ssid_len);
+
+ /* add all rates which were marked to be used above */
+ supp_rates_len = rates_len;
+ if (supp_rates_len > 8)
+ supp_rates_len = 8;
+
+ len = sband->n_bitrates;
+ pos = skb_put(skb, supp_rates_len + 2);
+ *pos++ = WLAN_EID_SUPP_RATES;
+ *pos++ = supp_rates_len;
+
+ count = 0;
+ for (i = 0; i < sband->n_bitrates; i++) {
+ if (BIT(i) & rates) {
+ int rate = sband->bitrates[i].bitrate;
+ *pos++ = (u8) (rate / 5);
+ if (++count == 8)
+ break;
+ }
+ }
+
+ if (rates_len > count) {
+ pos = skb_put(skb, rates_len - count + 2);
+ *pos++ = WLAN_EID_EXT_SUPP_RATES;
+ *pos++ = rates_len - count;
+
+ for (i++; i < sband->n_bitrates; i++) {
+ if (BIT(i) & rates) {
+ int rate = sband->bitrates[i].bitrate;
+ *pos++ = (u8) (rate / 5);
+ }
+ }
+ }
+
+ if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) {
+ /* 1. power capabilities */
+ pos = skb_put(skb, 4);
+ *pos++ = WLAN_EID_PWR_CAPABILITY;
+ *pos++ = 2;
+ *pos++ = 0; /* min tx power */
+ *pos++ = local->hw.conf.channel->max_power; /* max tx power */
+
+ /* 2. supported channels */
+ /* TODO: get this in reg domain format */
+ pos = skb_put(skb, 2 * sband->n_channels + 2);
+ *pos++ = WLAN_EID_SUPPORTED_CHANNELS;
+ *pos++ = 2 * sband->n_channels;
+ for (i = 0; i < sband->n_channels; i++) {
+ *pos++ = ieee80211_frequency_to_channel(
+ sband->channels[i].center_freq);
+ *pos++ = 1; /* one channel in the subband*/
+ }
+ }
+
+ if (wk->ie_len && wk->ie) {
+ pos = skb_put(skb, wk->ie_len);
+ memcpy(pos, wk->ie, wk->ie_len);
+ }
+
+ if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) {
+ pos = skb_put(skb, 9);
+ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+ *pos++ = 7; /* len */
+ *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
+ *pos++ = 0x50;
+ *pos++ = 0xf2;
+ *pos++ = 2; /* WME */
+ *pos++ = 0; /* WME info */
+ *pos++ = 1; /* WME ver */
+ *pos++ = 0;
+ }
+
+ /* wmm support is a must to HT */
+ /*
+ * IEEE802.11n does not allow TKIP/WEP as pairwise
+ * ciphers in HT mode. We still associate in non-ht
+ * mode (11a/b/g) if any one of these ciphers is
+ * configured as pairwise.
+ */
+ if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
+ sband->ht_cap.ht_supported &&
+ (ht_ie = ieee80211_bss_get_ie(&wk->bss->cbss, WLAN_EID_HT_INFORMATION)) &&
+ ht_ie[1] >= sizeof(struct ieee80211_ht_info) &&
+ (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))) {
+ struct ieee80211_ht_info *ht_info =
+ (struct ieee80211_ht_info *)(ht_ie + 2);
+ u16 cap = sband->ht_cap.cap;
+ __le16 tmp;
+ u32 flags = local->hw.conf.channel->flags;
+
+ switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
+ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+ if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
+ cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ cap &= ~IEEE80211_HT_CAP_SGI_40;
+ }
+ break;
+ case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+ if (flags & IEEE80211_CHAN_NO_HT40MINUS) {
+ cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ cap &= ~IEEE80211_HT_CAP_SGI_40;
+ }
+ break;
+ }
+
+ tmp = cpu_to_le16(cap);
+ pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2);
+ *pos++ = WLAN_EID_HT_CAPABILITY;
+ *pos++ = sizeof(struct ieee80211_ht_cap);
+ memset(pos, 0, sizeof(struct ieee80211_ht_cap));
+ memcpy(pos, &tmp, sizeof(u16));
+ pos += sizeof(u16);
+ /* TODO: needs a define here for << 2 */
+ *pos++ = sband->ht_cap.ampdu_factor |
+ (sband->ht_cap.ampdu_density << 2);
+ memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
+ }
+
+ IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+ ieee80211_tx_skb(sdata, skb);
+}
+
+
static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
const u8 *bssid, u16 stype, u16 reason,
void *cookie)
@@ -212,7 +443,7 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
if (!skb) {
printk(KERN_DEBUG "%s: failed to allocate buffer for "
- "deauth/disassoc frame\n", sdata->name);
+ "deauth/disassoc frame\n", sdata->dev->name);
return;
}
skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -220,7 +451,7 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
memset(mgmt, 0, 24);
memcpy(mgmt->da, bssid, ETH_ALEN);
- memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+ memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
memcpy(mgmt->bssid, bssid, ETH_ALEN);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
skb_put(skb, 2);
@@ -245,15 +476,30 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
void ieee80211_send_pspoll(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata)
{
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_pspoll *pspoll;
struct sk_buff *skb;
+ u16 fc;
- skb = ieee80211_pspoll_get(&local->hw, &sdata->vif);
- if (!skb)
+ skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll));
+ if (!skb) {
+ printk(KERN_DEBUG "%s: failed to allocate buffer for "
+ "pspoll frame\n", sdata->dev->name);
return;
+ }
+ skb_reserve(skb, local->hw.extra_tx_headroom);
+
+ pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll));
+ memset(pspoll, 0, sizeof(*pspoll));
+ fc = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL | IEEE80211_FCTL_PM;
+ pspoll->frame_control = cpu_to_le16(fc);
+ pspoll->aid = cpu_to_le16(ifmgd->aid);
+
+ /* aid in PS-Poll has its two MSBs each set to 1 */
+ pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14);
- pspoll = (struct ieee80211_pspoll *) skb->data;
- pspoll->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
+ memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN);
+ memcpy(pspoll->ta, sdata->dev->dev_addr, ETH_ALEN);
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
ieee80211_tx_skb(sdata, skb);
@@ -262,24 +508,6 @@ void ieee80211_send_pspoll(struct ieee80211_local *local,
void ieee80211_send_nullfunc(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
int powersave)
-{
- struct sk_buff *skb;
- struct ieee80211_hdr_3addr *nullfunc;
-
- skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif);
- if (!skb)
- return;
-
- nullfunc = (struct ieee80211_hdr_3addr *) skb->data;
- if (powersave)
- nullfunc->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
-
- IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
- ieee80211_tx_skb(sdata, skb);
-}
-
-static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata)
{
struct sk_buff *skb;
struct ieee80211_hdr *nullfunc;
@@ -288,23 +516,24 @@ static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
return;
- skb = dev_alloc_skb(local->hw.extra_tx_headroom + 30);
+ skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24);
if (!skb) {
- printk(KERN_DEBUG "%s: failed to allocate buffer for 4addr "
- "nullfunc frame\n", sdata->name);
+ printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
+ "frame\n", sdata->dev->name);
return;
}
skb_reserve(skb, local->hw.extra_tx_headroom);
- nullfunc = (struct ieee80211_hdr *) skb_put(skb, 30);
- memset(nullfunc, 0, 30);
+ nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24);
+ memset(nullfunc, 0, 24);
fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
- IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
+ IEEE80211_FCTL_TODS);
+ if (powersave)
+ fc |= cpu_to_le16(IEEE80211_FCTL_PM);
nullfunc->frame_control = fc;
memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN);
- memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
+ memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN);
memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN);
- memcpy(nullfunc->addr4, sdata->vif.addr, ETH_ALEN);
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
ieee80211_tx_skb(sdata, skb);
@@ -317,7 +546,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work);
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- if (!ieee80211_sdata_running(sdata))
+ if (!netif_running(sdata->dev))
return;
mutex_lock(&ifmgd->mtx);
@@ -328,7 +557,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL);
/* XXX: shouldn't really modify cfg80211-owned data! */
- ifmgd->associated->channel = sdata->local->oper_channel;
+ ifmgd->associated->cbss.channel = sdata->local->oper_channel;
ieee80211_wake_queues_by_reason(&sdata->local->hw,
IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -355,8 +584,6 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel_sw_ie *sw_elem,
struct ieee80211_bss *bss)
{
- struct cfg80211_bss *cbss =
- container_of((void *)bss, struct cfg80211_bss, priv);
struct ieee80211_channel *new_ch;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num);
@@ -390,7 +617,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
mod_timer(&ifmgd->chswitch_timer,
jiffies +
msecs_to_jiffies(sw_elem->count *
- cbss->beacon_interval));
+ bss->cbss.beacon_interval));
}
}
@@ -434,11 +661,8 @@ static void ieee80211_enable_ps(struct ieee80211_local *local,
} else {
if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
ieee80211_send_nullfunc(local, sdata, 1);
-
- if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {
- conf->flags |= IEEE80211_CONF_PS;
- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
- }
+ conf->flags |= IEEE80211_CONF_PS;
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
}
}
@@ -467,13 +691,8 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
return;
}
- if (!list_empty(&local->work_list)) {
- local->ps_sdata = NULL;
- goto change;
- }
-
list_for_each_entry(sdata, &local->interfaces, list) {
- if (!ieee80211_sdata_running(sdata))
+ if (!netif_running(sdata->dev))
continue;
if (sdata->vif.type != NL80211_IFTYPE_STATION)
continue;
@@ -482,8 +701,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
}
if (count == 1 && found->u.mgd.powersave &&
- found->u.mgd.associated &&
- found->u.mgd.associated->beacon_ies &&
+ found->u.mgd.associated && list_empty(&found->u.mgd.work_list) &&
!(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL |
IEEE80211_STA_CONNECTION_POLL))) {
s32 beaconint_us;
@@ -497,29 +715,20 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
if (beaconint_us > latency) {
local->ps_sdata = NULL;
} else {
- struct ieee80211_bss *bss;
+ u8 dtimper = found->vif.bss_conf.dtim_period;
int maxslp = 1;
- u8 dtimper;
-
- bss = (void *)found->u.mgd.associated->priv;
- dtimper = bss->dtim_period;
- /* If the TIM IE is invalid, pretend the value is 1 */
- if (!dtimper)
- dtimper = 1;
- else if (dtimper > 1)
+ if (dtimper > 1)
maxslp = min_t(int, dtimper,
latency / beaconint_us);
local->hw.conf.max_sleep_period = maxslp;
- local->hw.conf.ps_dtim_period = dtimper;
local->ps_sdata = found;
}
} else {
local->ps_sdata = NULL;
}
- change:
ieee80211_change_ps(local);
}
@@ -544,7 +753,6 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
container_of(work, struct ieee80211_local,
dynamic_ps_enable_work);
struct ieee80211_sub_if_data *sdata = local->ps_sdata;
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
/* can only happen when PS was just disabled anyway */
if (!sdata)
@@ -553,16 +761,11 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
if (local->hw.conf.flags & IEEE80211_CONF_PS)
return;
- if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
- (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)))
+ if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
ieee80211_send_nullfunc(local, sdata, 1);
- if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) ||
- (ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {
- ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
- local->hw.conf.flags |= IEEE80211_CONF_PS;
- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
- }
+ local->hw.conf.flags |= IEEE80211_CONF_PS;
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
}
void ieee80211_dynamic_ps_timer(unsigned long data)
@@ -583,9 +786,9 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
struct ieee80211_tx_queue_params params;
size_t left;
int count;
- u8 *pos, uapsd_queues = 0;
+ u8 *pos;
- if (local->hw.queues < 4)
+ if (!(ifmgd->flags & IEEE80211_STA_WMM_ENABLED))
return;
if (!wmm_param)
@@ -593,10 +796,6 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
return;
-
- if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED)
- uapsd_queues = local->uapsd_queues;
-
count = wmm_param[6] & 0x0f;
if (count == ifmgd->wmm_last_param_set)
return;
@@ -611,7 +810,6 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
for (; left >= 4; left -= 4, pos += 4) {
int aci = (pos[0] >> 5) & 0x03;
int acm = (pos[0] >> 4) & 0x01;
- bool uapsd = false;
int queue;
switch (aci) {
@@ -619,30 +817,22 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
queue = 3;
if (acm)
local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */
- if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
- uapsd = true;
break;
case 2: /* AC_VI */
queue = 1;
if (acm)
local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
- if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
- uapsd = true;
break;
case 3: /* AC_VO */
queue = 0;
if (acm)
local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
- if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
- uapsd = true;
break;
case 0: /* AC_BE */
default:
queue = 2;
if (acm)
local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
- if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
- uapsd = true;
break;
}
@@ -650,14 +840,11 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
params.cw_min = ecw2cw(pos[1] & 0x0f);
params.txop = get_unaligned_le16(pos + 2);
- params.uapsd = uapsd;
-
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
- "cWmin=%d cWmax=%d txop=%d uapsd=%d\n",
+ "cWmin=%d cWmax=%d txop=%d\n",
wiphy_name(local->hw.wiphy), queue, aci, acm,
- params.aifs, params.cw_min, params.cw_max, params.txop,
- params.uapsd);
+ params.aifs, params.cw_min, params.cw_max, params.txop);
#endif
if (drv_conf_tx(local, queue, ¶ms) && local->ops->conf_tx)
printk(KERN_DEBUG "%s: failed to set TX queue "
@@ -684,8 +871,6 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
}
use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME);
- if (sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
- use_short_slot = true;
if (use_protection != bss_conf->use_cts_prot) {
bss_conf->use_cts_prot = use_protection;
@@ -706,23 +891,25 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
}
static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
- struct cfg80211_bss *cbss,
+ struct ieee80211_mgd_work *wk,
u32 bss_info_changed)
{
- struct ieee80211_bss *bss = (void *)cbss->priv;
struct ieee80211_local *local = sdata->local;
+ struct ieee80211_bss *bss = wk->bss;
bss_info_changed |= BSS_CHANGED_ASSOC;
/* set timing information */
- sdata->vif.bss_conf.beacon_int = cbss->beacon_interval;
- sdata->vif.bss_conf.timestamp = cbss->tsf;
+ sdata->vif.bss_conf.beacon_int = bss->cbss.beacon_interval;
+ sdata->vif.bss_conf.timestamp = bss->cbss.tsf;
+ sdata->vif.bss_conf.dtim_period = bss->dtim_period;
bss_info_changed |= BSS_CHANGED_BEACON_INT;
bss_info_changed |= ieee80211_handle_bss_capability(sdata,
- cbss->capability, bss->has_erp_value, bss->erp_value);
+ bss->cbss.capability, bss->has_erp_value, bss->erp_value);
- sdata->u.mgd.associated = cbss;
- memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN);
+ sdata->u.mgd.associated = bss;
+ sdata->u.mgd.old_associate_work = wk;
+ memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN);
/* just to be sure */
sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL |
@@ -753,14 +940,99 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
mutex_lock(&local->iflist_mtx);
ieee80211_recalc_ps(local, -1);
- ieee80211_recalc_smps(local, sdata);
mutex_unlock(&local->iflist_mtx);
netif_tx_start_all_queues(sdata->dev);
netif_carrier_on(sdata->dev);
}
-static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata)
+static enum rx_mgmt_action __must_check
+ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk)
+{
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ struct ieee80211_local *local = sdata->local;
+
+ wk->tries++;
+ if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
+ printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n",
+ sdata->dev->name, wk->bss->cbss.bssid);
+
+ /*
+ * Most likely AP is not in the range so remove the
+ * bss struct for that AP.
+ */
+ cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss);
+
+ /*
+ * We might have a pending scan which had no chance to run yet
+ * due to work needing to be done. Hence, queue the STAs work
+ * again for that.
+ */
+ ieee80211_queue_work(&local->hw, &ifmgd->work);
+ return RX_MGMT_CFG80211_AUTH_TO;
+ }
+
+ printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n",
+ sdata->dev->name, wk->bss->cbss.bssid,
+ wk->tries);
+
+ /*
+ * Direct probe is sent to broadcast address as some APs
+ * will not answer to direct packet in unassociated state.
+ */
+ ieee80211_send_probe_req(sdata, NULL, wk->ssid, wk->ssid_len, NULL, 0);
+
+ wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
+ run_again(ifmgd, wk->timeout);
+
+ return RX_MGMT_NONE;
+}
+
+
+static enum rx_mgmt_action __must_check
+ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk)
+{
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ struct ieee80211_local *local = sdata->local;
+
+ wk->tries++;
+ if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
+ printk(KERN_DEBUG "%s: authentication with AP %pM"
+ " timed out\n",
+ sdata->dev->name, wk->bss->cbss.bssid);
+
+ /*
+ * Most likely AP is not in the range so remove the
+ * bss struct for that AP.
+ */
+ cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss);
+
+ /*
+ * We might have a pending scan which had no chance to run yet
+ * due to work needing to be done. Hence, queue the STAs work
+ * again for that.
+ */
+ ieee80211_queue_work(&local->hw, &ifmgd->work);
+ return RX_MGMT_CFG80211_AUTH_TO;
+ }
+
+ printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n",
+ sdata->dev->name, wk->bss->cbss.bssid, wk->tries);
+
+ ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len,
+ wk->bss->cbss.bssid, NULL, 0, 0);
+ wk->auth_transaction = 2;
+
+ wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
+ run_again(ifmgd, wk->timeout);
+
+ return RX_MGMT_NONE;
+}
+
+static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
+ bool deauth)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local;
@@ -773,11 +1045,21 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata)
if (WARN_ON(!ifmgd->associated))
return;
- memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
+ memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN);
ifmgd->associated = NULL;
memset(ifmgd->bssid, 0, ETH_ALEN);
+ if (deauth) {
+ kfree(ifmgd->old_associate_work);
+ ifmgd->old_associate_work = NULL;
+ } else {
+ struct ieee80211_mgd_work *wk = ifmgd->old_associate_work;
+
+ wk->state = IEEE80211_MGD_STATE_IDLE;
+ list_add(&wk->list, &ifmgd->work_list);
+ }
+
/*
* we need to commit the associated = NULL change because the
* scan code uses that to determine whether this iface should
@@ -796,11 +1078,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata)
netif_carrier_off(sdata->dev);
rcu_read_lock();
- sta = sta_info_get(sdata, bssid);
- if (sta) {
- set_sta_flags(sta, WLAN_STA_DISASSOC);
+ sta = sta_info_get(local, bssid);
+ if (sta)
ieee80211_sta_tear_down_BA_sessions(sta);
- }
rcu_read_unlock();
changed |= ieee80211_reset_erp_info(sdata);
@@ -833,7 +1113,57 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata)
changed |= BSS_CHANGED_BSSID;
ieee80211_bss_info_change_notify(sdata, changed);
- sta_info_destroy_addr(sdata, bssid);
+ rcu_read_lock();
+
+ sta = sta_info_get(local, bssid);
+ if (!sta) {
+ rcu_read_unlock();
+ return;
+ }
+
+ sta_info_unlink(&sta);
+
+ rcu_read_unlock();
+
+ sta_info_destroy(sta);
+}
+
+static enum rx_mgmt_action __must_check
+ieee80211_associate(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk)
+{
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ struct ieee80211_local *local = sdata->local;
+
+ wk->tries++;
+ if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) {
+ printk(KERN_DEBUG "%s: association with AP %pM"
+ " timed out\n",
+ sdata->dev->name, wk->bss->cbss.bssid);
+
+ /*
+ * Most likely AP is not in the range so remove the
+ * bss struct for that AP.
+ */
+ cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss);
+
+ /*
+ * We might have a pending scan which had no chance to run yet
+ * due to work needing to be done. Hence, queue the STAs work
+ * again for that.
+ */
+ ieee80211_queue_work(&local->hw, &ifmgd->work);
+ return RX_MGMT_CFG80211_ASSOC_TO;
+ }
+
+ printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n",
+ sdata->dev->name, wk->bss->cbss.bssid, wk->tries);
+ ieee80211_send_assoc(sdata, wk);
+
+ wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
+ run_again(ifmgd, wk->timeout);
+
+ return RX_MGMT_NONE;
}
void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
@@ -859,8 +1189,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
const u8 *ssid;
- ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
- ieee80211_send_probe_req(sdata, ifmgd->associated->bssid,
+ ssid = ieee80211_bss_get_ie(&ifmgd->associated->cbss, WLAN_EID_SSID);
+ ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid,
ssid + 2, ssid[1], NULL, 0);
ifmgd->probe_send_count++;
@@ -874,15 +1204,12 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
bool already = false;
- if (!ieee80211_sdata_running(sdata))
+ if (!netif_running(sdata->dev))
return;
if (sdata->local->scanning)
return;
- if (sdata->local->tmp_channel)
- return;
-
mutex_lock(&ifmgd->mtx);
if (!ifmgd->associated)
@@ -891,7 +1218,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
if (beacon && net_ratelimit())
printk(KERN_DEBUG "%s: detected beacon loss from AP "
- "- sending probe request\n", sdata->name);
+ "- sending probe request\n", sdata->dev->name);
#endif
/*
@@ -944,8 +1271,88 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif)
}
EXPORT_SYMBOL(ieee80211_beacon_loss);
+static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk)
+{
+ wk->state = IEEE80211_MGD_STATE_IDLE;
+ printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name);
+}
+
+
+static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk,
+ struct ieee80211_mgmt *mgmt,
+ size_t len)
+{
+ u8 *pos;
+ struct ieee802_11_elems elems;
+
+ pos = mgmt->u.auth.variable;
+ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
+ if (!elems.challenge)
+ return;
+ ieee80211_send_auth(sdata, 3, wk->auth_alg,
+ elems.challenge - 2, elems.challenge_len + 2,
+ wk->bss->cbss.bssid,
+ wk->key, wk->key_len, wk->key_idx);
+ wk->auth_transaction = 4;
+}
+
+static enum rx_mgmt_action __must_check
+ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk,
+ struct ieee80211_mgmt *mgmt, size_t len)
+{
+ u16 auth_alg, auth_transaction, status_code;
+
+ if (wk->state != IEEE80211_MGD_STATE_AUTH)
+ return RX_MGMT_NONE;
+
+ if (len < 24 + 6)
+ return RX_MGMT_NONE;
+
+ if (memcmp(wk->bss->cbss.bssid, mgmt->sa, ETH_ALEN) != 0)
+ return RX_MGMT_NONE;
+
+ if (memcmp(wk->bss->cbss.bssid, mgmt->bssid, ETH_ALEN) != 0)
+ return RX_MGMT_NONE;
+
+ auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
+ auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
+ status_code = le16_to_cpu(mgmt->u.auth.status_code);
+
+ if (auth_alg != wk->auth_alg ||
+ auth_transaction != wk->auth_transaction)
+ return RX_MGMT_NONE;
+
+ if (status_code != WLAN_STATUS_SUCCESS) {
+ list_del(&wk->list);
+ kfree(wk);
+ return RX_MGMT_CFG80211_AUTH;
+ }
+
+ switch (wk->auth_alg) {
+ case WLAN_AUTH_OPEN:
+ case WLAN_AUTH_LEAP:
+ case WLAN_AUTH_FT:
+ ieee80211_auth_completed(sdata, wk);
+ return RX_MGMT_CFG80211_AUTH;
+ case WLAN_AUTH_SHARED_KEY:
+ if (wk->auth_transaction == 4) {
+ ieee80211_auth_completed(sdata, wk);
+ return RX_MGMT_CFG80211_AUTH;
+ } else
+ ieee80211_auth_challenge(sdata, wk, mgmt, len);
+ break;
+ }
+
+ return RX_MGMT_NONE;
+}
+
+
static enum rx_mgmt_action __must_check
ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk,
struct ieee80211_mgmt *mgmt, size_t len)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -957,15 +1364,23 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
ASSERT_MGD_MTX(ifmgd);
- bssid = ifmgd->associated->bssid;
+ if (wk)
+ bssid = wk->bss->cbss.bssid;
+ else
+ bssid = ifmgd->associated->cbss.bssid;
reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n",
- sdata->name, bssid, reason_code);
+ sdata->dev->name, bssid, reason_code);
- ieee80211_set_disassoc(sdata);
- ieee80211_recalc_idle(sdata->local);
+ if (!wk) {
+ ieee80211_set_disassoc(sdata, true);
+ ieee80211_recalc_idle(sdata->local);
+ } else {
+ list_del(&wk->list);
+ kfree(wk);
+ }
return RX_MGMT_CFG80211_DEAUTH;
}
@@ -986,71 +1401,122 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
if (WARN_ON(!ifmgd->associated))
return RX_MGMT_NONE;
- if (WARN_ON(memcmp(ifmgd->associated->bssid, mgmt->sa, ETH_ALEN)))
+ if (WARN_ON(memcmp(ifmgd->associated->cbss.bssid, mgmt->sa, ETH_ALEN)))
return RX_MGMT_NONE;
reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n",
- sdata->name, mgmt->sa, reason_code);
+ sdata->dev->name, mgmt->sa, reason_code);
- ieee80211_set_disassoc(sdata);
+ ieee80211_set_disassoc(sdata, false);
ieee80211_recalc_idle(sdata->local);
return RX_MGMT_CFG80211_DISASSOC;
}
-static bool ieee80211_assoc_success(struct ieee80211_work *wk,
- struct ieee80211_mgmt *mgmt, size_t len)
+static enum rx_mgmt_action __must_check
+ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk,
+ struct ieee80211_mgmt *mgmt, size_t len,
+ bool reassoc)
{
- struct ieee80211_sub_if_data *sdata = wk->sdata;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband;
struct sta_info *sta;
- struct cfg80211_bss *cbss = wk->assoc.bss;
- u8 *pos;
u32 rates, basic_rates;
- u16 capab_info, aid;
+ u16 capab_info, status_code, aid;
struct ieee802_11_elems elems;
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
+ u8 *pos;
u32 changed = 0;
- int i, j, err;
- bool have_higher_than_11mbit = false;
+ int i, j;
+ bool have_higher_than_11mbit = false, newsta = false;
u16 ap_ht_cap_flags;
- /* AssocResp and ReassocResp have identical structure */
+ /*
+ * AssocResp and ReassocResp have identical structure, so process both
+ * of them in this function.
+ */
+
+ if (len < 24 + 6)
+ return RX_MGMT_NONE;
+
+ if (memcmp(wk->bss->cbss.bssid, mgmt->sa, ETH_ALEN) != 0)
+ return RX_MGMT_NONE;
- aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
+ status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
+ aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
- if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
- printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
- "set\n", sdata->name, aid);
- aid &= ~(BIT(15) | BIT(14));
+ printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x "
+ "status=%d aid=%d)\n",
+ sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa,
+ capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
pos = mgmt->u.assoc_resp.variable;
ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
+ if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
+ elems.timeout_int && elems.timeout_int_len == 5 &&
+ elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) {
+ u32 tu, ms;
+ tu = get_unaligned_le32(elems.timeout_int + 1);
+ ms = tu * 1024 / 1000;
+ printk(KERN_DEBUG "%s: AP rejected association temporarily; "
+ "comeback duration %u TU (%u ms)\n",
+ sdata->dev->name, tu, ms);
+ wk->timeout = jiffies + msecs_to_jiffies(ms);
+ if (ms > IEEE80211_ASSOC_TIMEOUT)
+ run_again(ifmgd, jiffies + msecs_to_jiffies(ms));
+ return RX_MGMT_NONE;
+ }
+
+ if (status_code != WLAN_STATUS_SUCCESS) {
+ printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
+ sdata->dev->name, status_code);
+ wk->state = IEEE80211_MGD_STATE_IDLE;
+ return RX_MGMT_CFG80211_ASSOC;
+ }
+
+ if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
+ printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
+ "set\n", sdata->dev->name, aid);
+ aid &= ~(BIT(15) | BIT(14));
+
if (!elems.supp_rates) {
printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
- sdata->name);
- return false;
+ sdata->dev->name);
+ return RX_MGMT_NONE;
}
+ printk(KERN_DEBUG "%s: associated\n", sdata->dev->name);
ifmgd->aid = aid;
- sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL);
+ rcu_read_lock();
+
+ /* Add STA entry for the AP */
+ sta = sta_info_get(local, wk->bss->cbss.bssid);
if (!sta) {
- printk(KERN_DEBUG "%s: failed to alloc STA entry for"
- " the AP\n", sdata->name);
- return false;
- }
+ newsta = true;
+
+ rcu_read_unlock();
+
+ sta = sta_info_alloc(sdata, wk->bss->cbss.bssid, GFP_KERNEL);
+ if (!sta) {
+ printk(KERN_DEBUG "%s: failed to alloc STA entry for"
+ " the AP\n", sdata->dev->name);
+ return RX_MGMT_NONE;
+ }
- set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC |
- WLAN_STA_ASSOC_AP);
- if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
- set_sta_flags(sta, WLAN_STA_AUTHORIZED);
+ set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC |
+ WLAN_STA_ASSOC_AP);
+ if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
+ set_sta_flags(sta, WLAN_STA_AUTHORIZED);
+
+ rcu_read_lock();
+ }
rates = 0;
basic_rates = 0;
@@ -1114,40 +1580,40 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
if (elems.wmm_param)
set_sta_flags(sta, WLAN_STA_WME);
- err = sta_info_insert(sta);
- sta = NULL;
- if (err) {
- printk(KERN_DEBUG "%s: failed to insert STA entry for"
- " the AP (error %d)\n", sdata->name, err);
- return false;
+ if (newsta) {
+ int err = sta_info_insert(sta);
+ if (err) {
+ printk(KERN_DEBUG "%s: failed to insert STA entry for"
+ " the AP (error %d)\n", sdata->dev->name, err);
+ rcu_read_unlock();
+ return RX_MGMT_NONE;
+ }
}
+ rcu_read_unlock();
+
if (elems.wmm_param)
ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param,
elems.wmm_param_len);
else
ieee80211_set_wmm_default(sdata);
- local->oper_channel = wk->chan;
-
if (elems.ht_info_elem && elems.wmm_param &&
- (sdata->local->hw.queues >= 4) &&
+ (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
- cbss->bssid, ap_ht_cap_flags);
+ wk->bss->cbss.bssid,
+ ap_ht_cap_flags);
+
+ /* delete work item -- must be before set_associated for PS */
+ list_del(&wk->list);
/* set AID and assoc capability,
* ieee80211_set_associated() will tell the driver */
bss_conf->aid = aid;
bss_conf->assoc_capability = capab_info;
- ieee80211_set_associated(sdata, cbss, changed);
-
- /*
- * If we're using 4-addr mode, let the AP know that we're
- * doing so, so that it can create the STA VLAN on its side
- */
- if (ifmgd->use_4addr)
- ieee80211_send_4addr_nullfunc(local, sdata);
+ /* this will take ownership of wk */
+ ieee80211_set_associated(sdata, wk, changed);
/*
* Start timer to probe the connection to the AP now.
@@ -1156,7 +1622,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
mod_beacon_timer(sdata);
- return true;
+ return RX_MGMT_CFG80211_ASSOC;
}
@@ -1171,13 +1637,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
int freq;
struct ieee80211_bss *bss;
struct ieee80211_channel *channel;
- bool need_ps = false;
-
- if (sdata->u.mgd.associated) {
- bss = (void *)sdata->u.mgd.associated->priv;
- /* not previously set so we may need to recalc */
- need_ps = !bss->dtim_period;
- }
if (elems->ds_params && elems->ds_params_len == 1)
freq = ieee80211_channel_to_frequency(elems->ds_params[0]);
@@ -1197,14 +1656,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
if (!sdata->u.mgd.associated)
return;
- if (need_ps) {
- mutex_lock(&local->iflist_mtx);
- ieee80211_recalc_ps(local, -1);
- mutex_unlock(&local->iflist_mtx);
- }
-
if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) &&
- (memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid,
+ (memcmp(mgmt->bssid, sdata->u.mgd.associated->cbss.bssid,
ETH_ALEN) == 0)) {
struct ieee80211_channel_sw_ie *sw_elem =
(struct ieee80211_channel_sw_ie *)elems->ch_switch_elem;
@@ -1214,19 +1667,19 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb)
+ struct ieee80211_mgd_work *wk,
+ struct ieee80211_mgmt *mgmt, size_t len,
+ struct ieee80211_rx_status *rx_status)
{
- struct ieee80211_mgmt *mgmt = (void *)skb->data;
struct ieee80211_if_managed *ifmgd;
- struct ieee80211_rx_status *rx_status = (void *) skb->cb;
- size_t baselen, len = skb->len;
+ size_t baselen;
struct ieee802_11_elems elems;
ifmgd = &sdata->u.mgd;
ASSERT_MGD_MTX(ifmgd);
- if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN))
+ if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
return; /* ignore ProbeResp to foreign address */
baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
@@ -1238,8 +1691,17 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false);
+ /* direct probe may be part of the association flow */
+ if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) {
+ printk(KERN_DEBUG "%s: direct probe responded\n",
+ sdata->dev->name);
+ wk->tries = 0;
+ wk->state = IEEE80211_MGD_STATE_AUTH;
+ WARN_ON(ieee80211_authenticate(sdata, wk) != RX_MGMT_NONE);
+ }
+
if (ifmgd->associated &&
- memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0 &&
+ memcmp(mgmt->bssid, ifmgd->associated->cbss.bssid, ETH_ALEN) == 0 &&
ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
IEEE80211_STA_CONNECTION_POLL)) {
ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
@@ -1312,7 +1774,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
if (!ifmgd->associated)
return;
- bssid = ifmgd->associated->bssid;
+ bssid = ifmgd->associated->cbss.bssid;
/*
* And in theory even frames from a different AP we were just
@@ -1325,7 +1787,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: cancelling probereq poll due "
- "to a received beacon\n", sdata->name);
+ "to a received beacon\n", sdata->dev->name);
}
#endif
ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL;
@@ -1403,7 +1865,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
rcu_read_lock();
- sta = sta_info_get(sdata, bssid);
+ sta = sta_info_get(local, bssid);
if (WARN_ON(!sta)) {
rcu_read_unlock();
return;
@@ -1451,6 +1913,9 @@ ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
switch (fc & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_PROBE_RESP:
case IEEE80211_STYPE_BEACON:
+ case IEEE80211_STYPE_AUTH:
+ case IEEE80211_STYPE_ASSOC_RESP:
+ case IEEE80211_STYPE_REASSOC_RESP:
case IEEE80211_STYPE_DEAUTH:
case IEEE80211_STYPE_DISASSOC:
case IEEE80211_STYPE_ACTION:
@@ -1468,6 +1933,7 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_rx_status *rx_status;
struct ieee80211_mgmt *mgmt;
+ struct ieee80211_mgd_work *wk;
enum rx_mgmt_action rma = RX_MGMT_NONE;
u16 fc;
@@ -1478,17 +1944,20 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
mutex_lock(&ifmgd->mtx);
if (ifmgd->associated &&
- memcmp(ifmgd->associated->bssid, mgmt->bssid, ETH_ALEN) == 0) {
+ memcmp(ifmgd->associated->cbss.bssid, mgmt->bssid,
+ ETH_ALEN) == 0) {
switch (fc & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_BEACON:
ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len,
rx_status);
break;
case IEEE80211_STYPE_PROBE_RESP:
- ieee80211_rx_mgmt_probe_resp(sdata, skb);
+ ieee80211_rx_mgmt_probe_resp(sdata, NULL, mgmt,
+ skb->len, rx_status);
break;
case IEEE80211_STYPE_DEAUTH:
- rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);
+ rma = ieee80211_rx_mgmt_deauth(sdata, NULL,
+ mgmt, skb->len);
break;
case IEEE80211_STYPE_DISASSOC:
rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
@@ -1499,7 +1968,7 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
ieee80211_sta_process_chanswitch(sdata,
&mgmt->u.action.u.chan_switch.sw_elem,
- (void *)ifmgd->associated->priv);
+ ifmgd->associated);
break;
}
mutex_unlock(&ifmgd->mtx);
@@ -1520,11 +1989,58 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
goto out;
}
+ list_for_each_entry(wk, &ifmgd->work_list, list) {
+ if (memcmp(wk->bss->cbss.bssid, mgmt->bssid, ETH_ALEN) != 0)
+ continue;
+
+ switch (fc & IEEE80211_FCTL_STYPE) {
+ case IEEE80211_STYPE_PROBE_RESP:
+ ieee80211_rx_mgmt_probe_resp(sdata, wk, mgmt, skb->len,
+ rx_status);
+ break;
+ case IEEE80211_STYPE_AUTH:
+ rma = ieee80211_rx_mgmt_auth(sdata, wk, mgmt, skb->len);
+ break;
+ case IEEE80211_STYPE_ASSOC_RESP:
+ rma = ieee80211_rx_mgmt_assoc_resp(sdata, wk, mgmt,
+ skb->len, false);
+ break;
+ case IEEE80211_STYPE_REASSOC_RESP:
+ rma = ieee80211_rx_mgmt_assoc_resp(sdata, wk, mgmt,
+ skb->len, true);
+ break;
+ case IEEE80211_STYPE_DEAUTH:
+ rma = ieee80211_rx_mgmt_deauth(sdata, wk, mgmt,
+ skb->len);
+ break;
+ }
+ /*
+ * We've processed this frame for that work, so it can't
+ * belong to another work struct.
+ * NB: this is also required for correctness because the
+ * called functions can free 'wk', and for 'rma'!
+ */
+ break;
+ }
+
mutex_unlock(&ifmgd->mtx);
- if (skb->len >= 24 + 2 /* mgmt + deauth reason */ &&
- (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH)
+ switch (rma) {
+ case RX_MGMT_NONE:
+ /* no action */
+ break;
+ case RX_MGMT_CFG80211_AUTH:
+ cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, skb->len);
+ break;
+ case RX_MGMT_CFG80211_ASSOC:
+ cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, skb->len);
+ break;
+ case RX_MGMT_CFG80211_DEAUTH:
cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
+ break;
+ default:
+ WARN(1, "unexpected: %d", rma);
+ }
out:
kfree_skb(skb);
@@ -1552,8 +2068,12 @@ static void ieee80211_sta_work(struct work_struct *work)
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd;
struct sk_buff *skb;
+ struct ieee80211_mgd_work *wk, *tmp;
+ LIST_HEAD(free_work);
+ enum rx_mgmt_action rma;
+ bool anybusy = false;
- if (!ieee80211_sdata_running(sdata))
+ if (!netif_running(sdata->dev))
return;
if (local->scanning)
@@ -1584,7 +2104,7 @@ static void ieee80211_sta_work(struct work_struct *work)
ifmgd->associated) {
u8 bssid[ETH_ALEN];
- memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
+ memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN);
if (time_is_after_jiffies(ifmgd->probe_timeout))
run_again(ifmgd, ifmgd->probe_timeout);
@@ -1606,7 +2126,7 @@ static void ieee80211_sta_work(struct work_struct *work)
printk(KERN_DEBUG "No probe response from AP %pM"
" after %dms, disconnecting.\n",
bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
- ieee80211_set_disassoc(sdata);
+ ieee80211_set_disassoc(sdata, true);
ieee80211_recalc_idle(local);
mutex_unlock(&ifmgd->mtx);
/*
@@ -1621,7 +2141,87 @@ static void ieee80211_sta_work(struct work_struct *work)
}
}
+
+ ieee80211_recalc_idle(local);
+
+ list_for_each_entry_safe(wk, tmp, &ifmgd->work_list, list) {
+ if (time_is_after_jiffies(wk->timeout)) {
+ /*
+ * This work item isn't supposed to be worked on
+ * right now, but take care to adjust the timer
+ * properly.
+ */
+ run_again(ifmgd, wk->timeout);
+ continue;
+ }
+
+ switch (wk->state) {
+ default:
+ WARN_ON(1);
+ /* fall through */
+ case IEEE80211_MGD_STATE_IDLE:
+ /* nothing */
+ rma = RX_MGMT_NONE;
+ break;
+ case IEEE80211_MGD_STATE_PROBE:
+ rma = ieee80211_direct_probe(sdata, wk);
+ break;
+ case IEEE80211_MGD_STATE_AUTH:
+ rma = ieee80211_authenticate(sdata, wk);
+ break;
+ case IEEE80211_MGD_STATE_ASSOC:
+ rma = ieee80211_associate(sdata, wk);
+ break;
+ }
+
+ switch (rma) {
+ case RX_MGMT_NONE:
+ /* no action required */
+ break;
+ case RX_MGMT_CFG80211_AUTH_TO:
+ case RX_MGMT_CFG80211_ASSOC_TO:
+ list_del(&wk->list);
+ list_add(&wk->list, &free_work);
+ wk->tries = rma; /* small abuse but only local */
+ break;
+ default:
+ WARN(1, "unexpected: %d", rma);
+ }
+ }
+
+ list_for_each_entry(wk, &ifmgd->work_list, list) {
+ if (wk->state != IEEE80211_MGD_STATE_IDLE) {
+ anybusy = true;
+ break;
+ }
+ }
+ if (!anybusy &&
+ test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request))
+ ieee80211_queue_delayed_work(&local->hw,
+ &local->scan_work,
+ round_jiffies_relative(0));
+
mutex_unlock(&ifmgd->mtx);
+
+ list_for_each_entry_safe(wk, tmp, &free_work, list) {
+ switch (wk->tries) {
+ case RX_MGMT_CFG80211_AUTH_TO:
+ cfg80211_send_auth_timeout(sdata->dev,
+ wk->bss->cbss.bssid);
+ break;
+ case RX_MGMT_CFG80211_ASSOC_TO:
+ cfg80211_send_assoc_timeout(sdata->dev,
+ wk->bss->cbss.bssid);
+ break;
+ default:
+ WARN(1, "unexpected: %d", wk->tries);
+ }
+
+ list_del(&wk->list);
+ kfree(wk);
+ }
+
+ ieee80211_recalc_idle(local);
}
static void ieee80211_sta_bcn_mon_timer(unsigned long data)
@@ -1730,14 +2330,14 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
(unsigned long) sdata);
skb_queue_head_init(&ifmgd->skb_queue);
+ INIT_LIST_HEAD(&ifmgd->work_list);
+
+ ifmgd->capab = WLAN_CAPABILITY_ESS;
ifmgd->flags = 0;
+ if (sdata->local->hw.queues >= 4)
+ ifmgd->flags |= IEEE80211_STA_WMM_ENABLED;
mutex_init(&ifmgd->mtx);
-
- if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS)
- ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC;
- else
- ifmgd->req_smps = IEEE80211_SMPS_OFF;
}
/* scan finished notification */
@@ -1768,34 +2368,12 @@ int ieee80211_max_network_latency(struct notifier_block *nb,
}
/* config hooks */
-static enum work_done_result
-ieee80211_probe_auth_done(struct ieee80211_work *wk,
- struct sk_buff *skb)
-{
- if (!skb) {
- cfg80211_send_auth_timeout(wk->sdata->dev, wk->filter_ta);
- return WORK_DONE_DESTROY;
- }
-
- if (wk->type == IEEE80211_WORK_AUTH) {
- cfg80211_send_rx_auth(wk->sdata->dev, skb->data, skb->len);
- return WORK_DONE_DESTROY;
- }
-
- mutex_lock(&wk->sdata->u.mgd.mtx);
- ieee80211_rx_mgmt_probe_resp(wk->sdata, skb);
- mutex_unlock(&wk->sdata->u.mgd.mtx);
-
- wk->type = IEEE80211_WORK_AUTH;
- wk->probe_auth.tries = 0;
- return WORK_DONE_REQUEUE;
-}
-
int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
struct cfg80211_auth_request *req)
{
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
const u8 *ssid;
- struct ieee80211_work *wk;
+ struct ieee80211_mgd_work *wk;
u16 auth_alg;
switch (req->auth_type) {
@@ -1819,7 +2397,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
if (!wk)
return -ENOMEM;
- memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN);
+ wk->bss = (void *)req->bss;
if (req->ie && req->ie_len) {
memcpy(wk->ie, req->ie, req->ie_len);
@@ -1827,83 +2405,68 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
}
if (req->key && req->key_len) {
- wk->probe_auth.key_len = req->key_len;
- wk->probe_auth.key_idx = req->key_idx;
- memcpy(wk->probe_auth.key, req->key, req->key_len);
+ wk->key_len = req->key_len;
+ wk->key_idx = req->key_idx;
+ memcpy(wk->key, req->key, req->key_len);
}
ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
- memcpy(wk->probe_auth.ssid, ssid + 2, ssid[1]);
- wk->probe_auth.ssid_len = ssid[1];
+ memcpy(wk->ssid, ssid + 2, ssid[1]);
+ wk->ssid_len = ssid[1];
- wk->probe_auth.algorithm = auth_alg;
- wk->probe_auth.privacy = req->bss->capability & WLAN_CAPABILITY_PRIVACY;
+ wk->state = IEEE80211_MGD_STATE_PROBE;
+ wk->auth_alg = auth_alg;
+ wk->timeout = jiffies; /* run right away */
- /* if we already have a probe, don't probe again */
- if (req->bss->proberesp_ies)
- wk->type = IEEE80211_WORK_AUTH;
- else
- wk->type = IEEE80211_WORK_DIRECT_PROBE;
- wk->chan = req->bss->channel;
- wk->sdata = sdata;
- wk->done = ieee80211_probe_auth_done;
+ /*
+ * XXX: if still associated need to tell AP that we're going
+ * to sleep and then change channel etc.
+ */
+ sdata->local->oper_channel = req->bss->channel;
+ ieee80211_hw_config(sdata->local, 0);
+
+ mutex_lock(&ifmgd->mtx);
+ list_add(&wk->list, &sdata->u.mgd.work_list);
+ mutex_unlock(&ifmgd->mtx);
- ieee80211_add_work(wk);
+ ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work);
return 0;
}
-static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
- struct sk_buff *skb)
+int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_assoc_request *req)
{
- struct ieee80211_mgmt *mgmt;
- u16 status;
-
- if (!skb) {
- cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta);
- return WORK_DONE_DESTROY;
- }
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ struct ieee80211_mgd_work *wk, *found = NULL;
+ int i, err;
- mgmt = (void *)skb->data;
- status = le16_to_cpu(mgmt->u.assoc_resp.status_code);
+ mutex_lock(&ifmgd->mtx);
- if (status == WLAN_STATUS_SUCCESS) {
- mutex_lock(&wk->sdata->u.mgd.mtx);
- if (!ieee80211_assoc_success(wk, mgmt, skb->len)) {
- mutex_unlock(&wk->sdata->u.mgd.mtx);
- /* oops -- internal error -- send timeout for now */
- cfg80211_send_assoc_timeout(wk->sdata->dev,
- wk->filter_ta);
- return WORK_DONE_DESTROY;
+ list_for_each_entry(wk, &ifmgd->work_list, list) {
+ if (&wk->bss->cbss == req->bss &&
+ wk->state == IEEE80211_MGD_STATE_IDLE) {
+ found = wk;
+ break;
}
- mutex_unlock(&wk->sdata->u.mgd.mtx);
}
- cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len);
- return WORK_DONE_DESTROY;
-}
+ if (!found) {
+ err = -ENOLINK;
+ goto out;
+ }
-int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
- struct cfg80211_assoc_request *req)
-{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct ieee80211_bss *bss = (void *)req->bss->priv;
- struct ieee80211_work *wk;
- const u8 *ssid;
- int i;
+ list_del(&found->list);
- mutex_lock(&ifmgd->mtx);
- if (ifmgd->associated) {
- mutex_unlock(&ifmgd->mtx);
- return -EALREADY;
+ wk = krealloc(found, sizeof(*wk) + req->ie_len, GFP_KERNEL);
+ if (!wk) {
+ list_add(&found->list, &ifmgd->work_list);
+ err = -ENOMEM;
+ goto out;
}
- mutex_unlock(&ifmgd->mtx);
- wk = kzalloc(sizeof(*wk) + req->ie_len, GFP_KERNEL);
- if (!wk)
- return -ENOMEM;
+ list_add(&wk->list, &ifmgd->work_list);
ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N;
- ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
for (i = 0; i < req->crypto.n_ciphers_pairwise; i++)
if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 ||
@@ -1911,6 +2474,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104)
ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
+ sdata->local->oper_channel = req->bss->channel;
+ ieee80211_hw_config(sdata->local, 0);
if (req->ie && req->ie_len) {
memcpy(wk->ie, req->ie, req->ie_len);
@@ -1918,55 +2483,12 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
} else
wk->ie_len = 0;
- wk->assoc.bss = req->bss;
-
- memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN);
-
- /* new association always uses requested smps mode */
- if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) {
- if (ifmgd->powersave)
- ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC;
- else
- ifmgd->ap_smps = IEEE80211_SMPS_OFF;
- } else
- ifmgd->ap_smps = ifmgd->req_smps;
-
- wk->assoc.smps = ifmgd->ap_smps;
- /*
- * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode.
- * We still associate in non-HT mode (11a/b/g) if any one of these
- * ciphers is configured as pairwise.
- * We can set this to true for non-11n hardware, that'll be checked
- * separately along with the peer capabilities.
- */
- wk->assoc.use_11n = !(ifmgd->flags & IEEE80211_STA_DISABLE_11N);
- wk->assoc.capability = req->bss->capability;
- wk->assoc.wmm_used = bss->wmm_used;
- wk->assoc.supp_rates = bss->supp_rates;
- wk->assoc.supp_rates_len = bss->supp_rates_len;
- wk->assoc.ht_information_ie =
- ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_INFORMATION);
-
- if (bss->wmm_used && bss->uapsd_supported &&
- (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) {
- wk->assoc.uapsd_used = true;
- ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED;
- } else {
- wk->assoc.uapsd_used = false;
- ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED;
- }
-
- ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
- memcpy(wk->assoc.ssid, ssid + 2, ssid[1]);
- wk->assoc.ssid_len = ssid[1];
-
if (req->prev_bssid)
- memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN);
+ memcpy(wk->prev_bssid, req->prev_bssid, ETH_ALEN);
- wk->type = IEEE80211_WORK_ASSOC;
- wk->chan = req->bss->channel;
- wk->sdata = sdata;
- wk->done = ieee80211_assoc_done;
+ wk->state = IEEE80211_MGD_STATE_ASSOC;
+ wk->tries = 0;
+ wk->timeout = jiffies; /* run right away */
if (req->use_mfp) {
ifmgd->mfp = IEEE80211_MFP_REQUIRED;
@@ -1981,65 +2503,69 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
else
ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT;
- ieee80211_add_work(wk);
- return 0;
+ ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work);
+
+ err = 0;
+
+ out:
+ mutex_unlock(&ifmgd->mtx);
+ return err;
}
int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
struct cfg80211_deauth_request *req,
void *cookie)
{
- struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct ieee80211_work *wk;
- const u8 *bssid = req->bss->bssid;
+ struct ieee80211_mgd_work *wk;
+ const u8 *bssid = NULL;
+ bool not_auth_yet = false;
mutex_lock(&ifmgd->mtx);
- if (ifmgd->associated == req->bss) {
+ if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) {
bssid = req->bss->bssid;
- ieee80211_set_disassoc(sdata);
- mutex_unlock(&ifmgd->mtx);
- } else {
- bool not_auth_yet = false;
-
- mutex_unlock(&ifmgd->mtx);
-
- mutex_lock(&local->work_mtx);
- list_for_each_entry(wk, &local->work_list, list) {
- if (wk->sdata != sdata)
- continue;
-
- if (wk->type != IEEE80211_WORK_DIRECT_PROBE &&
- wk->type != IEEE80211_WORK_AUTH)
- continue;
-
- if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN))
- continue;
-
- not_auth_yet = wk->type == IEEE80211_WORK_DIRECT_PROBE;
- list_del_rcu(&wk->list);
- free_work(wk);
+ ieee80211_set_disassoc(sdata, true);
+ } else list_for_each_entry(wk, &ifmgd->work_list, list) {
+ if (&wk->bss->cbss == req->bss) {
+ bssid = req->bss->bssid;
+ if (wk->state == IEEE80211_MGD_STATE_PROBE)
+ not_auth_yet = true;
+ list_del(&wk->list);
+ kfree(wk);
break;
}
- mutex_unlock(&local->work_mtx);
+ }
- /*
- * If somebody requests authentication and we haven't
- * sent out an auth frame yet there's no need to send
- * out a deauth frame either. If the state was PROBE,
- * then this is the case. If it's AUTH we have sent a
- * frame, and if it's IDLE we have completed the auth
- * process already.
- */
- if (not_auth_yet) {
- __cfg80211_auth_canceled(sdata->dev, bssid);
- return 0;
- }
+ /*
+ * If somebody requests authentication and we haven't
+ * sent out an auth frame yet there's no need to send
+ * out a deauth frame either. If the state was PROBE,
+ * then this is the case. If it's AUTH we have sent a
+ * frame, and if it's IDLE we have completed the auth
+ * process already.
+ */
+ if (not_auth_yet) {
+ mutex_unlock(&ifmgd->mtx);
+ __cfg80211_auth_canceled(sdata->dev, bssid);
+ return 0;
}
+ /*
+ * cfg80211 should catch this ... but it's racy since
+ * we can receive a deauth frame, process it, hand it
+ * to cfg80211 while that's in a locked section already
+ * trying to tell us that the user wants to disconnect.
+ */
+ if (!bssid) {
+ mutex_unlock(&ifmgd->mtx);
+ return -ENOLINK;
+ }
+
+ mutex_unlock(&ifmgd->mtx);
+
printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n",
- sdata->name, bssid, req->reason_code);
+ sdata->dev->name, bssid, req->reason_code);
ieee80211_send_deauth_disassoc(sdata, bssid,
IEEE80211_STYPE_DEAUTH, req->reason_code,
@@ -2064,15 +2590,15 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
* to cfg80211 while that's in a locked section already
* trying to tell us that the user wants to disconnect.
*/
- if (ifmgd->associated != req->bss) {
+ if (&ifmgd->associated->cbss != req->bss) {
mutex_unlock(&ifmgd->mtx);
return -ENOLINK;
}
printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n",
- sdata->name, req->bss->bssid, req->reason_code);
+ sdata->dev->name, req->bss->bssid, req->reason_code);
- ieee80211_set_disassoc(sdata);
+ ieee80211_set_disassoc(sdata, false);
mutex_unlock(&ifmgd->mtx);
@@ -2084,38 +2610,3 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
return 0;
}
-
-int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- const u8 *buf, size_t len, u64 *cookie)
-{
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct sk_buff *skb;
-
- /* Check that we are on the requested channel for transmission */
- if ((chan != local->tmp_channel ||
- channel_type != local->tmp_channel_type) &&
- (chan != local->oper_channel ||
- channel_type != local->oper_channel_type))
- return -EBUSY;
-
- skb = dev_alloc_skb(local->hw.extra_tx_headroom + len);
- if (!skb)
- return -ENOMEM;
- skb_reserve(skb, local->hw.extra_tx_headroom);
-
- memcpy(skb_put(skb, len), buf, len);
-
- if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED))
- IEEE80211_SKB_CB(skb)->flags |=
- IEEE80211_TX_INTFL_DONT_ENCRYPT;
- IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX |
- IEEE80211_TX_CTL_REQ_TX_STATUS;
- skb->dev = sdata->dev;
- ieee80211_tx_skb(sdata, skb);
-
- *cookie = (unsigned long) skb;
- return 0;
-}
diff --git a/trunk/net/mac80211/offchannel.c b/trunk/net/mac80211/offchannel.c
deleted file mode 100644
index c36b1911987a..000000000000
--- a/trunk/net/mac80211/offchannel.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Off-channel operation helpers
- *
- * Copyright 2003, Jouni Malinen
- * Copyright 2004, Instant802 Networks, Inc.
- * Copyright 2005, Devicescape Software, Inc.
- * Copyright 2006-2007 Jiri Benc
- * Copyright 2007, Michael Wu
- * Copyright 2009 Johannes Berg
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include
-#include "ieee80211_i.h"
-
-/*
- * inform AP that we will go to sleep so that it will buffer the frames
- * while we scan
- */
-static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_local *local = sdata->local;
-
- local->offchannel_ps_enabled = false;
-
- /* FIXME: what to do when local->pspolling is true? */
-
- del_timer_sync(&local->dynamic_ps_timer);
- cancel_work_sync(&local->dynamic_ps_enable_work);
-
- if (local->hw.conf.flags & IEEE80211_CONF_PS) {
- local->offchannel_ps_enabled = true;
- local->hw.conf.flags &= ~IEEE80211_CONF_PS;
- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
- }
-
- if (!(local->offchannel_ps_enabled) ||
- !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))
- /*
- * If power save was enabled, no need to send a nullfunc
- * frame because AP knows that we are sleeping. But if the
- * hardware is creating the nullfunc frame for power save
- * status (ie. IEEE80211_HW_PS_NULLFUNC_STACK is not
- * enabled) and power save was enabled, the firmware just
- * sent a null frame with power save disabled. So we need
- * to send a new nullfunc frame to inform the AP that we
- * are again sleeping.
- */
- ieee80211_send_nullfunc(local, sdata, 1);
-}
-
-/* inform AP that we are awake again, unless power save is enabled */
-static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_local *local = sdata->local;
-
- if (!local->ps_sdata)
- ieee80211_send_nullfunc(local, sdata, 0);
- else if (local->offchannel_ps_enabled) {
- /*
- * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware
- * will send a nullfunc frame with the powersave bit set
- * even though the AP already knows that we are sleeping.
- * This could be avoided by sending a null frame with power
- * save bit disabled before enabling the power save, but
- * this doesn't gain anything.
- *
- * When IEEE80211_HW_PS_NULLFUNC_STACK is enabled, no need
- * to send a nullfunc frame because AP already knows that
- * we are sleeping, let's just enable power save mode in
- * hardware.
- */
- local->hw.conf.flags |= IEEE80211_CONF_PS;
- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
- } else if (local->hw.conf.dynamic_ps_timeout > 0) {
- /*
- * If IEEE80211_CONF_PS was not set and the dynamic_ps_timer
- * had been running before leaving the operating channel,
- * restart the timer now and send a nullfunc frame to inform
- * the AP that we are awake.
- */
- ieee80211_send_nullfunc(local, sdata, 0);
- mod_timer(&local->dynamic_ps_timer, jiffies +
- msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
- }
-}
-
-void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local)
-{
- struct ieee80211_sub_if_data *sdata;
-
- mutex_lock(&local->iflist_mtx);
- list_for_each_entry(sdata, &local->interfaces, list) {
- if (!ieee80211_sdata_running(sdata))
- continue;
-
- /* disable beaconing */
- if (sdata->vif.type == NL80211_IFTYPE_AP ||
- sdata->vif.type == NL80211_IFTYPE_ADHOC ||
- sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
- ieee80211_bss_info_change_notify(
- sdata, BSS_CHANGED_BEACON_ENABLED);
-
- /*
- * only handle non-STA interfaces here, STA interfaces
- * are handled in ieee80211_offchannel_stop_station(),
- * e.g., from the background scan state machine.
- *
- * In addition, do not stop monitor interface to allow it to be
- * used from user space controlled off-channel operations.
- */
- if (sdata->vif.type != NL80211_IFTYPE_STATION &&
- sdata->vif.type != NL80211_IFTYPE_MONITOR)
- netif_tx_stop_all_queues(sdata->dev);
- }
- mutex_unlock(&local->iflist_mtx);
-}
-
-void ieee80211_offchannel_stop_station(struct ieee80211_local *local)
-{
- struct ieee80211_sub_if_data *sdata;
-
- /*
- * notify the AP about us leaving the channel and stop all STA interfaces
- */
- mutex_lock(&local->iflist_mtx);
- list_for_each_entry(sdata, &local->interfaces, list) {
- if (!ieee80211_sdata_running(sdata))
- continue;
-
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- netif_tx_stop_all_queues(sdata->dev);
- if (sdata->u.mgd.associated)
- ieee80211_offchannel_ps_enable(sdata);
- }
- }
- mutex_unlock(&local->iflist_mtx);
-}
-
-void ieee80211_offchannel_return(struct ieee80211_local *local,
- bool enable_beaconing)
-{
- struct ieee80211_sub_if_data *sdata;
-
- mutex_lock(&local->iflist_mtx);
- list_for_each_entry(sdata, &local->interfaces, list) {
- if (!ieee80211_sdata_running(sdata))
- continue;
-
- /* Tell AP we're back */
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- if (sdata->u.mgd.associated)
- ieee80211_offchannel_ps_disable(sdata);
- }
-
- if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
- netif_tx_wake_all_queues(sdata->dev);
-
- /* re-enable beaconing */
- if (enable_beaconing &&
- (sdata->vif.type == NL80211_IFTYPE_AP ||
- sdata->vif.type == NL80211_IFTYPE_ADHOC ||
- sdata->vif.type == NL80211_IFTYPE_MESH_POINT))
- ieee80211_bss_info_change_notify(
- sdata, BSS_CHANGED_BEACON_ENABLED);
- }
- mutex_unlock(&local->iflist_mtx);
-}
diff --git a/trunk/net/mac80211/pm.c b/trunk/net/mac80211/pm.c
index 0e64484e861c..e535f1c988fe 100644
--- a/trunk/net/mac80211/pm.c
+++ b/trunk/net/mac80211/pm.c
@@ -10,7 +10,9 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
{
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_if_init_conf conf;
struct sta_info *sta;
+ unsigned long flags;
ieee80211_scan_cancel(local);
@@ -54,21 +56,22 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
rcu_read_unlock();
/* remove STAs */
- mutex_lock(&local->sta_mtx);
+ spin_lock_irqsave(&local->sta_lock, flags);
list_for_each_entry(sta, &local->sta_list, list) {
- if (sta->uploaded) {
+ if (local->ops->sta_notify) {
sdata = sta->sdata;
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
sdata = container_of(sdata->bss,
struct ieee80211_sub_if_data,
u.ap);
- drv_sta_remove(local, sdata, &sta->sta);
+ drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE,
+ &sta->sta);
}
mesh_plink_quiesce(sta);
}
- mutex_unlock(&local->sta_mtx);
+ spin_unlock_irqrestore(&local->sta_lock, flags);
/* remove all interfaces */
list_for_each_entry(sdata, &local->interfaces, list) {
@@ -90,14 +93,17 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
break;
}
- if (!ieee80211_sdata_running(sdata))
+ if (!netif_running(sdata->dev))
continue;
/* disable beaconing */
ieee80211_bss_info_change_notify(sdata,
BSS_CHANGED_BEACON_ENABLED);
- drv_remove_interface(local, &sdata->vif);
+ conf.vif = &sdata->vif;
+ conf.type = sdata->vif.type;
+ conf.mac_addr = sdata->dev->dev_addr;
+ drv_remove_interface(local, &conf);
}
/* stop hardware - this must stop RX */
diff --git a/trunk/net/mac80211/rate.c b/trunk/net/mac80211/rate.c
index 0b299d236fa1..12a2bff7dcdb 100644
--- a/trunk/net/mac80211/rate.c
+++ b/trunk/net/mac80211/rate.c
@@ -145,7 +145,7 @@ static const struct file_operations rcname_ops = {
};
#endif
-static struct rate_control_ref *rate_control_alloc(const char *name,
+struct rate_control_ref *rate_control_alloc(const char *name,
struct ieee80211_local *local)
{
struct dentry *debugfsdir = NULL;
@@ -207,27 +207,6 @@ static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc)
return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc));
}
-static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, u8 max_rate_idx)
-{
- u8 i;
-
- if (basic_rates == 0)
- return; /* assume basic rates unknown and accept rate */
- if (*idx < 0)
- return;
- if (basic_rates & (1 << *idx))
- return; /* selected rate is a basic rate */
-
- for (i = *idx + 1; i <= max_rate_idx; i++) {
- if (basic_rates & (1 << i)) {
- *idx = i;
- return;
- }
- }
-
- /* could not find a basic rate; use original selection */
-}
-
bool rate_control_send_low(struct ieee80211_sta *sta,
void *priv_sta,
struct ieee80211_tx_rate_control *txrc)
@@ -239,48 +218,12 @@ bool rate_control_send_low(struct ieee80211_sta *sta,
info->control.rates[0].count =
(info->flags & IEEE80211_TX_CTL_NO_ACK) ?
1 : txrc->hw->max_rate_tries;
- if (!sta && txrc->ap)
- rc_send_low_broadcast(&info->control.rates[0].idx,
- txrc->bss_conf->basic_rates,
- txrc->sband->n_bitrates);
return true;
}
return false;
}
EXPORT_SYMBOL(rate_control_send_low);
-static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
- int n_bitrates, u32 mask)
-{
- int j;
-
- /* See whether the selected rate or anything below it is allowed. */
- for (j = rate->idx; j >= 0; j--) {
- if (mask & (1 << j)) {
- /* Okay, found a suitable rate. Use it. */
- rate->idx = j;
- return;
- }
- }
-
- /* Try to find a higher rate that would be allowed */
- for (j = rate->idx + 1; j < n_bitrates; j++) {
- if (mask & (1 << j)) {
- /* Okay, found a suitable rate. Use it. */
- rate->idx = j;
- return;
- }
- }
-
- /*
- * Uh.. No suitable rate exists. This should not really happen with
- * sane TX rate mask configurations. However, should someone manage to
- * configure supported rates and TX rate mask in incompatible way,
- * allow the frame to be transmitted with whatever the rate control
- * selected.
- */
-}
-
void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta,
struct ieee80211_tx_rate_control *txrc)
@@ -290,7 +233,6 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sta *ista = NULL;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb);
int i;
- u32 mask;
if (sta) {
ista = &sta->sta;
@@ -306,31 +248,23 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
if (sdata->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)
return;
- ref->ops->get_rate(ref->priv, ista, priv_sta, txrc);
+ if (sta && sdata->force_unicast_rateidx > -1) {
+ info->control.rates[0].idx = sdata->force_unicast_rateidx;
+ } else {
+ ref->ops->get_rate(ref->priv, ista, priv_sta, txrc);
+ info->flags |= IEEE80211_TX_INTFL_RCALGO;
+ }
/*
- * Try to enforce the rateidx mask the user wanted. skip this if the
- * default mask (allow all rates) is used to save some processing for
- * the common case.
+ * try to enforce the maximum rate the user wanted
*/
- mask = sdata->rc_rateidx_mask[info->band];
- if (mask != (1 << txrc->sband->n_bitrates) - 1) {
- if (sta) {
- /* Filter out rates that the STA does not support */
- mask &= sta->sta.supp_rates[info->band];
- }
- /*
- * Make sure the rate index selected for each TX rate is
- * included in the configured mask and change the rate indexes
- * if needed.
- */
+ if (sdata->max_ratectrl_rateidx > -1)
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
- /* Rate masking supports only legacy rates for now */
if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS)
continue;
- rate_idx_match_mask(&info->control.rates[i],
- txrc->sband->n_bitrates, mask);
- }
+ info->control.rates[i].idx =
+ min_t(s8, info->control.rates[i].idx,
+ sdata->max_ratectrl_rateidx);
}
BUG_ON(info->control.rates[0].idx < 0);
diff --git a/trunk/net/mac80211/rate.h b/trunk/net/mac80211/rate.h
index b6108bca96d4..cb9bd1f65e27 100644
--- a/trunk/net/mac80211/rate.h
+++ b/trunk/net/mac80211/rate.h
@@ -26,6 +26,10 @@ struct rate_control_ref {
struct kref kref;
};
+/* Get a reference to the rate control algorithm. If `name' is NULL, get the
+ * first available algorithm. */
+struct rate_control_ref *rate_control_alloc(const char *name,
+ struct ieee80211_local *local);
void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta,
struct ieee80211_tx_rate_control *txrc);
@@ -40,11 +44,10 @@ static inline void rate_control_tx_status(struct ieee80211_local *local,
struct rate_control_ref *ref = local->rate_ctrl;
struct ieee80211_sta *ista = &sta->sta;
void *priv_sta = sta->rate_ctrl_priv;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- if (!ref)
- return;
-
- ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb);
+ if (likely(info->flags & IEEE80211_TX_INTFL_RCALGO))
+ ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb);
}
@@ -112,8 +115,7 @@ static inline void rate_control_remove_sta_debugfs(struct sta_info *sta)
#endif
}
-/* Get a reference to the rate control algorithm. If `name' is NULL, get the
- * first available algorithm. */
+/* functions for rate control related to a device */
int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
const char *name);
void rate_control_deinitialize(struct ieee80211_local *local);
diff --git a/trunk/net/mac80211/rc80211_pid_algo.c b/trunk/net/mac80211/rc80211_pid_algo.c
index 2652a374974e..29bc4c516238 100644
--- a/trunk/net/mac80211/rc80211_pid_algo.c
+++ b/trunk/net/mac80211/rc80211_pid_algo.c
@@ -157,7 +157,9 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
/* In case nothing happened during the previous control interval, turn
* the sharpening factor on. */
- period = msecs_to_jiffies(pinfo->sampling_period);
+ period = (HZ * pinfo->sampling_period + 500) / 1000;
+ if (!period)
+ period = 1;
if (jiffies - spinfo->last_sample > 2 * period)
spinfo->sharp_cnt = pinfo->sharpen_duration;
@@ -250,7 +252,9 @@ static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_ba
}
/* Update PID controller state. */
- period = msecs_to_jiffies(pinfo->sampling_period);
+ period = (HZ * pinfo->sampling_period + 500) / 1000;
+ if (!period)
+ period = 1;
if (time_after(jiffies, spinfo->last_sample + period))
rate_control_pid_sample(pinfo, sband, sta, spinfo);
}
diff --git a/trunk/net/mac80211/rx.c b/trunk/net/mac80211/rx.c
index b5c48de81d8b..82a30c1bf3ab 100644
--- a/trunk/net/mac80211/rx.c
+++ b/trunk/net/mac80211/rx.c
@@ -2,7 +2,7 @@
* Copyright 2002-2005, Instant802 Networks, Inc.
* Copyright 2005-2006, Devicescape Software, Inc.
* Copyright 2006-2007 Jiri Benc
- * Copyright 2007-2010 Johannes Berg
+ * Copyright 2007 Johannes Berg
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -283,13 +283,13 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
skb->protocol = htons(ETH_P_802_2);
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
- if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
+ if (!netif_running(sdata->dev))
continue;
- if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)
+ if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
continue;
- if (!ieee80211_sdata_running(sdata))
+ if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)
continue;
if (prev_dev) {
@@ -361,9 +361,7 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
* boundary. In the case of regular frames, this simply means aligning the
* payload to a four-byte boundary (because either the IP header is directly
* contained, or IV/RFC1042 headers that have a length divisible by four are
- * in front of it). If the payload data is not properly aligned and the
- * architecture doesn't support efficient unaligned operations, mac80211
- * will align the data.
+ * in front of it).
*
* With A-MSDU frames, however, the payload data address must yield two modulo
* four because there are 14-byte 802.3 headers within the A-MSDU frames that
@@ -377,10 +375,25 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
*/
static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx)
{
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- WARN_ONCE((unsigned long)rx->skb->data & 1,
- "unaligned packet at 0x%p\n", rx->skb->data);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
+ int hdrlen;
+
+#ifndef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT
+ return;
#endif
+
+ if (WARN_ONCE((unsigned long)rx->skb->data & 1,
+ "unaligned packet at 0x%p\n", rx->skb->data))
+ return;
+
+ if (!ieee80211_is_data_present(hdr->frame_control))
+ return;
+
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
+ if (rx->flags & IEEE80211_RX_AMSDU)
+ hdrlen += ETH_HLEN;
+ WARN_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3,
+ "unaligned IP payload at 0x%p\n", rx->skb->data + hdrlen);
}
@@ -463,7 +476,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
- char *dev_addr = rx->sdata->vif.addr;
+ char *dev_addr = rx->sdata->dev->dev_addr;
if (ieee80211_is_data(hdr->frame_control)) {
if (is_multicast_ether_addr(hdr->addr1)) {
@@ -1008,10 +1021,10 @@ static void ap_sta_ps_start(struct sta_info *sta)
atomic_inc(&sdata->bss->num_sta_ps);
set_sta_flags(sta, WLAN_STA_PS_STA);
- drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
+ drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta);
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n",
- sdata->name, sta->sta.addr, sta->sta.aid);
+ sdata->dev->name, sta->sta.addr, sta->sta.aid);
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
}
@@ -1025,13 +1038,13 @@ static void ap_sta_ps_end(struct sta_info *sta)
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n",
- sdata->name, sta->sta.addr, sta->sta.aid);
+ sdata->dev->name, sta->sta.addr, sta->sta.aid);
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) {
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n",
- sdata->name, sta->sta.addr, sta->sta.aid);
+ sdata->dev->name, sta->sta.addr, sta->sta.aid);
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
return;
}
@@ -1111,18 +1124,6 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
if (ieee80211_is_nullfunc(hdr->frame_control) ||
ieee80211_is_qos_nullfunc(hdr->frame_control)) {
I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc);
-
- /*
- * If we receive a 4-addr nullfunc frame from a STA
- * that was not moved to a 4-addr STA vlan yet, drop
- * the frame to the monitor interface, to make sure
- * that hostapd sees it
- */
- if (ieee80211_has_a4(hdr->frame_control) &&
- (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
- (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
- !rx->sdata->u.vlan.sta)))
- return RX_DROP_MONITOR;
/*
* Update counter and free packet here to avoid
* counting this as a dropped packed.
@@ -1155,7 +1156,7 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
printk(KERN_DEBUG "%s: RX reassembly removed oldest "
"fragment entry (idx=%d age=%lu seq=%d last_frag=%d "
"addr1=%pM addr2=%pM\n",
- sdata->name, idx,
+ sdata->dev->name, idx,
jiffies - entry->first_frag_time, entry->seq,
entry->last_frag, hdr->addr1, hdr->addr2);
#endif
@@ -1397,21 +1398,6 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
ieee80211_is_data(fc) &&
(rx->key || rx->sdata->drop_unencrypted)))
return -EACCES;
-
- return 0;
-}
-
-static int
-ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
-{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
- __le16 fc = hdr->frame_control;
- int res;
-
- res = ieee80211_drop_unencrypted(rx, fc);
- if (unlikely(res))
- return res;
-
if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) {
if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
rx->key))
@@ -1438,6 +1424,7 @@ static int
__ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
{
struct ieee80211_sub_if_data *sdata = rx->sdata;
+ struct net_device *dev = sdata->dev;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
if (ieee80211_has_a4(hdr->frame_control) &&
@@ -1449,7 +1436,7 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
(sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.use_4addr)))
return -1;
- return ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type);
+ return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type);
}
/*
@@ -1466,7 +1453,7 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc)
* of whether the frame was encrypted or not.
*/
if (ehdr->h_proto == htons(ETH_P_PAE) &&
- (compare_ether_addr(ehdr->h_dest, rx->sdata->vif.addr) == 0 ||
+ (compare_ether_addr(ehdr->h_dest, rx->sdata->dev->dev_addr) == 0 ||
compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0))
return true;
@@ -1485,6 +1472,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
{
struct ieee80211_sub_if_data *sdata = rx->sdata;
struct net_device *dev = sdata->dev;
+ struct ieee80211_local *local = rx->local;
struct sk_buff *skb, *xmit_skb;
struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
struct sta_info *dsta;
@@ -1507,8 +1495,8 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
printk(KERN_DEBUG "%s: failed to clone "
"multicast frame\n", dev->name);
} else {
- dsta = sta_info_get(sdata, skb->data);
- if (dsta) {
+ dsta = sta_info_get(local, skb->data);
+ if (dsta && dsta->sdata->dev == dev) {
/*
* The destination station is associated to
* this AP (in this VLAN), so send the frame
@@ -1524,7 +1512,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
if (skb) {
int align __maybe_unused;
-#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+#if defined(CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT) || !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
/*
* 'align' will only take the values 0 or 2 here
* since all frames are required to be aligned
@@ -1568,10 +1556,16 @@ static ieee80211_rx_result debug_noinline
ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
{
struct net_device *dev = rx->sdata->dev;
- struct sk_buff *skb = rx->skb;
+ struct ieee80211_local *local = rx->local;
+ u16 ethertype;
+ u8 *payload;
+ struct sk_buff *skb = rx->skb, *frame = NULL;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
__le16 fc = hdr->frame_control;
- struct sk_buff_head frame_list;
+ const struct ethhdr *eth;
+ int remaining, err;
+ u8 dst[ETH_ALEN];
+ u8 src[ETH_ALEN];
if (unlikely(!ieee80211_is_data(fc)))
return RX_CONTINUE;
@@ -1582,34 +1576,94 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
if (!(rx->flags & IEEE80211_RX_AMSDU))
return RX_CONTINUE;
- if (ieee80211_has_a4(hdr->frame_control) &&
- rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
- !rx->sdata->u.vlan.sta)
+ err = __ieee80211_data_to_8023(rx);
+ if (unlikely(err))
return RX_DROP_UNUSABLE;
- if (is_multicast_ether_addr(hdr->addr1) &&
- ((rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
- rx->sdata->u.vlan.sta) ||
- (rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
- rx->sdata->u.mgd.use_4addr)))
+ skb->dev = dev;
+
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
+
+ /* skip the wrapping header */
+ eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr));
+ if (!eth)
return RX_DROP_UNUSABLE;
- skb->dev = dev;
- __skb_queue_head_init(&frame_list);
+ while (skb != frame) {
+ u8 padding;
+ __be16 len = eth->h_proto;
+ unsigned int subframe_len = sizeof(struct ethhdr) + ntohs(len);
+
+ remaining = skb->len;
+ memcpy(dst, eth->h_dest, ETH_ALEN);
+ memcpy(src, eth->h_source, ETH_ALEN);
+
+ padding = ((4 - subframe_len) & 0x3);
+ /* the last MSDU has no padding */
+ if (subframe_len > remaining)
+ return RX_DROP_UNUSABLE;
- ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
- rx->sdata->vif.type,
- rx->local->hw.extra_tx_headroom);
+ skb_pull(skb, sizeof(struct ethhdr));
+ /* if last subframe reuse skb */
+ if (remaining <= subframe_len + padding)
+ frame = skb;
+ else {
+ /*
+ * Allocate and reserve two bytes more for payload
+ * alignment since sizeof(struct ethhdr) is 14.
+ */
+ frame = dev_alloc_skb(
+ ALIGN(local->hw.extra_tx_headroom, 4) +
+ subframe_len + 2);
+
+ if (frame == NULL)
+ return RX_DROP_UNUSABLE;
+
+ skb_reserve(frame,
+ ALIGN(local->hw.extra_tx_headroom, 4) +
+ sizeof(struct ethhdr) + 2);
+ memcpy(skb_put(frame, ntohs(len)), skb->data,
+ ntohs(len));
+
+ eth = (struct ethhdr *) skb_pull(skb, ntohs(len) +
+ padding);
+ if (!eth) {
+ dev_kfree_skb(frame);
+ return RX_DROP_UNUSABLE;
+ }
+ }
- while (!skb_queue_empty(&frame_list)) {
- rx->skb = __skb_dequeue(&frame_list);
+ skb_reset_network_header(frame);
+ frame->dev = dev;
+ frame->priority = skb->priority;
+ rx->skb = frame;
+
+ payload = frame->data;
+ ethertype = (payload[6] << 8) | payload[7];
+
+ if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&
+ ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
+ compare_ether_addr(payload,
+ bridge_tunnel_header) == 0)) {
+ /* remove RFC1042 or Bridge-Tunnel
+ * encapsulation and replace EtherType */
+ skb_pull(frame, 6);
+ memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
+ memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
+ } else {
+ memcpy(skb_push(frame, sizeof(__be16)),
+ &len, sizeof(__be16));
+ memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
+ memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
+ }
if (!ieee80211_frame_allowed(rx, fc)) {
- dev_kfree_skb(rx->skb);
+ if (skb == frame) /* last frame */
+ return RX_DROP_UNUSABLE;
+ dev_kfree_skb(frame);
continue;
}
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += rx->skb->len;
ieee80211_deliver_skb(rx);
}
@@ -1667,7 +1721,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
/* Frame has reached destination. Don't forward */
if (!is_multicast_ether_addr(hdr->addr1) &&
- compare_ether_addr(sdata->vif.addr, hdr->addr3) == 0)
+ compare_ether_addr(sdata->dev->dev_addr, hdr->addr3) == 0)
return RX_CONTINUE;
mesh_hdr->ttl--;
@@ -1684,10 +1738,10 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
if (!fwd_skb && net_ratelimit())
printk(KERN_DEBUG "%s: failed to clone mesh frame\n",
- sdata->name);
+ sdata->dev->name);
fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
- memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
+ memcpy(fwd_hdr->addr2, sdata->dev->dev_addr, ETH_ALEN);
info = IEEE80211_SKB_CB(fwd_skb);
memset(info, 0, sizeof(*info));
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
@@ -1734,7 +1788,6 @@ static ieee80211_rx_result debug_noinline
ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
{
struct ieee80211_sub_if_data *sdata = rx->sdata;
- struct ieee80211_local *local = rx->local;
struct net_device *dev = sdata->dev;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
__le16 fc = hdr->frame_control;
@@ -1766,13 +1819,6 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
dev->stats.rx_packets++;
dev->stats.rx_bytes += rx->skb->len;
- if (ieee80211_is_data(hdr->frame_control) &&
- !is_multicast_ether_addr(hdr->addr1) &&
- local->hw.conf.dynamic_ps_timeout > 0 && local->ps_sdata) {
- mod_timer(&local->dynamic_ps_timer, jiffies +
- msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
- }
-
ieee80211_deliver_skb(rx);
return RX_QUEUED;
@@ -1826,7 +1872,7 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb;
struct ieee80211_mgmt *resp;
- if (compare_ether_addr(mgmt->da, sdata->vif.addr) != 0) {
+ if (compare_ether_addr(mgmt->da, sdata->dev->dev_addr) != 0) {
/* Not to own unicast address */
return;
}
@@ -1850,7 +1896,7 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
resp = (struct ieee80211_mgmt *) skb_put(skb, 24);
memset(resp, 0, 24);
memcpy(resp->da, mgmt->sa, ETH_ALEN);
- memcpy(resp->sa, sdata->vif.addr, ETH_ALEN);
+ memcpy(resp->sa, sdata->dev->dev_addr, ETH_ALEN);
memcpy(resp->bssid, sdata->u.mgd.bssid, ETH_ALEN);
resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
@@ -1870,25 +1916,23 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
struct ieee80211_local *local = rx->local;
struct ieee80211_sub_if_data *sdata = rx->sdata;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
- struct sk_buff *nskb;
- struct ieee80211_rx_status *status;
int len = rx->skb->len;
if (!ieee80211_is_action(mgmt->frame_control))
return RX_CONTINUE;
- /* drop too small frames */
- if (len < IEEE80211_MIN_ACTION_SIZE)
- return RX_DROP_UNUSABLE;
-
- if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC)
- return RX_DROP_UNUSABLE;
+ if (!rx->sta)
+ return RX_DROP_MONITOR;
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
- return RX_DROP_UNUSABLE;
+ return RX_DROP_MONITOR;
- if (ieee80211_drop_unencrypted_mgmt(rx))
- return RX_DROP_UNUSABLE;
+ if (ieee80211_drop_unencrypted(rx, mgmt->frame_control))
+ return RX_DROP_MONITOR;
+
+ /* all categories we currently handle have action_code */
+ if (len < IEEE80211_MIN_ACTION_SIZE + 1)
+ return RX_DROP_MONITOR;
switch (mgmt->u.action.category) {
case WLAN_CATEGORY_BACK:
@@ -1901,11 +1945,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
sdata->vif.type != NL80211_IFTYPE_AP)
- break;
-
- /* verify action_code is present */
- if (len < IEEE80211_MIN_ACTION_SIZE + 1)
- break;
+ return RX_DROP_MONITOR;
switch (mgmt->u.action.u.addba_req.action_code) {
case WLAN_ACTION_ADDBA_REQ:
@@ -1913,49 +1953,45 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
sizeof(mgmt->u.action.u.addba_req)))
return RX_DROP_MONITOR;
ieee80211_process_addba_request(local, rx->sta, mgmt, len);
- goto handled;
+ break;
case WLAN_ACTION_ADDBA_RESP:
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.addba_resp)))
- break;
+ return RX_DROP_MONITOR;
ieee80211_process_addba_resp(local, rx->sta, mgmt, len);
- goto handled;
+ break;
case WLAN_ACTION_DELBA:
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.delba)))
- break;
+ return RX_DROP_MONITOR;
ieee80211_process_delba(sdata, rx->sta, mgmt, len);
- goto handled;
+ break;
}
break;
case WLAN_CATEGORY_SPECTRUM_MGMT:
if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ)
- break;
+ return RX_DROP_MONITOR;
if (sdata->vif.type != NL80211_IFTYPE_STATION)
- break;
-
- /* verify action_code is present */
- if (len < IEEE80211_MIN_ACTION_SIZE + 1)
- break;
+ return RX_DROP_MONITOR;
switch (mgmt->u.action.u.measurement.action_code) {
case WLAN_ACTION_SPCT_MSR_REQ:
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.measurement)))
- break;
+ return RX_DROP_MONITOR;
ieee80211_process_measurement_req(sdata, mgmt, len);
- goto handled;
+ break;
case WLAN_ACTION_SPCT_CHL_SWITCH:
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.chan_switch)))
- break;
+ return RX_DROP_MONITOR;
if (sdata->vif.type != NL80211_IFTYPE_STATION)
- break;
+ return RX_DROP_MONITOR;
if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN))
- break;
+ return RX_DROP_MONITOR;
return ieee80211_sta_rx_mgmt(sdata, rx->skb);
}
@@ -1963,64 +1999,30 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
case WLAN_CATEGORY_SA_QUERY:
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.sa_query)))
- break;
-
+ return RX_DROP_MONITOR;
switch (mgmt->u.action.u.sa_query.action) {
case WLAN_ACTION_SA_QUERY_REQUEST:
if (sdata->vif.type != NL80211_IFTYPE_STATION)
- break;
+ return RX_DROP_MONITOR;
ieee80211_process_sa_query_req(sdata, mgmt, len);
- goto handled;
+ break;
+ case WLAN_ACTION_SA_QUERY_RESPONSE:
+ /*
+ * SA Query response is currently only used in AP mode
+ * and it is processed in user space.
+ */
+ return RX_CONTINUE;
}
break;
- }
-
- /*
- * For AP mode, hostapd is responsible for handling any action
- * frames that we didn't handle, including returning unknown
- * ones. For all other modes we will return them to the sender,
- * setting the 0x80 bit in the action category, as required by
- * 802.11-2007 7.3.1.11.
- */
- if (sdata->vif.type == NL80211_IFTYPE_AP ||
- sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- return RX_DROP_MONITOR;
-
- /*
- * Getting here means the kernel doesn't know how to handle
- * it, but maybe userspace does ... include returned frames
- * so userspace can register for those to know whether ones
- * it transmitted were processed or returned.
- */
- status = IEEE80211_SKB_RXCB(rx->skb);
-
- if (sdata->vif.type == NL80211_IFTYPE_STATION &&
- cfg80211_rx_action(rx->sdata->dev, status->freq,
- rx->skb->data, rx->skb->len,
- GFP_ATOMIC))
- goto handled;
-
- /* do not return rejected action frames */
- if (mgmt->u.action.category & 0x80)
- return RX_DROP_UNUSABLE;
-
- nskb = skb_copy_expand(rx->skb, local->hw.extra_tx_headroom, 0,
- GFP_ATOMIC);
- if (nskb) {
- struct ieee80211_mgmt *mgmt = (void *)nskb->data;
-
- mgmt->u.action.category |= 0x80;
- memcpy(mgmt->da, mgmt->sa, ETH_ALEN);
- memcpy(mgmt->sa, rx->sdata->vif.addr, ETH_ALEN);
-
- memset(nskb->cb, 0, sizeof(nskb->cb));
+ default:
+ /* do not process rejected action frames */
+ if (mgmt->u.action.category & 0x80)
+ return RX_DROP_MONITOR;
- ieee80211_tx_skb(rx->sdata, nskb);
+ return RX_CONTINUE;
}
- handled:
- if (rx->sta)
- rx->sta->rx_packets++;
+ rx->sta->rx_packets++;
dev_kfree_skb(rx->skb);
return RX_QUEUED;
}
@@ -2029,17 +2031,13 @@ static ieee80211_rx_result debug_noinline
ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
{
struct ieee80211_sub_if_data *sdata = rx->sdata;
- ieee80211_rx_result rxs;
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
return RX_DROP_MONITOR;
- if (ieee80211_drop_unencrypted_mgmt(rx))
- return RX_DROP_UNUSABLE;
-
- rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb);
- if (rxs != RX_CONTINUE)
- return rxs;
+ if (ieee80211_drop_unencrypted(rx, mgmt->frame_control))
+ return RX_DROP_MONITOR;
if (ieee80211_vif_is_mesh(&sdata->vif))
return ieee80211_mesh_rx_mgmt(sdata, rx->skb);
@@ -2145,7 +2143,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
skb->protocol = htons(ETH_P_802_2);
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
- if (!ieee80211_sdata_running(sdata))
+ if (!netif_running(sdata->dev))
continue;
if (sdata->vif.type != NL80211_IFTYPE_MONITOR ||
@@ -2282,7 +2280,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
if (!bssid && !sdata->u.mgd.use_4addr)
return 0;
if (!multicast &&
- compare_ether_addr(sdata->vif.addr, hdr->addr1) != 0) {
+ compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) {
if (!(sdata->dev->flags & IFF_PROMISC))
return 0;
rx->flags &= ~IEEE80211_RX_RA_MATCH;
@@ -2299,7 +2297,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
return 0;
rx->flags &= ~IEEE80211_RX_RA_MATCH;
} else if (!multicast &&
- compare_ether_addr(sdata->vif.addr,
+ compare_ether_addr(sdata->dev->dev_addr,
hdr->addr1) != 0) {
if (!(sdata->dev->flags & IFF_PROMISC))
return 0;
@@ -2310,13 +2308,13 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
rate_idx = 0; /* TODO: HT rates */
else
rate_idx = status->rate_idx;
- rx->sta = ieee80211_ibss_add_sta(sdata, bssid,
- hdr->addr2, BIT(rate_idx), GFP_ATOMIC);
+ rx->sta = ieee80211_ibss_add_sta(sdata, bssid, hdr->addr2,
+ BIT(rate_idx));
}
break;
case NL80211_IFTYPE_MESH_POINT:
if (!multicast &&
- compare_ether_addr(sdata->vif.addr,
+ compare_ether_addr(sdata->dev->dev_addr,
hdr->addr1) != 0) {
if (!(sdata->dev->flags & IFF_PROMISC))
return 0;
@@ -2327,11 +2325,11 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_AP:
if (!bssid) {
- if (compare_ether_addr(sdata->vif.addr,
+ if (compare_ether_addr(sdata->dev->dev_addr,
hdr->addr1))
return 0;
} else if (!ieee80211_bssid_match(bssid,
- sdata->vif.addr)) {
+ sdata->dev->dev_addr)) {
if (!(rx->flags & IEEE80211_RX_IN_SCAN))
return 0;
rx->flags &= ~IEEE80211_RX_RA_MATCH;
@@ -2370,8 +2368,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
int prepares;
struct ieee80211_sub_if_data *prev = NULL;
struct sk_buff *skb_new;
- struct sta_info *sta, *tmp;
- bool found_sta = false;
hdr = (struct ieee80211_hdr *)skb->data;
memset(&rx, 0, sizeof(rx));
@@ -2388,87 +2384,68 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
ieee80211_parse_qos(&rx);
ieee80211_verify_alignment(&rx);
- if (ieee80211_is_data(hdr->frame_control)) {
- for_each_sta_info(local, hdr->addr2, sta, tmp) {
- rx.sta = sta;
- found_sta = true;
- rx.sdata = sta->sdata;
-
- rx.flags |= IEEE80211_RX_RA_MATCH;
- prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
- if (prepares) {
- if (status->flag & RX_FLAG_MMIC_ERROR) {
- if (rx.flags & IEEE80211_RX_RA_MATCH)
- ieee80211_rx_michael_mic_report(hdr, &rx);
- } else
- prev = rx.sdata;
- }
- }
- }
- if (!found_sta) {
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
- if (!ieee80211_sdata_running(sdata))
- continue;
-
- if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
- sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- continue;
-
- /*
- * frame is destined for this interface, but if it's
- * not also for the previous one we handle that after
- * the loop to avoid copying the SKB once too much
- */
+ rx.sta = sta_info_get(local, hdr->addr2);
+ if (rx.sta)
+ rx.sdata = rx.sta->sdata;
- if (!prev) {
- prev = sdata;
- continue;
- }
+ if (rx.sdata && ieee80211_is_data(hdr->frame_control)) {
+ rx.flags |= IEEE80211_RX_RA_MATCH;
+ prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
+ if (prepares) {
+ if (status->flag & RX_FLAG_MMIC_ERROR) {
+ if (rx.flags & IEEE80211_RX_RA_MATCH)
+ ieee80211_rx_michael_mic_report(hdr, &rx);
+ } else
+ prev = rx.sdata;
+ }
+ } else list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ if (!netif_running(sdata->dev))
+ continue;
- rx.sta = sta_info_get_bss(prev, hdr->addr2);
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ continue;
- rx.flags |= IEEE80211_RX_RA_MATCH;
- prepares = prepare_for_handlers(prev, &rx, hdr);
+ rx.flags |= IEEE80211_RX_RA_MATCH;
+ prepares = prepare_for_handlers(sdata, &rx, hdr);
- if (!prepares)
- goto next;
+ if (!prepares)
+ continue;
- if (status->flag & RX_FLAG_MMIC_ERROR) {
- rx.sdata = prev;
- if (rx.flags & IEEE80211_RX_RA_MATCH)
- ieee80211_rx_michael_mic_report(hdr,
- &rx);
- goto next;
- }
+ if (status->flag & RX_FLAG_MMIC_ERROR) {
+ rx.sdata = sdata;
+ if (rx.flags & IEEE80211_RX_RA_MATCH)
+ ieee80211_rx_michael_mic_report(hdr, &rx);
+ continue;
+ }
- /*
- * frame was destined for the previous interface
- * so invoke RX handlers for it
- */
+ /*
+ * frame is destined for this interface, but if it's not
+ * also for the previous one we handle that after the
+ * loop to avoid copying the SKB once too much
+ */
- skb_new = skb_copy(skb, GFP_ATOMIC);
- if (!skb_new) {
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: failed to copy "
- "multicast frame for %s\n",
- wiphy_name(local->hw.wiphy),
- prev->name);
- goto next;
- }
- ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate);
-next:
+ if (!prev) {
prev = sdata;
+ continue;
}
- if (prev) {
- rx.sta = sta_info_get_bss(prev, hdr->addr2);
-
- rx.flags |= IEEE80211_RX_RA_MATCH;
- prepares = prepare_for_handlers(prev, &rx, hdr);
+ /*
+ * frame was destined for the previous interface
+ * so invoke RX handlers for it
+ */
- if (!prepares)
- prev = NULL;
+ skb_new = skb_copy(skb, GFP_ATOMIC);
+ if (!skb_new) {
+ if (net_ratelimit())
+ printk(KERN_DEBUG "%s: failed to copy "
+ "multicast frame for %s\n",
+ wiphy_name(local->hw.wiphy),
+ prev->dev->name);
+ continue;
}
+ ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate);
+ prev = sdata;
}
if (prev)
ieee80211_invoke_rx_handlers(prev, &rx, skb, rate);
diff --git a/trunk/net/mac80211/scan.c b/trunk/net/mac80211/scan.c
index b822dce97867..bc17cf7d68db 100644
--- a/trunk/net/mac80211/scan.c
+++ b/trunk/net/mac80211/scan.c
@@ -12,6 +12,7 @@
* published by the Free Software Foundation.
*/
+#include
#include
#include
#include
@@ -28,19 +29,16 @@ struct ieee80211_bss *
ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
u8 *ssid, u8 ssid_len)
{
- struct cfg80211_bss *cbss;
-
- cbss = cfg80211_get_bss(local->hw.wiphy,
- ieee80211_get_channel(local->hw.wiphy, freq),
- bssid, ssid, ssid_len, 0, 0);
- if (!cbss)
- return NULL;
- return (void *)cbss->priv;
+ return (void *)cfg80211_get_bss(local->hw.wiphy,
+ ieee80211_get_channel(local->hw.wiphy,
+ freq),
+ bssid, ssid, ssid_len,
+ 0, 0);
}
static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss)
{
- struct ieee80211_bss *bss = (void *)cbss->priv;
+ struct ieee80211_bss *bss = (void *)cbss;
kfree(bss_mesh_id(bss));
kfree(bss_mesh_cfg(bss));
@@ -49,26 +47,7 @@ static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss)
void ieee80211_rx_bss_put(struct ieee80211_local *local,
struct ieee80211_bss *bss)
{
- if (!bss)
- return;
- cfg80211_put_bss(container_of((void *)bss, struct cfg80211_bss, priv));
-}
-
-static bool is_uapsd_supported(struct ieee802_11_elems *elems)
-{
- u8 qos_info;
-
- if (elems->wmm_info && elems->wmm_info_len == 7
- && elems->wmm_info[5] == 1)
- qos_info = elems->wmm_info[6];
- else if (elems->wmm_param && elems->wmm_param_len == 24
- && elems->wmm_param[5] == 1)
- qos_info = elems->wmm_param[6];
- else
- /* no valid wmm information or parameter element found */
- return false;
-
- return qos_info & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD;
+ cfg80211_put_bss((struct cfg80211_bss *)bss);
}
struct ieee80211_bss *
@@ -80,7 +59,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
struct ieee80211_channel *channel,
bool beacon)
{
- struct cfg80211_bss *cbss;
struct ieee80211_bss *bss;
int clen;
s32 signal = 0;
@@ -90,14 +68,13 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
signal = (rx_status->signal * 100) / local->hw.max_signal;
- cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel,
- mgmt, len, signal, GFP_ATOMIC);
+ bss = (void *)cfg80211_inform_bss_frame(local->hw.wiphy, channel,
+ mgmt, len, signal, GFP_ATOMIC);
- if (!cbss)
+ if (!bss)
return NULL;
- cbss->free_priv = ieee80211_rx_bss_free;
- bss = (void *)cbss->priv;
+ bss->cbss.free_priv = ieee80211_rx_bss_free;
/* save the ERP value so that it is available at association time */
if (elems->erp_info && elems->erp_info_len >= 1) {
@@ -111,6 +88,10 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
bss->dtim_period = tim_ie->dtim_period;
}
+ /* set default value for buggy AP/no TIM element */
+ if (bss->dtim_period == 0)
+ bss->dtim_period = 1;
+
bss->supp_rates_len = 0;
if (elems->supp_rates) {
clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
@@ -130,7 +111,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
}
bss->wmm_used = elems->wmm_param || elems->wmm_info;
- bss->uapsd_supported = is_uapsd_supported(elems);
if (!beacon)
bss->last_probe_resp = jiffies;
@@ -167,7 +147,7 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
presp = ieee80211_is_probe_resp(fc);
if (presp) {
/* ignore ProbeResp to foreign address */
- if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN))
+ if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
return RX_DROP_MONITOR;
presp = true;
@@ -240,9 +220,82 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
return true;
}
+/*
+ * inform AP that we will go to sleep so that it will buffer the frames
+ * while we scan
+ */
+static void ieee80211_scan_ps_enable(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_local *local = sdata->local;
+
+ local->scan_ps_enabled = false;
+
+ /* FIXME: what to do when local->pspolling is true? */
+
+ del_timer_sync(&local->dynamic_ps_timer);
+ cancel_work_sync(&local->dynamic_ps_enable_work);
+
+ if (local->hw.conf.flags & IEEE80211_CONF_PS) {
+ local->scan_ps_enabled = true;
+ local->hw.conf.flags &= ~IEEE80211_CONF_PS;
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+ }
+
+ if (!(local->scan_ps_enabled) ||
+ !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))
+ /*
+ * If power save was enabled, no need to send a nullfunc
+ * frame because AP knows that we are sleeping. But if the
+ * hardware is creating the nullfunc frame for power save
+ * status (ie. IEEE80211_HW_PS_NULLFUNC_STACK is not
+ * enabled) and power save was enabled, the firmware just
+ * sent a null frame with power save disabled. So we need
+ * to send a new nullfunc frame to inform the AP that we
+ * are again sleeping.
+ */
+ ieee80211_send_nullfunc(local, sdata, 1);
+}
+
+/* inform AP that we are awake again, unless power save is enabled */
+static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_local *local = sdata->local;
+
+ if (!local->ps_sdata)
+ ieee80211_send_nullfunc(local, sdata, 0);
+ else if (local->scan_ps_enabled) {
+ /*
+ * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware
+ * will send a nullfunc frame with the powersave bit set
+ * even though the AP already knows that we are sleeping.
+ * This could be avoided by sending a null frame with power
+ * save bit disabled before enabling the power save, but
+ * this doesn't gain anything.
+ *
+ * When IEEE80211_HW_PS_NULLFUNC_STACK is enabled, no need
+ * to send a nullfunc frame because AP already knows that
+ * we are sleeping, let's just enable power save mode in
+ * hardware.
+ */
+ local->hw.conf.flags |= IEEE80211_CONF_PS;
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+ } else if (local->hw.conf.dynamic_ps_timeout > 0) {
+ /*
+ * If IEEE80211_CONF_PS was not set and the dynamic_ps_timer
+ * had been running before leaving the operating channel,
+ * restart the timer now and send a nullfunc frame to inform
+ * the AP that we are awake.
+ */
+ ieee80211_send_nullfunc(local, sdata, 0);
+ mod_timer(&local->dynamic_ps_timer, jiffies +
+ msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
+ }
+}
+
void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
{
struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_sub_if_data *sdata;
bool was_hw_scan;
mutex_lock(&local->scan_mtx);
@@ -291,19 +344,41 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
drv_sw_scan_complete(local);
- ieee80211_offchannel_return(local, true);
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (!netif_running(sdata->dev))
+ continue;
+
+ /* Tell AP we're back */
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ if (sdata->u.mgd.associated) {
+ ieee80211_scan_ps_disable(sdata);
+ netif_tx_wake_all_queues(sdata->dev);
+ }
+ } else
+ netif_tx_wake_all_queues(sdata->dev);
+
+ /* re-enable beaconing */
+ if (sdata->vif.type == NL80211_IFTYPE_AP ||
+ sdata->vif.type == NL80211_IFTYPE_ADHOC ||
+ sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
+ ieee80211_bss_info_change_notify(
+ sdata, BSS_CHANGED_BEACON_ENABLED);
+ }
+ mutex_unlock(&local->iflist_mtx);
done:
ieee80211_recalc_idle(local);
ieee80211_mlme_notify_scan_completed(local);
ieee80211_ibss_notify_scan_completed(local);
ieee80211_mesh_notify_scan_completed(local);
- ieee80211_queue_work(&local->hw, &local->work_work);
}
EXPORT_SYMBOL(ieee80211_scan_completed);
static int ieee80211_start_sw_scan(struct ieee80211_local *local)
{
+ struct ieee80211_sub_if_data *sdata;
+
/*
* Hardware/driver doesn't support hw_scan, so use software
* scanning instead. First send a nullfunc frame with power save
@@ -319,15 +394,33 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
*/
drv_sw_scan_start(local);
- ieee80211_offchannel_stop_beaconing(local);
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (!netif_running(sdata->dev))
+ continue;
+
+ /* disable beaconing */
+ if (sdata->vif.type == NL80211_IFTYPE_AP ||
+ sdata->vif.type == NL80211_IFTYPE_ADHOC ||
+ sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
+ ieee80211_bss_info_change_notify(
+ sdata, BSS_CHANGED_BEACON_ENABLED);
+
+ /*
+ * only handle non-STA interfaces here, STA interfaces
+ * are handled in the scan state machine
+ */
+ if (sdata->vif.type != NL80211_IFTYPE_STATION)
+ netif_tx_stop_all_queues(sdata->dev);
+ }
+ mutex_unlock(&local->iflist_mtx);
local->next_scan_state = SCAN_DECISION;
local->scan_channel_idx = 0;
- drv_flush(local, false);
-
ieee80211_configure_filter(local);
+ /* TODO: start scan as soon as all nullfunc frames are ACKed */
ieee80211_queue_delayed_work(&local->hw,
&local->scan_work,
IEEE80211_CHANNEL_TIME);
@@ -340,13 +433,17 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
struct cfg80211_scan_request *req)
{
struct ieee80211_local *local = sdata->local;
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
int rc;
if (local->scan_req)
return -EBUSY;
- if (!list_empty(&local->work_list)) {
- /* wait for the work to finish/time out */
+ if (req != local->int_scan_req &&
+ sdata->vif.type == NL80211_IFTYPE_STATION &&
+ !list_empty(&ifmgd->work_list)) {
+ /* actually wait for the work it's doing to finish/time out */
+ set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request);
local->scan_req = req;
local->scan_sdata = sdata;
return 0;
@@ -371,14 +468,6 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
local->hw_scan_req->ie = ies;
local->hw_scan_band = 0;
-
- /*
- * After allocating local->hw_scan_req, we must
- * go through until ieee80211_prep_hw_scan(), so
- * anything that might be changed here and leave
- * this function early must not go after this
- * allocation.
- */
}
local->scan_req = req;
@@ -388,16 +477,15 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
__set_bit(SCAN_HW_SCANNING, &local->scanning);
else
__set_bit(SCAN_SW_SCANNING, &local->scanning);
-
/*
* Kicking off the scan need not be protected,
* only the scan variable stuff, since now
* local->scan_req is assigned and other callers
* will abort their scan attempts.
*
- * This avoids too many locking dependencies
- * so that the scan completed calls have more
- * locking freedom.
+ * This avoids getting a scan_mtx -> iflist_mtx
+ * dependency, so that the scan completed calls
+ * have more locking freedom.
*/
ieee80211_recalc_idle(local);
@@ -440,7 +528,7 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
/* check if at least one STA interface is associated */
mutex_lock(&local->iflist_mtx);
list_for_each_entry(sdata, &local->interfaces, list) {
- if (!ieee80211_sdata_running(sdata))
+ if (!netif_running(sdata->dev))
continue;
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
@@ -478,35 +566,56 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local,
unsigned long *next_delay)
{
- ieee80211_offchannel_stop_station(local);
-
- __set_bit(SCAN_OFF_CHANNEL, &local->scanning);
+ struct ieee80211_sub_if_data *sdata;
/*
- * What if the nullfunc frames didn't arrive?
+ * notify the AP about us leaving the channel and stop all STA interfaces
*/
- drv_flush(local, false);
- if (local->ops->flush)
- *next_delay = 0;
- else
- *next_delay = HZ / 10;
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (!netif_running(sdata->dev))
+ continue;
+
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ netif_tx_stop_all_queues(sdata->dev);
+ if (sdata->u.mgd.associated)
+ ieee80211_scan_ps_enable(sdata);
+ }
+ }
+ mutex_unlock(&local->iflist_mtx);
+
+ __set_bit(SCAN_OFF_CHANNEL, &local->scanning);
/* advance to the next channel to be scanned */
+ *next_delay = HZ / 10;
local->next_scan_state = SCAN_SET_CHANNEL;
}
static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local,
unsigned long *next_delay)
{
+ struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+
/* switch back to the operating channel */
local->scan_channel = NULL;
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
/*
- * Only re-enable station mode interface now; beaconing will be
- * re-enabled once the full scan has been completed.
+ * notify the AP about us being back and restart all STA interfaces
*/
- ieee80211_offchannel_return(local, false);
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (!netif_running(sdata->dev))
+ continue;
+
+ /* Tell AP we're back */
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ if (sdata->u.mgd.associated)
+ ieee80211_scan_ps_disable(sdata);
+ netif_tx_wake_all_queues(sdata->dev);
+ }
+ }
+ mutex_unlock(&local->iflist_mtx);
__clear_bit(SCAN_OFF_CHANNEL, &local->scanning);
@@ -620,7 +729,7 @@ void ieee80211_scan_work(struct work_struct *work)
/*
* Avoid re-scheduling when the sdata is going away.
*/
- if (!ieee80211_sdata_running(sdata)) {
+ if (!netif_running(sdata->dev)) {
ieee80211_scan_completed(&local->hw, true);
return;
}
diff --git a/trunk/net/mac80211/spectmgmt.c b/trunk/net/mac80211/spectmgmt.c
index 7733f66ee2c4..aa743a895cf9 100644
--- a/trunk/net/mac80211/spectmgmt.c
+++ b/trunk/net/mac80211/spectmgmt.c
@@ -35,7 +35,7 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da
if (!skb) {
printk(KERN_ERR "%s: failed to allocate buffer for "
- "measurement report frame\n", sdata->name);
+ "measurement report frame\n", sdata->dev->name);
return;
}
@@ -43,7 +43,7 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da
msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24);
memset(msr_report, 0, 24);
memcpy(msr_report->da, da, ETH_ALEN);
- memcpy(msr_report->sa, sdata->vif.addr, ETH_ALEN);
+ memcpy(msr_report->sa, sdata->dev->dev_addr, ETH_ALEN);
memcpy(msr_report->bssid, bssid, ETH_ALEN);
msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
diff --git a/trunk/net/mac80211/sta_info.c b/trunk/net/mac80211/sta_info.c
index 211c475f73c6..71f370dd24bc 100644
--- a/trunk/net/mac80211/sta_info.c
+++ b/trunk/net/mac80211/sta_info.c
@@ -32,33 +32,49 @@
* for faster lookup and a list for iteration. They are managed using
* RCU, i.e. access to the list and hash table is protected by RCU.
*
- * Upon allocating a STA info structure with sta_info_alloc(), the caller
- * owns that structure. It must then insert it into the hash table using
- * either sta_info_insert() or sta_info_insert_rcu(); only in the latter
- * case (which acquires an rcu read section but must not be called from
- * within one) will the pointer still be valid after the call. Note that
- * the caller may not do much with the STA info before inserting it, in
- * particular, it may not start any mesh peer link management or add
- * encryption keys.
+ * Upon allocating a STA info structure with sta_info_alloc(), the caller owns
+ * that structure. It must then either destroy it using sta_info_destroy()
+ * (which is pretty useless) or insert it into the hash table using
+ * sta_info_insert() which demotes the reference from ownership to a regular
+ * RCU-protected reference; if the function is called without protection by an
+ * RCU critical section the reference is instantly invalidated. Note that the
+ * caller may not do much with the STA info before inserting it, in particular,
+ * it may not start any mesh peer link management or add encryption keys.
*
* When the insertion fails (sta_info_insert()) returns non-zero), the
* structure will have been freed by sta_info_insert()!
*
- * Station entries are added by mac80211 when you establish a link with a
+ * sta entries are added by mac80211 when you establish a link with a
* peer. This means different things for the different type of interfaces
* we support. For a regular station this mean we add the AP sta when we
* receive an assocation response from the AP. For IBSS this occurs when
- * get to know about a peer on the same IBSS. For WDS we add the sta for
- * the peer imediately upon device open. When using AP mode we add stations
- * for each respective station upon request from userspace through nl80211.
+ * we receive a probe response or a beacon from target IBSS network. For
+ * WDS we add the sta for the peer imediately upon device open. When using
+ * AP mode we add stations for each respective station upon request from
+ * userspace through nl80211.
*
- * In order to remove a STA info structure, various sta_info_destroy_*()
- * calls are available.
+ * Because there are debugfs entries for each station, and adding those
+ * must be able to sleep, it is also possible to "pin" a station entry,
+ * that means it can be removed from the hash table but not be freed.
+ * See the comment in __sta_info_unlink() for more information, this is
+ * an internal capability only.
*
- * There is no concept of ownership on a STA entry, each structure is
- * owned by the global hash table/list until it is removed. All users of
- * the structure need to be RCU protected so that the structure won't be
- * freed before they are done using it.
+ * In order to remove a STA info structure, the caller needs to first
+ * unlink it (sta_info_unlink()) from the list and hash tables and
+ * then destroy it; sta_info_destroy() will wait for an RCU grace period
+ * to elapse before actually freeing it. Due to the pinning and the
+ * possibility of multiple callers trying to remove the same STA info at
+ * the same time, sta_info_unlink() can clear the STA info pointer it is
+ * passed to indicate that the STA info is owned by somebody else now.
+ *
+ * If sta_info_unlink() did not clear the pointer then the caller owns
+ * the STA info structure now and is responsible of destroying it with
+ * a call to sta_info_destroy().
+ *
+ * In all other cases, there is no concept of ownership on a STA entry,
+ * each structure is owned by the global hash table/list until it is
+ * removed. All users of the structure need to be RCU protected so that
+ * the structure won't be freed before they are done using it.
*/
/* Caller must hold local->sta_lock */
@@ -87,37 +103,13 @@ static int sta_info_hash_del(struct ieee80211_local *local,
}
/* protected by RCU */
-struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
- const u8 *addr)
+struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr)
{
- struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]);
while (sta) {
- if (sta->sdata == sdata &&
- memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
- break;
- sta = rcu_dereference(sta->hnext);
- }
- return sta;
-}
-
-/*
- * Get sta info either from the specified interface
- * or from one of its vlans
- */
-struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
- const u8 *addr)
-{
- struct ieee80211_local *local = sdata->local;
- struct sta_info *sta;
-
- sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]);
- while (sta) {
- if ((sta->sdata == sdata ||
- sta->sdata->bss == sdata->bss) &&
- memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
+ if (memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
break;
sta = rcu_dereference(sta->hnext);
}
@@ -169,6 +161,101 @@ static void __sta_info_free(struct ieee80211_local *local,
kfree(sta);
}
+void sta_info_destroy(struct sta_info *sta)
+{
+ struct ieee80211_local *local;
+ struct sk_buff *skb;
+ int i;
+
+ might_sleep();
+
+ if (!sta)
+ return;
+
+ local = sta->local;
+
+ cancel_work_sync(&sta->drv_unblock_wk);
+
+ rate_control_remove_sta_debugfs(sta);
+ ieee80211_sta_debugfs_remove(sta);
+
+#ifdef CONFIG_MAC80211_MESH
+ if (ieee80211_vif_is_mesh(&sta->sdata->vif))
+ mesh_plink_deactivate(sta);
+#endif
+
+ /*
+ * We have only unlinked the key, and actually destroying it
+ * may mean it is removed from hardware which requires that
+ * the key->sta pointer is still valid, so flush the key todo
+ * list here.
+ *
+ * ieee80211_key_todo() will synchronize_rcu() so after this
+ * nothing can reference this sta struct any more.
+ */
+ ieee80211_key_todo();
+
+#ifdef CONFIG_MAC80211_MESH
+ if (ieee80211_vif_is_mesh(&sta->sdata->vif))
+ del_timer_sync(&sta->plink_timer);
+#endif
+
+ while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
+ local->total_ps_buffered--;
+ dev_kfree_skb_any(skb);
+ }
+
+ while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL)
+ dev_kfree_skb_any(skb);
+
+ for (i = 0; i < STA_TID_NUM; i++) {
+ struct tid_ampdu_rx *tid_rx;
+ struct tid_ampdu_tx *tid_tx;
+
+ spin_lock_bh(&sta->lock);
+ tid_rx = sta->ampdu_mlme.tid_rx[i];
+ /* Make sure timer won't free the tid_rx struct, see below */
+ if (tid_rx)
+ tid_rx->shutdown = true;
+
+ spin_unlock_bh(&sta->lock);
+
+ /*
+ * Outside spinlock - shutdown is true now so that the timer
+ * won't free tid_rx, we have to do that now. Can't let the
+ * timer do it because we have to sync the timer outside the
+ * lock that it takes itself.
+ */
+ if (tid_rx) {
+ del_timer_sync(&tid_rx->session_timer);
+ kfree(tid_rx);
+ }
+
+ /*
+ * No need to do such complications for TX agg sessions, the
+ * path leading to freeing the tid_tx struct goes via a call
+ * from the driver, and thus needs to look up the sta struct
+ * again, which cannot be found when we get here. Hence, we
+ * just need to delete the timer and free the aggregation
+ * info; we won't be telling the peer about it then but that
+ * doesn't matter if we're not talking to it again anyway.
+ */
+ tid_tx = sta->ampdu_mlme.tid_tx[i];
+ if (tid_tx) {
+ del_timer_sync(&tid_tx->addba_resp_timer);
+ /*
+ * STA removed while aggregation session being
+ * started? Bit odd, but purge frames anyway.
+ */
+ skb_queue_purge(&tid_tx->pending);
+ kfree(tid_tx);
+ }
+ }
+
+ __sta_info_free(local, sta);
+}
+
+
/* Caller must hold local->sta_lock */
static void sta_info_hash_add(struct ieee80211_local *local,
struct sta_info *sta)
@@ -265,93 +352,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
return sta;
}
-static int sta_info_finish_insert(struct sta_info *sta, bool async)
-{
- struct ieee80211_local *local = sta->local;
- struct ieee80211_sub_if_data *sdata = sta->sdata;
- struct station_info sinfo;
- unsigned long flags;
- int err = 0;
-
- WARN_ON(!mutex_is_locked(&local->sta_mtx));
-
- /* notify driver */
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- sdata = container_of(sdata->bss,
- struct ieee80211_sub_if_data,
- u.ap);
- err = drv_sta_add(local, sdata, &sta->sta);
- if (err) {
- if (!async)
- return err;
- printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to driver (%d)"
- " - keeping it anyway.\n",
- sdata->name, sta->sta.addr, err);
- } else {
- sta->uploaded = true;
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- if (async)
- printk(KERN_DEBUG "%s: Finished adding IBSS STA %pM\n",
- wiphy_name(local->hw.wiphy), sta->sta.addr);
-#endif
- }
-
- sdata = sta->sdata;
-
- if (!async) {
- local->num_sta++;
- local->sta_generation++;
- smp_mb();
-
- /* make the station visible */
- spin_lock_irqsave(&local->sta_lock, flags);
- sta_info_hash_add(local, sta);
- spin_unlock_irqrestore(&local->sta_lock, flags);
- }
-
- list_add(&sta->list, &local->sta_list);
-
- ieee80211_sta_debugfs_add(sta);
- rate_control_add_sta_debugfs(sta);
-
- sinfo.filled = 0;
- sinfo.generation = local->sta_generation;
- cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL);
-
-
- return 0;
-}
-
-static void sta_info_finish_pending(struct ieee80211_local *local)
-{
- struct sta_info *sta;
- unsigned long flags;
-
- spin_lock_irqsave(&local->sta_lock, flags);
- while (!list_empty(&local->sta_pending_list)) {
- sta = list_first_entry(&local->sta_pending_list,
- struct sta_info, list);
- list_del(&sta->list);
- spin_unlock_irqrestore(&local->sta_lock, flags);
-
- sta_info_finish_insert(sta, true);
-
- spin_lock_irqsave(&local->sta_lock, flags);
- }
- spin_unlock_irqrestore(&local->sta_lock, flags);
-}
-
-static void sta_info_finish_work(struct work_struct *work)
-{
- struct ieee80211_local *local =
- container_of(work, struct ieee80211_local, sta_finish_work);
-
- mutex_lock(&local->sta_mtx);
- sta_info_finish_pending(local);
- mutex_unlock(&local->sta_mtx);
-}
-
-int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)
+int sta_info_insert(struct sta_info *sta)
{
struct ieee80211_local *local = sta->local;
struct ieee80211_sub_if_data *sdata = sta->sdata;
@@ -363,89 +364,38 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)
* something inserts a STA (on one CPU) without holding the RTNL
* and another CPU turns off the net device.
*/
- if (unlikely(!ieee80211_sdata_running(sdata))) {
+ if (unlikely(!netif_running(sdata->dev))) {
err = -ENETDOWN;
- rcu_read_lock();
goto out_free;
}
- if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 ||
+ if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->dev->dev_addr) == 0 ||
is_multicast_ether_addr(sta->sta.addr))) {
err = -EINVAL;
- rcu_read_lock();
goto out_free;
}
- /*
- * In ad-hoc mode, we sometimes need to insert stations
- * from tasklet context from the RX path. To avoid races,
- * always do so in that case -- see the comment below.
- */
- if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
- spin_lock_irqsave(&local->sta_lock, flags);
- /* check if STA exists already */
- if (sta_info_get_bss(sdata, sta->sta.addr)) {
- spin_unlock_irqrestore(&local->sta_lock, flags);
- rcu_read_lock();
- err = -EEXIST;
- goto out_free;
- }
-
- local->num_sta++;
- local->sta_generation++;
- smp_mb();
- sta_info_hash_add(local, sta);
-
- list_add_tail(&sta->list, &local->sta_pending_list);
-
- rcu_read_lock();
- spin_unlock_irqrestore(&local->sta_lock, flags);
-
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- printk(KERN_DEBUG "%s: Added IBSS STA %pM\n",
- wiphy_name(local->hw.wiphy), sta->sta.addr);
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-
- ieee80211_queue_work(&local->hw, &local->sta_finish_work);
-
- return 0;
- }
-
- /*
- * On first glance, this will look racy, because the code
- * below this point, which inserts a station with sleeping,
- * unlocks the sta_lock between checking existence in the
- * hash table and inserting into it.
- *
- * However, it is not racy against itself because it keeps
- * the mutex locked. It still seems to race against the
- * above code that atomically inserts the station... That,
- * however, is not true because the above code can only
- * be invoked for IBSS interfaces, and the below code will
- * not be -- and the two do not race against each other as
- * the hash table also keys off the interface.
- */
-
- might_sleep();
-
- mutex_lock(&local->sta_mtx);
-
spin_lock_irqsave(&local->sta_lock, flags);
/* check if STA exists already */
- if (sta_info_get_bss(sdata, sta->sta.addr)) {
+ if (sta_info_get(local, sta->sta.addr)) {
spin_unlock_irqrestore(&local->sta_lock, flags);
- rcu_read_lock();
err = -EEXIST;
goto out_free;
}
+ list_add(&sta->list, &local->sta_list);
+ local->sta_generation++;
+ local->num_sta++;
+ sta_info_hash_add(local, sta);
- spin_unlock_irqrestore(&local->sta_lock, flags);
+ /* notify driver */
+ if (local->ops->sta_notify) {
+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ sdata = container_of(sdata->bss,
+ struct ieee80211_sub_if_data,
+ u.ap);
- err = sta_info_finish_insert(sta, false);
- if (err) {
- mutex_unlock(&local->sta_mtx);
- rcu_read_lock();
- goto out_free;
+ drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta);
+ sdata = sta->sdata;
}
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
@@ -453,9 +403,18 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)
wiphy_name(local->hw.wiphy), sta->sta.addr);
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
- /* move reference to rcu-protected */
- rcu_read_lock();
- mutex_unlock(&local->sta_mtx);
+ spin_unlock_irqrestore(&local->sta_lock, flags);
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+ /*
+ * Debugfs entry adding might sleep, so schedule process
+ * context task for adding entry for STAs that do not yet
+ * have one.
+ * NOTE: due to auto-freeing semantics this may only be done
+ * if the insertion is successful!
+ */
+ schedule_work(&local->sta_debugfs_add);
+#endif
if (ieee80211_vif_is_mesh(&sdata->vif))
mesh_accept_plinks_update(sdata);
@@ -467,15 +426,6 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)
return err;
}
-int sta_info_insert(struct sta_info *sta)
-{
- int err = sta_info_insert_rcu(sta);
-
- rcu_read_unlock();
-
- return err;
-}
-
static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid)
{
/*
@@ -544,6 +494,108 @@ void sta_info_clear_tim_bit(struct sta_info *sta)
spin_unlock_irqrestore(&sta->local->sta_lock, flags);
}
+static void __sta_info_unlink(struct sta_info **sta)
+{
+ struct ieee80211_local *local = (*sta)->local;
+ struct ieee80211_sub_if_data *sdata = (*sta)->sdata;
+ /*
+ * pull caller's reference if we're already gone.
+ */
+ if (sta_info_hash_del(local, *sta)) {
+ *sta = NULL;
+ return;
+ }
+
+ if ((*sta)->key) {
+ ieee80211_key_free((*sta)->key);
+ WARN_ON((*sta)->key);
+ }
+
+ list_del(&(*sta)->list);
+ (*sta)->dead = true;
+
+ if (test_and_clear_sta_flags(*sta,
+ WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) {
+ BUG_ON(!sdata->bss);
+
+ atomic_dec(&sdata->bss->num_sta_ps);
+ __sta_info_clear_tim_bit(sdata->bss, *sta);
+ }
+
+ local->num_sta--;
+ local->sta_generation++;
+
+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ rcu_assign_pointer(sdata->u.vlan.sta, NULL);
+
+ if (local->ops->sta_notify) {
+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ sdata = container_of(sdata->bss,
+ struct ieee80211_sub_if_data,
+ u.ap);
+
+ drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE,
+ &(*sta)->sta);
+ sdata = (*sta)->sdata;
+ }
+
+ if (ieee80211_vif_is_mesh(&sdata->vif)) {
+ mesh_accept_plinks_update(sdata);
+#ifdef CONFIG_MAC80211_MESH
+ del_timer(&(*sta)->plink_timer);
+#endif
+ }
+
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+ printk(KERN_DEBUG "%s: Removed STA %pM\n",
+ wiphy_name(local->hw.wiphy), (*sta)->sta.addr);
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+
+ /*
+ * Finally, pull caller's reference if the STA is pinned by the
+ * task that is adding the debugfs entries. In that case, we
+ * leave the STA "to be freed".
+ *
+ * The rules are not trivial, but not too complex either:
+ * (1) pin_status is only modified under the sta_lock
+ * (2) STAs may only be pinned under the RTNL so that
+ * sta_info_flush() is guaranteed to actually destroy
+ * all STAs that are active for a given interface, this
+ * is required for correctness because otherwise we
+ * could notify a driver that an interface is going
+ * away and only after that (!) notify it about a STA
+ * on that interface going away.
+ * (3) sta_info_debugfs_add_work() will set the status
+ * to PINNED when it found an item that needs a new
+ * debugfs directory created. In that case, that item
+ * must not be freed although all *RCU* users are done
+ * with it. Hence, we tell the caller of _unlink()
+ * that the item is already gone (as can happen when
+ * two tasks try to unlink/destroy at the same time)
+ * (4) We set the pin_status to DESTROY here when we
+ * find such an item.
+ * (5) sta_info_debugfs_add_work() will reset the pin_status
+ * from PINNED to NORMAL when it is done with the item,
+ * but will check for DESTROY before resetting it in
+ * which case it will free the item.
+ */
+ if ((*sta)->pin_status == STA_INFO_PIN_STAT_PINNED) {
+ (*sta)->pin_status = STA_INFO_PIN_STAT_DESTROY;
+ *sta = NULL;
+ return;
+ }
+}
+
+void sta_info_unlink(struct sta_info **sta)
+{
+ struct ieee80211_local *local = (*sta)->local;
+ unsigned long flags;
+
+ spin_lock_irqsave(&local->sta_lock, flags);
+ __sta_info_unlink(sta);
+ spin_unlock_irqrestore(&local->sta_lock, flags);
+}
+
static int sta_info_buffer_expired(struct sta_info *sta,
struct sk_buff *skb)
{
@@ -600,209 +652,109 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
}
}
-static int __must_check __sta_info_destroy(struct sta_info *sta)
-{
- struct ieee80211_local *local;
- struct ieee80211_sub_if_data *sdata;
- struct sk_buff *skb;
- unsigned long flags;
- int ret, i;
-
- might_sleep();
-
- if (!sta)
- return -ENOENT;
-
- local = sta->local;
- sdata = sta->sdata;
-
- spin_lock_irqsave(&local->sta_lock, flags);
- ret = sta_info_hash_del(local, sta);
- /* this might still be the pending list ... which is fine */
- if (!ret)
- list_del(&sta->list);
- spin_unlock_irqrestore(&local->sta_lock, flags);
- if (ret)
- return ret;
-
- if (sta->key) {
- ieee80211_key_free(sta->key);
- /*
- * We have only unlinked the key, and actually destroying it
- * may mean it is removed from hardware which requires that
- * the key->sta pointer is still valid, so flush the key todo
- * list here.
- *
- * ieee80211_key_todo() will synchronize_rcu() so after this
- * nothing can reference this sta struct any more.
- */
- ieee80211_key_todo();
-
- WARN_ON(sta->key);
- }
-
- sta->dead = true;
-
- if (test_and_clear_sta_flags(sta,
- WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) {
- BUG_ON(!sdata->bss);
-
- atomic_dec(&sdata->bss->num_sta_ps);
- __sta_info_clear_tim_bit(sdata->bss, sta);
- }
-
- local->num_sta--;
- local->sta_generation++;
-
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- rcu_assign_pointer(sdata->u.vlan.sta, NULL);
-
- if (sta->uploaded) {
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- sdata = container_of(sdata->bss,
- struct ieee80211_sub_if_data,
- u.ap);
- drv_sta_remove(local, sdata, &sta->sta);
- sdata = sta->sdata;
- }
-
-#ifdef CONFIG_MAC80211_MESH
- if (ieee80211_vif_is_mesh(&sdata->vif)) {
- mesh_accept_plinks_update(sdata);
- del_timer(&sta->plink_timer);
- }
-#endif
-
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- printk(KERN_DEBUG "%s: Removed STA %pM\n",
- wiphy_name(local->hw.wiphy), sta->sta.addr);
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
- cancel_work_sync(&sta->drv_unblock_wk);
-
- rate_control_remove_sta_debugfs(sta);
- ieee80211_sta_debugfs_remove(sta);
-
-#ifdef CONFIG_MAC80211_MESH
- if (ieee80211_vif_is_mesh(&sta->sdata->vif)) {
- mesh_plink_deactivate(sta);
- del_timer_sync(&sta->plink_timer);
- }
-#endif
- while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
- local->total_ps_buffered--;
- dev_kfree_skb_any(skb);
- }
-
- while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL)
- dev_kfree_skb_any(skb);
-
- for (i = 0; i < STA_TID_NUM; i++) {
- struct tid_ampdu_rx *tid_rx;
- struct tid_ampdu_tx *tid_tx;
-
- spin_lock_bh(&sta->lock);
- tid_rx = sta->ampdu_mlme.tid_rx[i];
- /* Make sure timer won't free the tid_rx struct, see below */
- if (tid_rx)
- tid_rx->shutdown = true;
-
- spin_unlock_bh(&sta->lock);
-
- /*
- * Outside spinlock - shutdown is true now so that the timer
- * won't free tid_rx, we have to do that now. Can't let the
- * timer do it because we have to sync the timer outside the
- * lock that it takes itself.
- */
- if (tid_rx) {
- del_timer_sync(&tid_rx->session_timer);
- kfree(tid_rx);
- }
+static void sta_info_cleanup(unsigned long data)
+{
+ struct ieee80211_local *local = (struct ieee80211_local *) data;
+ struct sta_info *sta;
- /*
- * No need to do such complications for TX agg sessions, the
- * path leading to freeing the tid_tx struct goes via a call
- * from the driver, and thus needs to look up the sta struct
- * again, which cannot be found when we get here. Hence, we
- * just need to delete the timer and free the aggregation
- * info; we won't be telling the peer about it then but that
- * doesn't matter if we're not talking to it again anyway.
- */
- tid_tx = sta->ampdu_mlme.tid_tx[i];
- if (tid_tx) {
- del_timer_sync(&tid_tx->addba_resp_timer);
- /*
- * STA removed while aggregation session being
- * started? Bit odd, but purge frames anyway.
- */
- skb_queue_purge(&tid_tx->pending);
- kfree(tid_tx);
- }
- }
+ rcu_read_lock();
+ list_for_each_entry_rcu(sta, &local->sta_list, list)
+ sta_info_cleanup_expire_buffered(local, sta);
+ rcu_read_unlock();
- __sta_info_free(local, sta);
+ if (local->quiescing)
+ return;
- return 0;
+ local->sta_cleanup.expires =
+ round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL);
+ add_timer(&local->sta_cleanup);
}
-int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr)
+#ifdef CONFIG_MAC80211_DEBUGFS
+/*
+ * See comment in __sta_info_unlink,
+ * caller must hold local->sta_lock.
+ */
+static void __sta_info_pin(struct sta_info *sta)
{
- struct sta_info *sta;
- int ret;
-
- mutex_lock(&sdata->local->sta_mtx);
- sta = sta_info_get(sdata, addr);
- ret = __sta_info_destroy(sta);
- mutex_unlock(&sdata->local->sta_mtx);
-
- return ret;
+ WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_NORMAL);
+ sta->pin_status = STA_INFO_PIN_STAT_PINNED;
}
-int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata,
- const u8 *addr)
+/*
+ * See comment in __sta_info_unlink, returns sta if it
+ * needs to be destroyed.
+ */
+static struct sta_info *__sta_info_unpin(struct sta_info *sta)
{
- struct sta_info *sta;
- int ret;
+ struct sta_info *ret = NULL;
+ unsigned long flags;
- mutex_lock(&sdata->local->sta_mtx);
- sta = sta_info_get_bss(sdata, addr);
- ret = __sta_info_destroy(sta);
- mutex_unlock(&sdata->local->sta_mtx);
+ spin_lock_irqsave(&sta->local->sta_lock, flags);
+ WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_DESTROY &&
+ sta->pin_status != STA_INFO_PIN_STAT_PINNED);
+ if (sta->pin_status == STA_INFO_PIN_STAT_DESTROY)
+ ret = sta;
+ sta->pin_status = STA_INFO_PIN_STAT_NORMAL;
+ spin_unlock_irqrestore(&sta->local->sta_lock, flags);
return ret;
}
-static void sta_info_cleanup(unsigned long data)
+static void sta_info_debugfs_add_work(struct work_struct *work)
{
- struct ieee80211_local *local = (struct ieee80211_local *) data;
- struct sta_info *sta;
+ struct ieee80211_local *local =
+ container_of(work, struct ieee80211_local, sta_debugfs_add);
+ struct sta_info *sta, *tmp;
+ unsigned long flags;
- rcu_read_lock();
- list_for_each_entry_rcu(sta, &local->sta_list, list)
- sta_info_cleanup_expire_buffered(local, sta);
- rcu_read_unlock();
+ /* We need to keep the RTNL across the whole pinned status. */
+ rtnl_lock();
+ while (1) {
+ sta = NULL;
- if (local->quiescing)
- return;
+ spin_lock_irqsave(&local->sta_lock, flags);
+ list_for_each_entry(tmp, &local->sta_list, list) {
+ /*
+ * debugfs.add_has_run will be set by
+ * ieee80211_sta_debugfs_add regardless
+ * of what else it does.
+ */
+ if (!tmp->debugfs.add_has_run) {
+ sta = tmp;
+ __sta_info_pin(sta);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&local->sta_lock, flags);
- local->sta_cleanup.expires =
- round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL);
- add_timer(&local->sta_cleanup);
+ if (!sta)
+ break;
+
+ ieee80211_sta_debugfs_add(sta);
+ rate_control_add_sta_debugfs(sta);
+
+ sta = __sta_info_unpin(sta);
+ sta_info_destroy(sta);
+ }
+ rtnl_unlock();
}
+#endif
void sta_info_init(struct ieee80211_local *local)
{
spin_lock_init(&local->sta_lock);
- mutex_init(&local->sta_mtx);
INIT_LIST_HEAD(&local->sta_list);
- INIT_LIST_HEAD(&local->sta_pending_list);
- INIT_WORK(&local->sta_finish_work, sta_info_finish_work);
setup_timer(&local->sta_cleanup, sta_info_cleanup,
(unsigned long)local);
local->sta_cleanup.expires =
round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL);
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+ INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_work);
+#endif
}
int sta_info_start(struct ieee80211_local *local)
@@ -814,6 +766,16 @@ int sta_info_start(struct ieee80211_local *local)
void sta_info_stop(struct ieee80211_local *local)
{
del_timer(&local->sta_cleanup);
+#ifdef CONFIG_MAC80211_DEBUGFS
+ /*
+ * Make sure the debugfs adding work isn't pending after this
+ * because we're about to be destroyed. It doesn't matter
+ * whether it ran or not since we're going to flush all STAs
+ * anyway.
+ */
+ cancel_work_sync(&local->sta_debugfs_add);
+#endif
+
sta_info_flush(local, NULL);
}
@@ -829,19 +791,26 @@ int sta_info_flush(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata)
{
struct sta_info *sta, *tmp;
+ LIST_HEAD(tmp_list);
int ret = 0;
+ unsigned long flags;
might_sleep();
- mutex_lock(&local->sta_mtx);
-
- sta_info_finish_pending(local);
-
+ spin_lock_irqsave(&local->sta_lock, flags);
list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
- if (!sdata || sdata == sta->sdata)
- WARN_ON(__sta_info_destroy(sta));
+ if (!sdata || sdata == sta->sdata) {
+ __sta_info_unlink(&sta);
+ if (sta) {
+ list_add_tail(&sta->list, &tmp_list);
+ ret++;
+ }
+ }
}
- mutex_unlock(&local->sta_mtx);
+ spin_unlock_irqrestore(&local->sta_lock, flags);
+
+ list_for_each_entry_safe(sta, tmp, &tmp_list, list)
+ sta_info_destroy(sta);
return ret;
}
@@ -851,28 +820,34 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_local *local = sdata->local;
struct sta_info *sta, *tmp;
+ LIST_HEAD(tmp_list);
+ unsigned long flags;
- mutex_lock(&local->sta_mtx);
+ spin_lock_irqsave(&local->sta_lock, flags);
list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
if (time_after(jiffies, sta->last_rx + exp_time)) {
#ifdef CONFIG_MAC80211_IBSS_DEBUG
printk(KERN_DEBUG "%s: expiring inactive STA %pM\n",
- sdata->name, sta->sta.addr);
+ sdata->dev->name, sta->sta.addr);
#endif
- WARN_ON(__sta_info_destroy(sta));
+ __sta_info_unlink(&sta);
+ if (sta)
+ list_add(&sta->list, &tmp_list);
}
- mutex_unlock(&local->sta_mtx);
+ spin_unlock_irqrestore(&local->sta_lock, flags);
+
+ list_for_each_entry_safe(sta, tmp, &tmp_list, list)
+ sta_info_destroy(sta);
}
struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
const u8 *addr)
{
- struct sta_info *sta, *nxt;
+ struct sta_info *sta = sta_info_get(hw_to_local(hw), addr);
- /* Just return a random station ... first in list ... */
- for_each_sta_info(hw_to_local(hw), addr, sta, nxt)
- return &sta->sta;
- return NULL;
+ if (!sta)
+ return NULL;
+ return &sta->sta;
}
EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw);
@@ -897,7 +872,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
struct ieee80211_local *local = sdata->local;
int sent, buffered;
- drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
+ drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta);
if (!skb_queue_empty(&sta->ps_tx_buf))
sta_info_clear_tim_bit(sta);
@@ -910,7 +885,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames "
- "since STA not sleeping anymore\n", sdata->name,
+ "since STA not sleeping anymore\n", sdata->dev->name,
sta->sta.addr, sta->sta.aid, sent - buffered, buffered);
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
}
@@ -969,7 +944,7 @@ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta)
*/
printk(KERN_DEBUG "%s: STA %pM sent PS Poll even "
"though there are no buffered frames for it\n",
- sdata->name, sta->sta.addr);
+ sdata->dev->name, sta->sta.addr);
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
}
}
diff --git a/trunk/net/mac80211/sta_info.h b/trunk/net/mac80211/sta_info.h
index 822d84522937..b4810f6aa94f 100644
--- a/trunk/net/mac80211/sta_info.h
+++ b/trunk/net/mac80211/sta_info.h
@@ -42,9 +42,6 @@
* be in the queues
* @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping
* station in power-save mode, reply when the driver unblocks.
- * @WLAN_STA_DISASSOC: Disassociation in progress.
- * This is used to reject TX BA session requests when disassociation
- * is in progress.
*/
enum ieee80211_sta_info_flags {
WLAN_STA_AUTH = 1<<0,
@@ -60,7 +57,6 @@ enum ieee80211_sta_info_flags {
WLAN_STA_SUSPEND = 1<<11,
WLAN_STA_PS_DRIVER = 1<<12,
WLAN_STA_PSPOLL = 1<<13,
- WLAN_STA_DISASSOC = 1<<14,
};
#define STA_TID_NUM 16
@@ -166,6 +162,11 @@ struct sta_ampdu_mlme {
};
+/* see __sta_info_unlink */
+#define STA_INFO_PIN_STAT_NORMAL 0
+#define STA_INFO_PIN_STAT_PINNED 1
+#define STA_INFO_PIN_STAT_DESTROY 2
+
/**
* struct sta_info - STA information
*
@@ -186,6 +187,7 @@ struct sta_ampdu_mlme {
* @flaglock: spinlock for flags accesses
* @drv_unblock_wk: used for driver PS unblocking
* @listen_interval: listen interval of this station, when we're acting as AP
+ * @pin_status: used internally for pinning a STA struct into memory
* @flags: STA flags, see &enum ieee80211_sta_info_flags
* @ps_tx_buf: buffer of frames to transmit to this station
* when it leaves power saving state
@@ -224,7 +226,6 @@ struct sta_ampdu_mlme {
* @debugfs: debug filesystem info
* @sta: station information we share with the driver
* @dead: set to true when sta is unlinked
- * @uploaded: set to true when sta is uploaded to the driver
*/
struct sta_info {
/* General information, mostly static */
@@ -244,7 +245,11 @@ struct sta_info {
bool dead;
- bool uploaded;
+ /*
+ * for use by the internal lifetime management,
+ * see __sta_info_unlink
+ */
+ u8 pin_status;
/*
* frequently updated, locked with own spinlock (flaglock),
@@ -398,37 +403,9 @@ static inline u32 get_sta_flags(struct sta_info *sta)
#define STA_INFO_CLEANUP_INTERVAL (10 * HZ)
/*
- * Get a STA info, must be under RCU read lock.
+ * Get a STA info, must have be under RCU read lock.
*/
-struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
- const u8 *addr);
-
-struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
- const u8 *addr);
-
-static inline
-void for_each_sta_info_type_check(struct ieee80211_local *local,
- const u8 *addr,
- struct sta_info *sta,
- struct sta_info *nxt)
-{
-}
-
-#define for_each_sta_info(local, _addr, sta, nxt) \
- for ( /* initialise loop */ \
- sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\
- nxt = sta ? rcu_dereference(sta->hnext) : NULL; \
- /* typecheck */ \
- for_each_sta_info_type_check(local, (_addr), sta, nxt), \
- /* continue condition */ \
- sta; \
- /* advance loop */ \
- sta = nxt, \
- nxt = sta ? rcu_dereference(sta->hnext) : NULL \
- ) \
- /* compare address and run code only if it matches */ \
- if (memcmp(sta->sta.addr, (_addr), ETH_ALEN) == 0)
-
+struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr);
/*
* Get STA info by index, BROKEN!
*/
@@ -444,19 +421,18 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
* Insert STA info into hash table/list, returns zero or a
* -EEXIST if (if the same MAC address is already present).
*
- * Calling the non-rcu version makes the caller relinquish,
- * the _rcu version calls read_lock_rcu() and must be called
- * without it held.
+ * Calling this without RCU protection makes the caller
+ * relinquish its reference to @sta.
*/
int sta_info_insert(struct sta_info *sta);
-int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU);
-int sta_info_insert_atomic(struct sta_info *sta);
-
-int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata,
- const u8 *addr);
-int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata,
- const u8 *addr);
+/*
+ * Unlink a STA info from the hash table/list.
+ * This can NULL the STA pointer if somebody else
+ * has already unlinked it.
+ */
+void sta_info_unlink(struct sta_info **sta);
+void sta_info_destroy(struct sta_info *sta);
void sta_info_set_tim_bit(struct sta_info *sta);
void sta_info_clear_tim_bit(struct sta_info *sta);
diff --git a/trunk/net/mac80211/status.c b/trunk/net/mac80211/status.c
index 56d5b9a6ec5b..d78f36c64c7b 100644
--- a/trunk/net/mac80211/status.c
+++ b/trunk/net/mac80211/status.c
@@ -2,7 +2,7 @@
* Copyright 2002-2005, Instant802 Networks, Inc.
* Copyright 2005-2006, Devicescape Software, Inc.
* Copyright 2006-2007 Jiri Benc
- * Copyright 2008-2010 Johannes Berg
+ * Copyright 2008-2009 Johannes Berg
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -45,19 +45,29 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
/*
- * This skb 'survived' a round-trip through the driver, and
- * hopefully the driver didn't mangle it too badly. However,
- * we can definitely not rely on the the control information
- * being correct. Clear it so we don't get junk there, and
- * indicate that it needs new processing, but must not be
- * modified/encrypted again.
+ * XXX: This is temporary!
+ *
+ * The problem here is that when we get here, the driver will
+ * quite likely have pretty much overwritten info->control by
+ * using info->driver_data or info->rate_driver_data. Thus,
+ * when passing out the frame to the driver again, we would be
+ * passing completely bogus data since the driver would then
+ * expect a properly filled info->control. In mac80211 itself
+ * the same problem occurs, since we need info->control.vif
+ * internally.
+ *
+ * To fix this, we should send the frame through TX processing
+ * again. However, it's not that simple, since the frame will
+ * have been software-encrypted (if applicable) already, and
+ * encrypting it again doesn't do much good. So to properly do
+ * that, we not only have to skip the actual 'raw' encryption
+ * (key selection etc. still has to be done!) but also the
+ * sequence number assignment since that impacts the crypto
+ * encapsulation, of course.
+ *
+ * Hence, for now, fix the bug by just dropping the frame.
*/
- memset(&info->control, 0, sizeof(info->control));
-
- info->control.jiffies = jiffies;
- info->control.vif = &sta->sdata->vif;
- info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING |
- IEEE80211_TX_INTFL_RETRANSMISSION;
+ goto drop;
sta->tx_filtered_count++;
@@ -112,6 +122,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
return;
}
+ drop:
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
if (net_ratelimit())
printk(KERN_DEBUG "%s: dropped TX filtered frame, "
@@ -123,40 +134,6 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
dev_kfree_skb(skb);
}
-static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
-{
- struct ieee80211_mgmt *mgmt = (void *) skb->data;
- struct ieee80211_local *local = sta->local;
- struct ieee80211_sub_if_data *sdata = sta->sdata;
-
- if (ieee80211_is_action(mgmt->frame_control) &&
- sdata->vif.type == NL80211_IFTYPE_STATION &&
- mgmt->u.action.category == WLAN_CATEGORY_HT &&
- mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS) {
- /*
- * This update looks racy, but isn't -- if we come
- * here we've definitely got a station that we're
- * talking to, and on a managed interface that can
- * only be the AP. And the only other place updating
- * this variable is before we're associated.
- */
- switch (mgmt->u.action.u.ht_smps.smps_control) {
- case WLAN_HT_SMPS_CONTROL_DYNAMIC:
- sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_DYNAMIC;
- break;
- case WLAN_HT_SMPS_CONTROL_STATIC:
- sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_STATIC;
- break;
- case WLAN_HT_SMPS_CONTROL_DISABLED:
- default: /* shouldn't happen since we don't send that */
- sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_OFF;
- break;
- }
-
- ieee80211_queue_work(&local->hw, &local->recalc_smps);
- }
-}
-
void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct sk_buff *skb2;
@@ -169,7 +146,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
struct ieee80211_tx_status_rtap_hdr *rthdr;
struct ieee80211_sub_if_data *sdata;
struct net_device *prev_dev = NULL;
- struct sta_info *sta, *tmp;
+ struct sta_info *sta;
int retry_count = -1, i;
bool injected;
@@ -188,13 +165,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
rcu_read_lock();
sband = local->hw.wiphy->bands[info->band];
- fc = hdr->frame_control;
- for_each_sta_info(local, hdr->addr1, sta, tmp) {
- /* skip wrong virtual interface */
- if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN))
- continue;
+ sta = sta_info_get(local, hdr->addr1);
+ if (sta) {
if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
test_sta_flags(sta, WLAN_STA_PS_STA)) {
/*
@@ -206,6 +180,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
return;
}
+ fc = hdr->frame_control;
+
if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&
(ieee80211_is_data_qos(fc))) {
u16 tid, ssn;
@@ -232,10 +208,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
rate_control_tx_status(local, sband, sta, skb);
if (ieee80211_vif_is_mesh(&sta->sdata->vif))
ieee80211s_update_metric(local, sta, skb);
-
- if (!(info->flags & IEEE80211_TX_CTL_INJECTED) &&
- (info->flags & IEEE80211_TX_STAT_ACK))
- ieee80211_frame_acked(sta, skb);
}
rcu_read_unlock();
@@ -274,25 +246,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
local->dot11FailedCount++;
}
- if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc) &&
- (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) &&
- !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
- local->ps_sdata && !(local->scanning)) {
- if (info->flags & IEEE80211_TX_STAT_ACK) {
- local->ps_sdata->u.mgd.flags |=
- IEEE80211_STA_NULLFUNC_ACKED;
- ieee80211_queue_work(&local->hw,
- &local->dynamic_ps_enable_work);
- } else
- mod_timer(&local->dynamic_ps_timer, jiffies +
- msecs_to_jiffies(10));
- }
-
- if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX)
- cfg80211_action_tx_status(
- skb->dev, (unsigned long) skb, skb->data, skb->len,
- !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC);
-
/* this was a transmitted frame, but now we want to reuse it */
skb_orphan(skb);
@@ -358,7 +311,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
- if (!ieee80211_sdata_running(sdata))
+ if (!netif_running(sdata->dev))
continue;
if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) &&
diff --git a/trunk/net/mac80211/tkip.c b/trunk/net/mac80211/tkip.c
index 7ef491e9d66d..4921d724b6c7 100644
--- a/trunk/net/mac80211/tkip.c
+++ b/trunk/net/mac80211/tkip.c
@@ -100,7 +100,7 @@ static void tkip_mixing_phase1(const u8 *tk, struct tkip_ctx *ctx,
p1k[3] += tkipS(p1k[2] ^ get_unaligned_le16(tk + 12 + j));
p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i;
}
- ctx->state = TKIP_STATE_PHASE1_DONE;
+ ctx->initialized = 1;
}
static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx,
@@ -183,7 +183,7 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
/* Update the p1k only when the iv16 in the packet wraps around, this
* might occur after the wrap around of iv16 in the key in case of
* fragmented packets. */
- if (iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT)
+ if (iv16 == 0 || !ctx->initialized)
tkip_mixing_phase1(tk, ctx, hdr->addr2, iv32);
if (type == IEEE80211_TKIP_P1_KEY) {
@@ -195,13 +195,11 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
}
EXPORT_SYMBOL(ieee80211_get_tkip_key);
-/*
- * Encrypt packet payload with TKIP using @key. @pos is a pointer to the
+/* Encrypt packet payload with TKIP using @key. @pos is a pointer to the
* beginning of the buffer containing payload. This payload must include
- * the IV/Ext.IV and space for (taildroom) four octets for ICV.
- * @payload_len is the length of payload (_not_ including IV/ICV length).
- * @ta is the transmitter addresses.
- */
+ * headroom of eight octets for IV and Ext. IV and taildroom of four octets
+ * for ICV. @payload_len is the length of payload (_not_ including extra
+ * headroom and tailroom). @ta is the transmitter addresses. */
void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
struct ieee80211_key *key,
u8 *pos, size_t payload_len, u8 *ta)
@@ -211,11 +209,12 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
/* Calculate per-packet key */
- if (ctx->iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT)
+ if (ctx->iv16 == 0 || !ctx->initialized)
tkip_mixing_phase1(tk, ctx, ta, ctx->iv32);
tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key);
+ pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16);
ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len);
}
@@ -260,7 +259,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
if ((keyid >> 6) != key->conf.keyidx)
return TKIP_DECRYPT_INVALID_KEYIDX;
- if (key->u.tkip.rx[queue].state != TKIP_STATE_NOT_INIT &&
+ if (key->u.tkip.rx[queue].initialized &&
(iv32 < key->u.tkip.rx[queue].iv32 ||
(iv32 == key->u.tkip.rx[queue].iv32 &&
iv16 <= key->u.tkip.rx[queue].iv16))) {
@@ -276,11 +275,11 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
if (only_iv) {
res = TKIP_DECRYPT_OK;
- key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED;
+ key->u.tkip.rx[queue].initialized = 1;
goto done;
}
- if (key->u.tkip.rx[queue].state == TKIP_STATE_NOT_INIT ||
+ if (!key->u.tkip.rx[queue].initialized ||
key->u.tkip.rx[queue].iv32 != iv32) {
/* IV16 wrapped around - perform TKIP phase 1 */
tkip_mixing_phase1(tk, &key->u.tkip.rx[queue], ta, iv32);
@@ -300,18 +299,18 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
printk("\n");
}
#endif
- }
- if (key->local->ops->update_tkip_key &&
- key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
- key->u.tkip.rx[queue].state != TKIP_STATE_PHASE1_HW_UPLOADED) {
- struct ieee80211_sub_if_data *sdata = key->sdata;
-
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- sdata = container_of(key->sdata->bss,
- struct ieee80211_sub_if_data, u.ap);
- drv_update_tkip_key(key->local, sdata, &key->conf, key->sta,
- iv32, key->u.tkip.rx[queue].p1k);
- key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED;
+ if (key->local->ops->update_tkip_key &&
+ key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
+ static const u8 bcast[ETH_ALEN] =
+ {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ const u8 *sta_addr = key->sta->sta.addr;
+
+ if (is_multicast_ether_addr(ra))
+ sta_addr = bcast;
+
+ drv_update_tkip_key(key->local, &key->conf, sta_addr,
+ iv32, key->u.tkip.rx[queue].p1k);
+ }
}
tkip_mixing_phase2(tk, &key->u.tkip.rx[queue], iv16, rc4key);
diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c
index cbe53ed4fb0b..ac210b586702 100644
--- a/trunk/net/mac80211/tx.c
+++ b/trunk/net/mac80211/tx.c
@@ -180,71 +180,6 @@ static int inline is_ieee80211_device(struct ieee80211_local *local,
}
/* tx handlers */
-static ieee80211_tx_result debug_noinline
-ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
-{
- struct ieee80211_local *local = tx->local;
- struct ieee80211_if_managed *ifmgd;
-
- /* driver doesn't support power save */
- if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
- return TX_CONTINUE;
-
- /* hardware does dynamic power save */
- if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
- return TX_CONTINUE;
-
- /* dynamic power save disabled */
- if (local->hw.conf.dynamic_ps_timeout <= 0)
- return TX_CONTINUE;
-
- /* we are scanning, don't enable power save */
- if (local->scanning)
- return TX_CONTINUE;
-
- if (!local->ps_sdata)
- return TX_CONTINUE;
-
- /* No point if we're going to suspend */
- if (local->quiescing)
- return TX_CONTINUE;
-
- /* dynamic ps is supported only in managed mode */
- if (tx->sdata->vif.type != NL80211_IFTYPE_STATION)
- return TX_CONTINUE;
-
- ifmgd = &tx->sdata->u.mgd;
-
- /*
- * Don't wakeup from power save if u-apsd is enabled, voip ac has
- * u-apsd enabled and the frame is in voip class. This effectively
- * means that even if all access categories have u-apsd enabled, in
- * practise u-apsd is only used with the voip ac. This is a
- * workaround for the case when received voip class packets do not
- * have correct qos tag for some reason, due the network or the
- * peer application.
- *
- * Note: local->uapsd_queues access is racy here. If the value is
- * changed via debugfs, user needs to reassociate manually to have
- * everything in sync.
- */
- if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED)
- && (local->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
- && skb_get_queue_mapping(tx->skb) == 0)
- return TX_CONTINUE;
-
- if (local->hw.conf.flags & IEEE80211_CONF_PS) {
- ieee80211_stop_queues_by_reason(&local->hw,
- IEEE80211_QUEUE_STOP_REASON_PS);
- ieee80211_queue_work(&local->hw,
- &local->dynamic_ps_disable_work);
- }
-
- mod_timer(&local->dynamic_ps_timer, jiffies +
- msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
-
- return TX_CONTINUE;
-}
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
@@ -288,7 +223,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: dropped data frame to not "
"associated station %pM\n",
- tx->sdata->name, hdr->addr1);
+ tx->dev->name, hdr->addr1);
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
return TX_DROP;
@@ -396,7 +331,7 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
if (net_ratelimit())
printk(KERN_DEBUG "%s: BC TX buffer full - dropping the oldest frame\n",
- tx->sdata->name);
+ tx->dev->name);
#endif
dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf));
} else
@@ -456,7 +391,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: STA %pM TX "
"buffer full - dropping oldest frame\n",
- tx->sdata->name, sta->sta.addr);
+ tx->dev->name, sta->sta.addr);
}
#endif
dev_kfree_skb(old);
@@ -481,7 +416,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
else if (unlikely(staflags & WLAN_STA_PS_STA)) {
printk(KERN_DEBUG "%s: STA %pM in PS mode, but pspoll "
- "set -> send frame\n", tx->sdata->name,
+ "set -> send frame\n", tx->dev->name,
sta->sta.addr);
}
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
@@ -529,8 +464,6 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
tx->key = NULL;
if (tx->key) {
- bool skip_hw = false;
-
tx->key->tx_rx_count++;
/* TODO: add threshold stuff again */
@@ -547,32 +480,16 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
!ieee80211_use_mfp(hdr->frame_control, tx->sta,
tx->skb))
tx->key = NULL;
- else
- skip_hw = (tx->key->conf.flags &
- IEEE80211_KEY_FLAG_SW_MGMT) &&
- ieee80211_is_mgmt(hdr->frame_control);
break;
case ALG_AES_CMAC:
if (!ieee80211_is_mgmt(hdr->frame_control))
tx->key = NULL;
break;
}
-
- if (!skip_hw && tx->key &&
- tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
- info->control.hw_key = &tx->key->conf;
}
- return TX_CONTINUE;
-}
-
-static ieee80211_tx_result debug_noinline
-ieee80211_tx_h_sta(struct ieee80211_tx_data *tx)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
-
- if (tx->sta && tx->sta->uploaded)
- info->control.sta = &tx->sta->sta;
+ if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
+ info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
return TX_CONTINUE;
}
@@ -602,12 +519,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
txrc.bss_conf = &tx->sdata->vif.bss_conf;
txrc.skb = tx->skb;
txrc.reported_rate.idx = -1;
- txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[tx->channel->band];
- if (txrc.rate_idx_mask == (1 << sband->n_bitrates) - 1)
- txrc.max_rate_idx = -1;
- else
- txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
- txrc.ap = tx->sdata->vif.type == NL80211_IFTYPE_AP;
+ txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx;
/* set up RTS protection if desired */
if (len > tx->local->hw.wiphy->rts_threshold) {
@@ -637,7 +549,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
"%s: Dropped data frame as no usable bitrate found while "
"scanning and associated. Target station: "
"%pM on %d GHz band\n",
- tx->sdata->name, hdr->addr1,
+ tx->dev->name, hdr->addr1,
tx->channel->band ? 5 : 2))
return TX_DROP;
@@ -751,6 +663,17 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
return TX_CONTINUE;
}
+static ieee80211_tx_result debug_noinline
+ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+
+ if (tx->sta)
+ info->control.sta = &tx->sta->sta;
+
+ return TX_CONTINUE;
+}
+
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
{
@@ -1010,8 +933,7 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
(struct ieee80211_radiotap_header *) skb->data;
struct ieee80211_supported_band *sband;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
- NULL);
+ int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len);
sband = tx->local->hw.wiphy->bands[tx->channel->band];
@@ -1047,7 +969,7 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
* because it will be recomputed and added
* on transmission
*/
- if (skb->len < (iterator._max_length + FCS_LEN))
+ if (skb->len < (iterator.max_length + FCS_LEN))
return false;
skb_trim(skb, skb->len - FCS_LEN);
@@ -1074,10 +996,10 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
/*
* remove the radiotap header
- * iterator->_max_length was sanity-checked against
+ * iterator->max_length was sanity-checked against
* skb->len by iterator init
*/
- skb_pull(skb, iterator._max_length);
+ skb_pull(skb, iterator.max_length);
return true;
}
@@ -1099,6 +1021,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
memset(tx, 0, sizeof(*tx));
tx->skb = skb;
+ tx->dev = sdata->dev; /* use original interface */
tx->local = local;
tx->sdata = sdata;
tx->channel = local->hw.conf.channel;
@@ -1109,7 +1032,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
tx->flags |= IEEE80211_TX_FRAGMENTED;
/* process and remove the injection radiotap header */
- if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) {
+ if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) {
if (!__ieee80211_parse_tx_radiotap(tx, skb))
return TX_DROP;
@@ -1118,7 +1041,6 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
* the radiotap header that was present and pre-filled
* 'tx' with tx control information.
*/
- info->flags &= ~IEEE80211_TX_INTFL_HAS_RADIOTAP;
}
/*
@@ -1130,15 +1052,10 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
hdr = (struct ieee80211_hdr *) skb->data;
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
tx->sta = rcu_dereference(sdata->u.vlan.sta);
- if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr)
- return TX_DROP;
- } else if (info->flags & IEEE80211_TX_CTL_INJECTED) {
- tx->sta = sta_info_get_bss(sdata, hdr->addr1);
- }
if (!tx->sta)
- tx->sta = sta_info_get(sdata, hdr->addr1);
+ tx->sta = sta_info_get(local, hdr->addr1);
if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) {
@@ -1290,7 +1207,6 @@ static int __ieee80211_tx(struct ieee80211_local *local,
static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
{
struct sk_buff *skb = tx->skb;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
ieee80211_tx_result res = TX_DROP;
#define CALL_TXH(txh) \
@@ -1300,18 +1216,13 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
goto txh_done; \
} while (0)
- CALL_TXH(ieee80211_tx_h_dynamic_ps);
CALL_TXH(ieee80211_tx_h_check_assoc);
CALL_TXH(ieee80211_tx_h_ps_buf);
CALL_TXH(ieee80211_tx_h_select_key);
- CALL_TXH(ieee80211_tx_h_sta);
+ CALL_TXH(ieee80211_tx_h_michael_mic_add);
if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
CALL_TXH(ieee80211_tx_h_rate_ctrl);
-
- if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION))
- goto txh_done;
-
- CALL_TXH(ieee80211_tx_h_michael_mic_add);
+ CALL_TXH(ieee80211_tx_h_misc);
CALL_TXH(ieee80211_tx_h_sequence);
CALL_TXH(ieee80211_tx_h_fragment);
/* handlers after fragment must be aware of tx info fragmentation! */
@@ -1487,6 +1398,34 @@ static int ieee80211_skb_resize(struct ieee80211_local *local,
return 0;
}
+static bool need_dynamic_ps(struct ieee80211_local *local)
+{
+ /* driver doesn't support power save */
+ if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
+ return false;
+
+ /* hardware does dynamic power save */
+ if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
+ return false;
+
+ /* dynamic power save disabled */
+ if (local->hw.conf.dynamic_ps_timeout <= 0)
+ return false;
+
+ /* we are scanning, don't enable power save */
+ if (local->scanning)
+ return false;
+
+ if (!local->ps_sdata)
+ return false;
+
+ /* No point if we're going to suspend */
+ if (local->quiescing)
+ return false;
+
+ return true;
+}
+
static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb)
{
@@ -1497,14 +1436,25 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
int headroom;
bool may_encrypt;
+ if (need_dynamic_ps(local)) {
+ if (local->hw.conf.flags & IEEE80211_CONF_PS) {
+ ieee80211_stop_queues_by_reason(&local->hw,
+ IEEE80211_QUEUE_STOP_REASON_PS);
+ ieee80211_queue_work(&local->hw,
+ &local->dynamic_ps_disable_work);
+ }
+
+ mod_timer(&local->dynamic_ps_timer, jiffies +
+ msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
+ }
+
rcu_read_lock();
if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) {
int hdrlen;
u16 len_rthdr;
- info->flags |= IEEE80211_TX_CTL_INJECTED |
- IEEE80211_TX_INTFL_HAS_RADIOTAP;
+ info->flags |= IEEE80211_TX_CTL_INJECTED;
len_rthdr = ieee80211_get_radiotap_len(skb->data);
hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
@@ -1524,11 +1474,11 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
list_for_each_entry_rcu(tmp_sdata, &local->interfaces,
list) {
- if (!ieee80211_sdata_running(tmp_sdata))
+ if (!netif_running(tmp_sdata->dev))
continue;
if (tmp_sdata->vif.type != NL80211_IFTYPE_AP)
continue;
- if (compare_ether_addr(tmp_sdata->vif.addr,
+ if (compare_ether_addr(tmp_sdata->dev->dev_addr,
hdr->addr2) == 0) {
sdata = tmp_sdata;
break;
@@ -1692,7 +1642,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
/* RA TA DA SA */
memcpy(hdr.addr1, sta->sta.addr, ETH_ALEN);
- memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
+ memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
memcpy(hdr.addr3, skb->data, ETH_ALEN);
memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
hdrlen = 30;
@@ -1706,7 +1656,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
/* DA BSSID SA */
memcpy(hdr.addr1, skb->data, ETH_ALEN);
- memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
+ memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
hdrlen = 24;
break;
@@ -1714,7 +1664,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
/* RA TA DA SA */
memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN);
- memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
+ memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
memcpy(hdr.addr3, skb->data, ETH_ALEN);
memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
hdrlen = 30;
@@ -1728,8 +1678,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
goto fail;
}
- if (compare_ether_addr(sdata->vif.addr,
- skb->data + ETH_ALEN) == 0) {
+ if (compare_ether_addr(dev->dev_addr,
+ skb->data + ETH_ALEN) == 0) {
hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
skb->data, skb->data + ETH_ALEN);
meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
@@ -1759,7 +1709,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
}
}
hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
- mesh_da, sdata->vif.addr);
+ mesh_da, dev->dev_addr);
rcu_read_unlock();
if (is_mesh_mcast)
meshhdrlen =
@@ -1784,7 +1734,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
if (sdata->u.mgd.use_4addr && ethertype != ETH_P_PAE) {
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
/* RA TA DA SA */
- memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
+ memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
memcpy(hdr.addr3, skb->data, ETH_ALEN);
memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
hdrlen = 30;
@@ -1815,8 +1765,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
*/
if (!is_multicast_ether_addr(hdr.addr1)) {
rcu_read_lock();
- sta = sta_info_get(sdata, hdr.addr1);
- if (sta)
+ sta = sta_info_get(local, hdr.addr1);
+ /* XXX: in the future, use sdata to look up the sta */
+ if (sta && sta->sdata == sdata)
sta_flags = get_sta_flags(sta);
rcu_read_unlock();
}
@@ -1835,7 +1786,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
unlikely(!is_multicast_ether_addr(hdr.addr1) &&
!(sta_flags & WLAN_STA_AUTHORIZED) &&
!(ethertype == ETH_P_PAE &&
- compare_ether_addr(sdata->vif.addr,
+ compare_ether_addr(dev->dev_addr,
skb->data + ETH_ALEN) == 0))) {
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
if (net_ratelimit())
@@ -1975,7 +1926,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
ieee80211_tx(sdata, skb, true);
} else {
hdr = (struct ieee80211_hdr *)skb->data;
- sta = sta_info_get(sdata, hdr->addr1);
+ sta = sta_info_get(local, hdr->addr1);
ret = __ieee80211_tx(local, &skb, sta, true);
if (ret != IEEE80211_TX_OK)
@@ -2111,7 +2062,6 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
struct beacon_data *beacon;
struct ieee80211_supported_band *sband;
enum ieee80211_band band = local->hw.conf.channel->band;
- struct ieee80211_tx_rate_control txrc;
sband = local->hw.wiphy->bands[band];
@@ -2200,8 +2150,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
mgmt->frame_control =
cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
memset(mgmt->da, 0xff, ETH_ALEN);
- memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
- memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
+ memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
+ memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
mgmt->u.beacon.beacon_int =
cpu_to_le16(sdata->vif.bss_conf.beacon_int);
mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */
@@ -2219,25 +2169,21 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
info = IEEE80211_SKB_CB(skb);
info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
- info->flags |= IEEE80211_TX_CTL_NO_ACK;
info->band = band;
-
- memset(&txrc, 0, sizeof(txrc));
- txrc.hw = hw;
- txrc.sband = sband;
- txrc.bss_conf = &sdata->vif.bss_conf;
- txrc.skb = skb;
- txrc.reported_rate.idx = -1;
- txrc.rate_idx_mask = sdata->rc_rateidx_mask[band];
- if (txrc.rate_idx_mask == (1 << sband->n_bitrates) - 1)
- txrc.max_rate_idx = -1;
- else
- txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
- txrc.ap = true;
- rate_control_get_rate(sdata, NULL, &txrc);
+ /*
+ * XXX: For now, always use the lowest rate
+ */
+ info->control.rates[0].idx = 0;
+ info->control.rates[0].count = 1;
+ info->control.rates[1].idx = -1;
+ info->control.rates[2].idx = -1;
+ info->control.rates[3].idx = -1;
+ info->control.rates[4].idx = -1;
+ BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5);
info->control.vif = vif;
+ info->flags |= IEEE80211_TX_CTL_NO_ACK;
info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
out:
@@ -2246,134 +2192,6 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL(ieee80211_beacon_get_tim);
-struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
-{
- struct ieee80211_sub_if_data *sdata;
- struct ieee80211_if_managed *ifmgd;
- struct ieee80211_pspoll *pspoll;
- struct ieee80211_local *local;
- struct sk_buff *skb;
-
- if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
- return NULL;
-
- sdata = vif_to_sdata(vif);
- ifmgd = &sdata->u.mgd;
- local = sdata->local;
-
- skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll));
- if (!skb) {
- printk(KERN_DEBUG "%s: failed to allocate buffer for "
- "pspoll template\n", sdata->name);
- return NULL;
- }
- skb_reserve(skb, local->hw.extra_tx_headroom);
-
- pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll));
- memset(pspoll, 0, sizeof(*pspoll));
- pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
- IEEE80211_STYPE_PSPOLL);
- pspoll->aid = cpu_to_le16(ifmgd->aid);
-
- /* aid in PS-Poll has its two MSBs each set to 1 */
- pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14);
-
- memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN);
- memcpy(pspoll->ta, vif->addr, ETH_ALEN);
-
- return skb;
-}
-EXPORT_SYMBOL(ieee80211_pspoll_get);
-
-struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
-{
- struct ieee80211_hdr_3addr *nullfunc;
- struct ieee80211_sub_if_data *sdata;
- struct ieee80211_if_managed *ifmgd;
- struct ieee80211_local *local;
- struct sk_buff *skb;
-
- if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
- return NULL;
-
- sdata = vif_to_sdata(vif);
- ifmgd = &sdata->u.mgd;
- local = sdata->local;
-
- skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*nullfunc));
- if (!skb) {
- printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
- "template\n", sdata->name);
- return NULL;
- }
- skb_reserve(skb, local->hw.extra_tx_headroom);
-
- nullfunc = (struct ieee80211_hdr_3addr *) skb_put(skb,
- sizeof(*nullfunc));
- memset(nullfunc, 0, sizeof(*nullfunc));
- nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
- IEEE80211_STYPE_NULLFUNC |
- IEEE80211_FCTL_TODS);
- memcpy(nullfunc->addr1, ifmgd->bssid, ETH_ALEN);
- memcpy(nullfunc->addr2, vif->addr, ETH_ALEN);
- memcpy(nullfunc->addr3, ifmgd->bssid, ETH_ALEN);
-
- return skb;
-}
-EXPORT_SYMBOL(ieee80211_nullfunc_get);
-
-struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *ssid, size_t ssid_len,
- const u8 *ie, size_t ie_len)
-{
- struct ieee80211_sub_if_data *sdata;
- struct ieee80211_local *local;
- struct ieee80211_hdr_3addr *hdr;
- struct sk_buff *skb;
- size_t ie_ssid_len;
- u8 *pos;
-
- sdata = vif_to_sdata(vif);
- local = sdata->local;
- ie_ssid_len = 2 + ssid_len;
-
- skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) +
- ie_ssid_len + ie_len);
- if (!skb) {
- printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
- "request template\n", sdata->name);
- return NULL;
- }
-
- skb_reserve(skb, local->hw.extra_tx_headroom);
-
- hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr));
- memset(hdr, 0, sizeof(*hdr));
- hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
- IEEE80211_STYPE_PROBE_REQ);
- memset(hdr->addr1, 0xff, ETH_ALEN);
- memcpy(hdr->addr2, vif->addr, ETH_ALEN);
- memset(hdr->addr3, 0xff, ETH_ALEN);
-
- pos = skb_put(skb, ie_ssid_len);
- *pos++ = WLAN_EID_SSID;
- *pos++ = ssid_len;
- if (ssid)
- memcpy(pos, ssid, ssid_len);
- pos += ssid_len;
-
- if (ie) {
- pos = skb_put(skb, ie_len);
- memcpy(pos, ie, ie_len);
- }
-
- return skb;
-}
-EXPORT_SYMBOL(ieee80211_probereq_get);
-
void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
const void *frame, size_t frame_len,
const struct ieee80211_tx_info *frame_txctl,
diff --git a/trunk/net/mac80211/util.c b/trunk/net/mac80211/util.c
index c453226f06b2..3848140313f5 100644
--- a/trunk/net/mac80211/util.c
+++ b/trunk/net/mac80211/util.c
@@ -18,6 +18,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -479,8 +480,8 @@ void ieee80211_iterate_active_interfaces(
case NL80211_IFTYPE_MESH_POINT:
break;
}
- if (ieee80211_sdata_running(sdata))
- iterator(data, sdata->vif.addr,
+ if (netif_running(sdata->dev))
+ iterator(data, sdata->dev->dev_addr,
&sdata->vif);
}
@@ -513,8 +514,8 @@ void ieee80211_iterate_active_interfaces_atomic(
case NL80211_IFTYPE_MESH_POINT:
break;
}
- if (ieee80211_sdata_running(sdata))
- iterator(data, sdata->vif.addr,
+ if (netif_running(sdata->dev))
+ iterator(data, sdata->dev->dev_addr,
&sdata->vif);
}
@@ -792,8 +793,6 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
break;
}
- qparam.uapsd = false;
-
drv_conf_tx(local, queue, &qparam);
}
}
@@ -861,7 +860,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
sizeof(*mgmt) + 6 + extra_len);
if (!skb) {
printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
- "frame\n", sdata->name);
+ "frame\n", sdata->dev->name);
return;
}
skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -871,7 +870,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_AUTH);
memcpy(mgmt->da, bssid, ETH_ALEN);
- memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+ memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
memcpy(mgmt->bssid, bssid, ETH_ALEN);
mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg);
mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
@@ -894,87 +893,43 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
enum ieee80211_band band)
{
struct ieee80211_supported_band *sband;
- u8 *pos;
- size_t offset = 0, noffset;
- int supp_rates_len, i;
+ u8 *pos, *supp_rates_len, *esupp_rates_len = NULL;
+ int i;
sband = local->hw.wiphy->bands[band];
pos = buffer;
- supp_rates_len = min_t(int, sband->n_bitrates, 8);
-
*pos++ = WLAN_EID_SUPP_RATES;
- *pos++ = supp_rates_len;
-
- for (i = 0; i < supp_rates_len; i++) {
- int rate = sband->bitrates[i].bitrate;
- *pos++ = (u8) (rate / 5);
- }
-
- /* insert "request information" if in custom IEs */
- if (ie && ie_len) {
- static const u8 before_extrates[] = {
- WLAN_EID_SSID,
- WLAN_EID_SUPP_RATES,
- WLAN_EID_REQUEST,
- };
- noffset = ieee80211_ie_split(ie, ie_len,
- before_extrates,
- ARRAY_SIZE(before_extrates),
- offset);
- memcpy(pos, ie + offset, noffset - offset);
- pos += noffset - offset;
- offset = noffset;
- }
-
- if (sband->n_bitrates > i) {
- *pos++ = WLAN_EID_EXT_SUPP_RATES;
- *pos++ = sband->n_bitrates - i;
-
- for (; i < sband->n_bitrates; i++) {
- int rate = sband->bitrates[i].bitrate;
- *pos++ = (u8) (rate / 5);
- }
- }
+ supp_rates_len = pos;
+ *pos++ = 0;
+
+ for (i = 0; i < sband->n_bitrates; i++) {
+ struct ieee80211_rate *rate = &sband->bitrates[i];
+
+ if (esupp_rates_len) {
+ *esupp_rates_len += 1;
+ } else if (*supp_rates_len == 8) {
+ *pos++ = WLAN_EID_EXT_SUPP_RATES;
+ esupp_rates_len = pos;
+ *pos++ = 1;
+ } else
+ *supp_rates_len += 1;
- /* insert custom IEs that go before HT */
- if (ie && ie_len) {
- static const u8 before_ht[] = {
- WLAN_EID_SSID,
- WLAN_EID_SUPP_RATES,
- WLAN_EID_REQUEST,
- WLAN_EID_EXT_SUPP_RATES,
- WLAN_EID_DS_PARAMS,
- WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
- };
- noffset = ieee80211_ie_split(ie, ie_len,
- before_ht, ARRAY_SIZE(before_ht),
- offset);
- memcpy(pos, ie + offset, noffset - offset);
- pos += noffset - offset;
- offset = noffset;
+ *pos++ = rate->bitrate / 5;
}
if (sband->ht_cap.ht_supported) {
- u16 cap = sband->ht_cap.cap;
- __le16 tmp;
-
- if (ieee80211_disable_40mhz_24ghz &&
- sband->band == IEEE80211_BAND_2GHZ) {
- cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- cap &= ~IEEE80211_HT_CAP_SGI_40;
- }
+ __le16 tmp = cpu_to_le16(sband->ht_cap.cap);
*pos++ = WLAN_EID_HT_CAPABILITY;
*pos++ = sizeof(struct ieee80211_ht_cap);
memset(pos, 0, sizeof(struct ieee80211_ht_cap));
- tmp = cpu_to_le16(cap);
memcpy(pos, &tmp, sizeof(u16));
pos += sizeof(u16);
+ /* TODO: needs a define here for << 2 */
*pos++ = sband->ht_cap.ampdu_factor |
- (sband->ht_cap.ampdu_density <<
- IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
+ (sband->ht_cap.ampdu_density << 2);
memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
pos += sizeof(sband->ht_cap.mcs);
pos += 2 + 4 + 1; /* ext info, BF cap, antsel */
@@ -985,11 +940,9 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
* that calculates local->scan_ies_len.
*/
- /* add any remaining custom IEs */
- if (ie && ie_len) {
- noffset = ie_len;
- memcpy(pos, ie + offset, noffset - offset);
- pos += noffset - offset;
+ if (ie) {
+ memcpy(pos, ie, ie_len);
+ pos += ie_len;
}
return pos - buffer;
@@ -1002,33 +955,40 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
- size_t buf_len;
- u8 *buf;
-
- /* FIXME: come up with a proper value */
- buf = kmalloc(200 + ie_len, GFP_KERNEL);
- if (!buf) {
- printk(KERN_DEBUG "%s: failed to allocate temporary IE "
- "buffer\n", sdata->name);
+ u8 *pos;
+
+ skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 +
+ ie_len);
+ if (!skb) {
+ printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
+ "request\n", sdata->dev->name);
return;
}
+ skb_reserve(skb, local->hw.extra_tx_headroom);
- buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len,
- local->hw.conf.channel->band);
-
- skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
- ssid, ssid_len,
- buf, buf_len);
-
+ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+ memset(mgmt, 0, 24);
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_PROBE_REQ);
+ memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
if (dst) {
- mgmt = (struct ieee80211_mgmt *) skb->data;
memcpy(mgmt->da, dst, ETH_ALEN);
memcpy(mgmt->bssid, dst, ETH_ALEN);
+ } else {
+ memset(mgmt->da, 0xff, ETH_ALEN);
+ memset(mgmt->bssid, 0xff, ETH_ALEN);
}
+ pos = skb_put(skb, 2 + ssid_len);
+ *pos++ = WLAN_EID_SSID;
+ *pos++ = ssid_len;
+ memcpy(pos, ssid, ssid_len);
+ pos += ssid_len;
+
+ skb_put(skb, ieee80211_build_preq_ies(local, pos, ie, ie_len,
+ local->hw.conf.channel->band));
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
ieee80211_tx_skb(sdata, skb);
- kfree(buf);
}
u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
@@ -1072,16 +1032,18 @@ void ieee80211_stop_device(struct ieee80211_local *local)
ieee80211_led_radio(local, false);
cancel_work_sync(&local->reconfig_filter);
+ drv_stop(local);
flush_workqueue(local->workqueue);
- drv_stop(local);
}
int ieee80211_reconfig(struct ieee80211_local *local)
{
struct ieee80211_hw *hw = &local->hw;
struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_if_init_conf conf;
struct sta_info *sta;
+ unsigned long flags;
int res;
if (local->suspended)
@@ -1099,7 +1061,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
if (res) {
WARN(local->suspended, "Harware became unavailable "
"upon resume. This is could be a software issue"
- "prior to suspend or a hardware issue\n");
+ "prior to suspend or a harware issue\n");
return res;
}
@@ -1110,24 +1072,29 @@ int ieee80211_reconfig(struct ieee80211_local *local)
list_for_each_entry(sdata, &local->interfaces, list) {
if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
sdata->vif.type != NL80211_IFTYPE_MONITOR &&
- ieee80211_sdata_running(sdata))
- res = drv_add_interface(local, &sdata->vif);
+ netif_running(sdata->dev)) {
+ conf.vif = &sdata->vif;
+ conf.type = sdata->vif.type;
+ conf.mac_addr = sdata->dev->dev_addr;
+ res = drv_add_interface(local, &conf);
+ }
}
/* add STAs back */
- mutex_lock(&local->sta_mtx);
- list_for_each_entry(sta, &local->sta_list, list) {
- if (sta->uploaded) {
+ if (local->ops->sta_notify) {
+ spin_lock_irqsave(&local->sta_lock, flags);
+ list_for_each_entry(sta, &local->sta_list, list) {
sdata = sta->sdata;
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
sdata = container_of(sdata->bss,
struct ieee80211_sub_if_data,
u.ap);
- WARN_ON(drv_sta_add(local, sdata, &sta->sta));
+ drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD,
+ &sta->sta);
}
+ spin_unlock_irqrestore(&local->sta_lock, flags);
}
- mutex_unlock(&local->sta_mtx);
/* Clear Suspend state so that ADDBA requests can be processed */
@@ -1152,7 +1119,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
/* Finally also reconfigure all the BSS information */
list_for_each_entry(sdata, &local->interfaces, list) {
u32 changed = ~0;
- if (!ieee80211_sdata_running(sdata))
+ if (!netif_running(sdata->dev))
continue;
switch (sdata->vif.type) {
case NL80211_IFTYPE_STATION:
@@ -1178,17 +1145,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
}
}
- rcu_read_lock();
- if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
- list_for_each_entry_rcu(sta, &local->sta_list, list) {
- ieee80211_sta_tear_down_BA_sessions(sta);
- }
- }
- rcu_read_unlock();
-
/* add back keys */
list_for_each_entry(sdata, &local->interfaces, list)
- if (ieee80211_sdata_running(sdata))
+ if (netif_running(sdata->dev))
ieee80211_enable_keys(sdata);
ieee80211_wake_queues_by_reason(hw,
@@ -1225,143 +1184,13 @@ int ieee80211_reconfig(struct ieee80211_local *local)
add_timer(&local->sta_cleanup);
- mutex_lock(&local->sta_mtx);
+ spin_lock_irqsave(&local->sta_lock, flags);
list_for_each_entry(sta, &local->sta_list, list)
mesh_plink_restart(sta);
- mutex_unlock(&local->sta_mtx);
+ spin_unlock_irqrestore(&local->sta_lock, flags);
#else
WARN_ON(1);
#endif
return 0;
}
-static int check_mgd_smps(struct ieee80211_if_managed *ifmgd,
- enum ieee80211_smps_mode *smps_mode)
-{
- if (ifmgd->associated) {
- *smps_mode = ifmgd->ap_smps;
-
- if (*smps_mode == IEEE80211_SMPS_AUTOMATIC) {
- if (ifmgd->powersave)
- *smps_mode = IEEE80211_SMPS_DYNAMIC;
- else
- *smps_mode = IEEE80211_SMPS_OFF;
- }
-
- return 1;
- }
-
- return 0;
-}
-
-/* must hold iflist_mtx */
-void ieee80211_recalc_smps(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *forsdata)
-{
- struct ieee80211_sub_if_data *sdata;
- enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF;
- int count = 0;
-
- if (forsdata)
- WARN_ON(!mutex_is_locked(&forsdata->u.mgd.mtx));
-
- WARN_ON(!mutex_is_locked(&local->iflist_mtx));
-
- /*
- * This function could be improved to handle multiple
- * interfaces better, but right now it makes any
- * non-station interfaces force SM PS to be turned
- * off. If there are multiple station interfaces it
- * could also use the best possible mode, e.g. if
- * one is in static and the other in dynamic then
- * dynamic is ok.
- */
-
- list_for_each_entry(sdata, &local->interfaces, list) {
- if (!netif_running(sdata->dev))
- continue;
- if (sdata->vif.type != NL80211_IFTYPE_STATION)
- goto set;
- if (sdata != forsdata) {
- /*
- * This nested is ok -- we are holding the iflist_mtx
- * so can't get here twice or so. But it's required
- * since normally we acquire it first and then the
- * iflist_mtx.
- */
- mutex_lock_nested(&sdata->u.mgd.mtx, SINGLE_DEPTH_NESTING);
- count += check_mgd_smps(&sdata->u.mgd, &smps_mode);
- mutex_unlock(&sdata->u.mgd.mtx);
- } else
- count += check_mgd_smps(&sdata->u.mgd, &smps_mode);
-
- if (count > 1) {
- smps_mode = IEEE80211_SMPS_OFF;
- break;
- }
- }
-
- if (smps_mode == local->smps_mode)
- return;
-
- set:
- local->smps_mode = smps_mode;
- /* changed flag is auto-detected for this */
- ieee80211_hw_config(local, 0);
-}
-
-static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
-{
- int i;
-
- for (i = 0; i < n_ids; i++)
- if (ids[i] == id)
- return true;
- return false;
-}
-
-/**
- * ieee80211_ie_split - split an IE buffer according to ordering
- *
- * @ies: the IE buffer
- * @ielen: the length of the IE buffer
- * @ids: an array with element IDs that are allowed before
- * the split
- * @n_ids: the size of the element ID array
- * @offset: offset where to start splitting in the buffer
- *
- * This function splits an IE buffer by updating the @offset
- * variable to point to the location where the buffer should be
- * split.
- *
- * It assumes that the given IE buffer is well-formed, this
- * has to be guaranteed by the caller!
- *
- * It also assumes that the IEs in the buffer are ordered
- * correctly, if not the result of using this function will not
- * be ordered correctly either, i.e. it does no reordering.
- *
- * The function returns the offset where the next part of the
- * buffer starts, which may be @ielen if the entire (remainder)
- * of the buffer should be used.
- */
-size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
- const u8 *ids, int n_ids, size_t offset)
-{
- size_t pos = offset;
-
- while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos]))
- pos += 2 + ies[pos + 1];
-
- return pos;
-}
-
-size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)
-{
- size_t pos = offset;
-
- while (pos < ielen && ies[pos] != WLAN_EID_VENDOR_SPECIFIC)
- pos += 2 + ies[pos + 1];
-
- return pos;
-}
diff --git a/trunk/net/mac80211/wep.c b/trunk/net/mac80211/wep.c
index 5d745f2d7236..247123fe1a7a 100644
--- a/trunk/net/mac80211/wep.c
+++ b/trunk/net/mac80211/wep.c
@@ -305,19 +305,20 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- if (!info->control.hw_key) {
+ if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key,
tx->key->conf.keylen,
tx->key->conf.keyidx))
return -1;
- } else if (info->control.hw_key->flags &
- IEEE80211_KEY_FLAG_GENERATE_IV) {
- if (!ieee80211_wep_add_iv(tx->local, skb,
- tx->key->conf.keylen,
- tx->key->conf.keyidx))
- return -1;
+ } else {
+ info->control.hw_key = &tx->key->conf;
+ if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) {
+ if (!ieee80211_wep_add_iv(tx->local, skb,
+ tx->key->conf.keylen,
+ tx->key->conf.keyidx))
+ return -1;
+ }
}
-
return 0;
}
diff --git a/trunk/net/mac80211/wme.c b/trunk/net/mac80211/wme.c
index 34e6d02da779..79d887dae738 100644
--- a/trunk/net/mac80211/wme.c
+++ b/trunk/net/mac80211/wme.c
@@ -96,7 +96,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
}
if (!sta && ra && !is_multicast_ether_addr(ra)) {
- sta = sta_info_get(sdata, ra);
+ sta = sta_info_get(local, ra);
if (sta)
sta_flags = get_sta_flags(sta);
}
diff --git a/trunk/net/mac80211/work.c b/trunk/net/mac80211/work.c
deleted file mode 100644
index 7e708d5c88b4..000000000000
--- a/trunk/net/mac80211/work.c
+++ /dev/null
@@ -1,1099 +0,0 @@
-/*
- * mac80211 work implementation
- *
- * Copyright 2003-2008, Jouni Malinen
- * Copyright 2004, Instant802 Networks, Inc.
- * Copyright 2005, Devicescape Software, Inc.
- * Copyright 2006-2007 Jiri Benc
- * Copyright 2007, Michael Wu
- * Copyright 2009, Johannes Berg
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "ieee80211_i.h"
-#include "rate.h"
-
-#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
-#define IEEE80211_AUTH_MAX_TRIES 3
-#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
-#define IEEE80211_ASSOC_MAX_TRIES 3
-#define IEEE80211_MAX_PROBE_TRIES 5
-
-enum work_action {
- WORK_ACT_NONE,
- WORK_ACT_TIMEOUT,
- WORK_ACT_DONE,
-};
-
-
-/* utils */
-static inline void ASSERT_WORK_MTX(struct ieee80211_local *local)
-{
- WARN_ON(!mutex_is_locked(&local->work_mtx));
-}
-
-/*
- * We can have multiple work items (and connection probing)
- * scheduling this timer, but we need to take care to only
- * reschedule it when it should fire _earlier_ than it was
- * asked for before, or if it's not pending right now. This
- * function ensures that. Note that it then is required to
- * run this function for all timeouts after the first one
- * has happened -- the work that runs from this timer will
- * do that.
- */
-static void run_again(struct ieee80211_local *local,
- unsigned long timeout)
-{
- ASSERT_WORK_MTX(local);
-
- if (!timer_pending(&local->work_timer) ||
- time_before(timeout, local->work_timer.expires))
- mod_timer(&local->work_timer, timeout);
-}
-
-static void work_free_rcu(struct rcu_head *head)
-{
- struct ieee80211_work *wk =
- container_of(head, struct ieee80211_work, rcu_head);
-
- kfree(wk);
-}
-
-void free_work(struct ieee80211_work *wk)
-{
- call_rcu(&wk->rcu_head, work_free_rcu);
-}
-
-static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len,
- struct ieee80211_supported_band *sband,
- u32 *rates)
-{
- int i, j, count;
- *rates = 0;
- count = 0;
- for (i = 0; i < supp_rates_len; i++) {
- int rate = (supp_rates[i] & 0x7F) * 5;
-
- for (j = 0; j < sband->n_bitrates; j++)
- if (sband->bitrates[j].bitrate == rate) {
- *rates |= BIT(j);
- count++;
- break;
- }
- }
-
- return count;
-}
-
-/* frame sending functions */
-
-static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
- struct ieee80211_supported_band *sband,
- struct ieee80211_channel *channel,
- enum ieee80211_smps_mode smps)
-{
- struct ieee80211_ht_info *ht_info;
- u8 *pos;
- u32 flags = channel->flags;
- u16 cap = sband->ht_cap.cap;
- __le16 tmp;
-
- if (!sband->ht_cap.ht_supported)
- return;
-
- if (!ht_info_ie)
- return;
-
- if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info))
- return;
-
- ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2);
-
- /* determine capability flags */
-
- if (ieee80211_disable_40mhz_24ghz &&
- sband->band == IEEE80211_BAND_2GHZ) {
- cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- cap &= ~IEEE80211_HT_CAP_SGI_40;
- }
-
- switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
- case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
- if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
- cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- cap &= ~IEEE80211_HT_CAP_SGI_40;
- }
- break;
- case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
- if (flags & IEEE80211_CHAN_NO_HT40MINUS) {
- cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- cap &= ~IEEE80211_HT_CAP_SGI_40;
- }
- break;
- }
-
- /* set SM PS mode properly */
- cap &= ~IEEE80211_HT_CAP_SM_PS;
- switch (smps) {
- case IEEE80211_SMPS_AUTOMATIC:
- case IEEE80211_SMPS_NUM_MODES:
- WARN_ON(1);
- case IEEE80211_SMPS_OFF:
- cap |= WLAN_HT_CAP_SM_PS_DISABLED <<
- IEEE80211_HT_CAP_SM_PS_SHIFT;
- break;
- case IEEE80211_SMPS_STATIC:
- cap |= WLAN_HT_CAP_SM_PS_STATIC <<
- IEEE80211_HT_CAP_SM_PS_SHIFT;
- break;
- case IEEE80211_SMPS_DYNAMIC:
- cap |= WLAN_HT_CAP_SM_PS_DYNAMIC <<
- IEEE80211_HT_CAP_SM_PS_SHIFT;
- break;
- }
-
- /* reserve and fill IE */
-
- pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
- *pos++ = WLAN_EID_HT_CAPABILITY;
- *pos++ = sizeof(struct ieee80211_ht_cap);
- memset(pos, 0, sizeof(struct ieee80211_ht_cap));
-
- /* capability flags */
- tmp = cpu_to_le16(cap);
- memcpy(pos, &tmp, sizeof(u16));
- pos += sizeof(u16);
-
- /* AMPDU parameters */
- *pos++ = sband->ht_cap.ampdu_factor |
- (sband->ht_cap.ampdu_density <<
- IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
-
- /* MCS set */
- memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
- pos += sizeof(sband->ht_cap.mcs);
-
- /* extended capabilities */
- pos += sizeof(__le16);
-
- /* BF capabilities */
- pos += sizeof(__le32);
-
- /* antenna selection */
- pos += sizeof(u8);
-}
-
-static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_work *wk)
-{
- struct ieee80211_local *local = sdata->local;
- struct sk_buff *skb;
- struct ieee80211_mgmt *mgmt;
- u8 *pos, qos_info;
- const u8 *ies;
- size_t offset = 0, noffset;
- int i, len, count, rates_len, supp_rates_len;
- u16 capab;
- struct ieee80211_supported_band *sband;
- u32 rates = 0;
-
- sband = local->hw.wiphy->bands[wk->chan->band];
-
- /*
- * Get all rates supported by the device and the AP as
- * some APs don't like getting a superset of their rates
- * in the association request (e.g. D-Link DAP 1353 in
- * b-only mode)...
- */
- rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates,
- wk->assoc.supp_rates_len,
- sband, &rates);
-
- skb = alloc_skb(local->hw.extra_tx_headroom +
- sizeof(*mgmt) + /* bit too much but doesn't matter */
- 2 + wk->assoc.ssid_len + /* SSID */
- 4 + rates_len + /* (extended) rates */
- 4 + /* power capability */
- 2 + 2 * sband->n_channels + /* supported channels */
- 2 + sizeof(struct ieee80211_ht_cap) + /* HT */
- wk->ie_len + /* extra IEs */
- 9, /* WMM */
- GFP_KERNEL);
- if (!skb) {
- printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
- "frame\n", sdata->name);
- return;
- }
- skb_reserve(skb, local->hw.extra_tx_headroom);
-
- capab = WLAN_CAPABILITY_ESS;
-
- if (sband->band == IEEE80211_BAND_2GHZ) {
- if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
- capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
- if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
- capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
- }
-
- if (wk->assoc.capability & WLAN_CAPABILITY_PRIVACY)
- capab |= WLAN_CAPABILITY_PRIVACY;
-
- if ((wk->assoc.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
- (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
- capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
-
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
- memset(mgmt, 0, 24);
- memcpy(mgmt->da, wk->filter_ta, ETH_ALEN);
- memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
- memcpy(mgmt->bssid, wk->filter_ta, ETH_ALEN);
-
- if (!is_zero_ether_addr(wk->assoc.prev_bssid)) {
- skb_put(skb, 10);
- mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
- IEEE80211_STYPE_REASSOC_REQ);
- mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
- mgmt->u.reassoc_req.listen_interval =
- cpu_to_le16(local->hw.conf.listen_interval);
- memcpy(mgmt->u.reassoc_req.current_ap, wk->assoc.prev_bssid,
- ETH_ALEN);
- } else {
- skb_put(skb, 4);
- mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
- IEEE80211_STYPE_ASSOC_REQ);
- mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
- mgmt->u.assoc_req.listen_interval =
- cpu_to_le16(local->hw.conf.listen_interval);
- }
-
- /* SSID */
- ies = pos = skb_put(skb, 2 + wk->assoc.ssid_len);
- *pos++ = WLAN_EID_SSID;
- *pos++ = wk->assoc.ssid_len;
- memcpy(pos, wk->assoc.ssid, wk->assoc.ssid_len);
-
- /* add all rates which were marked to be used above */
- supp_rates_len = rates_len;
- if (supp_rates_len > 8)
- supp_rates_len = 8;
-
- len = sband->n_bitrates;
- pos = skb_put(skb, supp_rates_len + 2);
- *pos++ = WLAN_EID_SUPP_RATES;
- *pos++ = supp_rates_len;
-
- count = 0;
- for (i = 0; i < sband->n_bitrates; i++) {
- if (BIT(i) & rates) {
- int rate = sband->bitrates[i].bitrate;
- *pos++ = (u8) (rate / 5);
- if (++count == 8)
- break;
- }
- }
-
- if (rates_len > count) {
- pos = skb_put(skb, rates_len - count + 2);
- *pos++ = WLAN_EID_EXT_SUPP_RATES;
- *pos++ = rates_len - count;
-
- for (i++; i < sband->n_bitrates; i++) {
- if (BIT(i) & rates) {
- int rate = sband->bitrates[i].bitrate;
- *pos++ = (u8) (rate / 5);
- }
- }
- }
-
- if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) {
- /* 1. power capabilities */
- pos = skb_put(skb, 4);
- *pos++ = WLAN_EID_PWR_CAPABILITY;
- *pos++ = 2;
- *pos++ = 0; /* min tx power */
- *pos++ = wk->chan->max_power; /* max tx power */
-
- /* 2. supported channels */
- /* TODO: get this in reg domain format */
- pos = skb_put(skb, 2 * sband->n_channels + 2);
- *pos++ = WLAN_EID_SUPPORTED_CHANNELS;
- *pos++ = 2 * sband->n_channels;
- for (i = 0; i < sband->n_channels; i++) {
- *pos++ = ieee80211_frequency_to_channel(
- sband->channels[i].center_freq);
- *pos++ = 1; /* one channel in the subband*/
- }
- }
-
- /* if present, add any custom IEs that go before HT */
- if (wk->ie_len && wk->ie) {
- static const u8 before_ht[] = {
- WLAN_EID_SSID,
- WLAN_EID_SUPP_RATES,
- WLAN_EID_EXT_SUPP_RATES,
- WLAN_EID_PWR_CAPABILITY,
- WLAN_EID_SUPPORTED_CHANNELS,
- WLAN_EID_RSN,
- WLAN_EID_QOS_CAPA,
- WLAN_EID_RRM_ENABLED_CAPABILITIES,
- WLAN_EID_MOBILITY_DOMAIN,
- WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
- };
- noffset = ieee80211_ie_split(wk->ie, wk->ie_len,
- before_ht, ARRAY_SIZE(before_ht),
- offset);
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, wk->ie + offset, noffset - offset);
- offset = noffset;
- }
-
- if (wk->assoc.use_11n && wk->assoc.wmm_used &&
- local->hw.queues >= 4)
- ieee80211_add_ht_ie(skb, wk->assoc.ht_information_ie,
- sband, wk->chan, wk->assoc.smps);
-
- /* if present, add any custom non-vendor IEs that go after HT */
- if (wk->ie_len && wk->ie) {
- noffset = ieee80211_ie_split_vendor(wk->ie, wk->ie_len,
- offset);
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, wk->ie + offset, noffset - offset);
- offset = noffset;
- }
-
- if (wk->assoc.wmm_used && local->hw.queues >= 4) {
- if (wk->assoc.uapsd_used) {
- qos_info = local->uapsd_queues;
- qos_info |= (local->uapsd_max_sp_len <<
- IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT);
- } else {
- qos_info = 0;
- }
-
- pos = skb_put(skb, 9);
- *pos++ = WLAN_EID_VENDOR_SPECIFIC;
- *pos++ = 7; /* len */
- *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
- *pos++ = 0x50;
- *pos++ = 0xf2;
- *pos++ = 2; /* WME */
- *pos++ = 0; /* WME info */
- *pos++ = 1; /* WME ver */
- *pos++ = qos_info;
- }
-
- /* add any remaining custom (i.e. vendor specific here) IEs */
- if (wk->ie_len && wk->ie) {
- noffset = wk->ie_len;
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, wk->ie + offset, noffset - offset);
- }
-
- IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
- ieee80211_tx_skb(sdata, skb);
-}
-
-static void ieee80211_remove_auth_bss(struct ieee80211_local *local,
- struct ieee80211_work *wk)
-{
- struct cfg80211_bss *cbss;
- u16 capa_val = WLAN_CAPABILITY_ESS;
-
- if (wk->probe_auth.privacy)
- capa_val |= WLAN_CAPABILITY_PRIVACY;
-
- cbss = cfg80211_get_bss(local->hw.wiphy, wk->chan, wk->filter_ta,
- wk->probe_auth.ssid, wk->probe_auth.ssid_len,
- WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY,
- capa_val);
- if (!cbss)
- return;
-
- cfg80211_unlink_bss(local->hw.wiphy, cbss);
- cfg80211_put_bss(cbss);
-}
-
-static enum work_action __must_check
-ieee80211_direct_probe(struct ieee80211_work *wk)
-{
- struct ieee80211_sub_if_data *sdata = wk->sdata;
- struct ieee80211_local *local = sdata->local;
-
- wk->probe_auth.tries++;
- if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) {
- printk(KERN_DEBUG "%s: direct probe to %pM timed out\n",
- sdata->name, wk->filter_ta);
-
- /*
- * Most likely AP is not in the range so remove the
- * bss struct for that AP.
- */
- ieee80211_remove_auth_bss(local, wk);
-
- return WORK_ACT_TIMEOUT;
- }
-
- printk(KERN_DEBUG "%s: direct probe to %pM (try %d)\n",
- sdata->name, wk->filter_ta, wk->probe_auth.tries);
-
- /*
- * Direct probe is sent to broadcast address as some APs
- * will not answer to direct packet in unassociated state.
- */
- ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid,
- wk->probe_auth.ssid_len, NULL, 0);
-
- wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
- run_again(local, wk->timeout);
-
- return WORK_ACT_NONE;
-}
-
-
-static enum work_action __must_check
-ieee80211_authenticate(struct ieee80211_work *wk)
-{
- struct ieee80211_sub_if_data *sdata = wk->sdata;
- struct ieee80211_local *local = sdata->local;
-
- wk->probe_auth.tries++;
- if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) {
- printk(KERN_DEBUG "%s: authentication with %pM"
- " timed out\n", sdata->name, wk->filter_ta);
-
- /*
- * Most likely AP is not in the range so remove the
- * bss struct for that AP.
- */
- ieee80211_remove_auth_bss(local, wk);
-
- return WORK_ACT_TIMEOUT;
- }
-
- printk(KERN_DEBUG "%s: authenticate with %pM (try %d)\n",
- sdata->name, wk->filter_ta, wk->probe_auth.tries);
-
- ieee80211_send_auth(sdata, 1, wk->probe_auth.algorithm, wk->ie,
- wk->ie_len, wk->filter_ta, NULL, 0, 0);
- wk->probe_auth.transaction = 2;
-
- wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
- run_again(local, wk->timeout);
-
- return WORK_ACT_NONE;
-}
-
-static enum work_action __must_check
-ieee80211_associate(struct ieee80211_work *wk)
-{
- struct ieee80211_sub_if_data *sdata = wk->sdata;
- struct ieee80211_local *local = sdata->local;
-
- wk->assoc.tries++;
- if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) {
- printk(KERN_DEBUG "%s: association with %pM"
- " timed out\n",
- sdata->name, wk->filter_ta);
-
- /*
- * Most likely AP is not in the range so remove the
- * bss struct for that AP.
- */
- if (wk->assoc.bss)
- cfg80211_unlink_bss(local->hw.wiphy, wk->assoc.bss);
-
- return WORK_ACT_TIMEOUT;
- }
-
- printk(KERN_DEBUG "%s: associate with %pM (try %d)\n",
- sdata->name, wk->filter_ta, wk->assoc.tries);
- ieee80211_send_assoc(sdata, wk);
-
- wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
- run_again(local, wk->timeout);
-
- return WORK_ACT_NONE;
-}
-
-static enum work_action __must_check
-ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk)
-{
- /*
- * First time we run, do nothing -- the generic code will
- * have switched to the right channel etc.
- */
- if (!wk->started) {
- wk->timeout = jiffies + msecs_to_jiffies(wk->remain.duration);
-
- cfg80211_ready_on_channel(wk->sdata->dev, (unsigned long) wk,
- wk->chan, wk->chan_type,
- wk->remain.duration, GFP_KERNEL);
-
- return WORK_ACT_NONE;
- }
-
- return WORK_ACT_TIMEOUT;
-}
-
-static void ieee80211_auth_challenge(struct ieee80211_work *wk,
- struct ieee80211_mgmt *mgmt,
- size_t len)
-{
- struct ieee80211_sub_if_data *sdata = wk->sdata;
- u8 *pos;
- struct ieee802_11_elems elems;
-
- pos = mgmt->u.auth.variable;
- ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
- if (!elems.challenge)
- return;
- ieee80211_send_auth(sdata, 3, wk->probe_auth.algorithm,
- elems.challenge - 2, elems.challenge_len + 2,
- wk->filter_ta, wk->probe_auth.key,
- wk->probe_auth.key_len, wk->probe_auth.key_idx);
- wk->probe_auth.transaction = 4;
-}
-
-static enum work_action __must_check
-ieee80211_rx_mgmt_auth(struct ieee80211_work *wk,
- struct ieee80211_mgmt *mgmt, size_t len)
-{
- u16 auth_alg, auth_transaction, status_code;
-
- if (wk->type != IEEE80211_WORK_AUTH)
- return WORK_ACT_NONE;
-
- if (len < 24 + 6)
- return WORK_ACT_NONE;
-
- auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
- auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
- status_code = le16_to_cpu(mgmt->u.auth.status_code);
-
- if (auth_alg != wk->probe_auth.algorithm ||
- auth_transaction != wk->probe_auth.transaction)
- return WORK_ACT_NONE;
-
- if (status_code != WLAN_STATUS_SUCCESS) {
- printk(KERN_DEBUG "%s: %pM denied authentication (status %d)\n",
- wk->sdata->name, mgmt->sa, status_code);
- return WORK_ACT_DONE;
- }
-
- switch (wk->probe_auth.algorithm) {
- case WLAN_AUTH_OPEN:
- case WLAN_AUTH_LEAP:
- case WLAN_AUTH_FT:
- break;
- case WLAN_AUTH_SHARED_KEY:
- if (wk->probe_auth.transaction != 4) {
- ieee80211_auth_challenge(wk, mgmt, len);
- /* need another frame */
- return WORK_ACT_NONE;
- }
- break;
- default:
- WARN_ON(1);
- return WORK_ACT_NONE;
- }
-
- printk(KERN_DEBUG "%s: authenticated\n", wk->sdata->name);
- return WORK_ACT_DONE;
-}
-
-static enum work_action __must_check
-ieee80211_rx_mgmt_assoc_resp(struct ieee80211_work *wk,
- struct ieee80211_mgmt *mgmt, size_t len,
- bool reassoc)
-{
- struct ieee80211_sub_if_data *sdata = wk->sdata;
- struct ieee80211_local *local = sdata->local;
- u16 capab_info, status_code, aid;
- struct ieee802_11_elems elems;
- u8 *pos;
-
- /*
- * AssocResp and ReassocResp have identical structure, so process both
- * of them in this function.
- */
-
- if (len < 24 + 6)
- return WORK_ACT_NONE;
-
- capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
- status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
- aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
-
- printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x "
- "status=%d aid=%d)\n",
- sdata->name, reassoc ? "Rea" : "A", mgmt->sa,
- capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
-
- pos = mgmt->u.assoc_resp.variable;
- ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
-
- if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
- elems.timeout_int && elems.timeout_int_len == 5 &&
- elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) {
- u32 tu, ms;
- tu = get_unaligned_le32(elems.timeout_int + 1);
- ms = tu * 1024 / 1000;
- printk(KERN_DEBUG "%s: %pM rejected association temporarily; "
- "comeback duration %u TU (%u ms)\n",
- sdata->name, mgmt->sa, tu, ms);
- wk->timeout = jiffies + msecs_to_jiffies(ms);
- if (ms > IEEE80211_ASSOC_TIMEOUT)
- run_again(local, wk->timeout);
- return WORK_ACT_NONE;
- }
-
- if (status_code != WLAN_STATUS_SUCCESS)
- printk(KERN_DEBUG "%s: %pM denied association (code=%d)\n",
- sdata->name, mgmt->sa, status_code);
- else
- printk(KERN_DEBUG "%s: associated\n", sdata->name);
-
- return WORK_ACT_DONE;
-}
-
-static enum work_action __must_check
-ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk,
- struct ieee80211_mgmt *mgmt, size_t len,
- struct ieee80211_rx_status *rx_status)
-{
- struct ieee80211_sub_if_data *sdata = wk->sdata;
- struct ieee80211_local *local = sdata->local;
- size_t baselen;
-
- ASSERT_WORK_MTX(local);
-
- baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
- if (baselen > len)
- return WORK_ACT_NONE;
-
- printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name);
- return WORK_ACT_DONE;
-}
-
-static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
- struct sk_buff *skb)
-{
- struct ieee80211_rx_status *rx_status;
- struct ieee80211_mgmt *mgmt;
- struct ieee80211_work *wk;
- enum work_action rma = WORK_ACT_NONE;
- u16 fc;
-
- rx_status = (struct ieee80211_rx_status *) skb->cb;
- mgmt = (struct ieee80211_mgmt *) skb->data;
- fc = le16_to_cpu(mgmt->frame_control);
-
- mutex_lock(&local->work_mtx);
-
- list_for_each_entry(wk, &local->work_list, list) {
- const u8 *bssid = NULL;
-
- switch (wk->type) {
- case IEEE80211_WORK_DIRECT_PROBE:
- case IEEE80211_WORK_AUTH:
- case IEEE80211_WORK_ASSOC:
- bssid = wk->filter_ta;
- break;
- default:
- continue;
- }
-
- /*
- * Before queuing, we already verified mgmt->sa,
- * so this is needed just for matching.
- */
- if (compare_ether_addr(bssid, mgmt->bssid))
- continue;
-
- switch (fc & IEEE80211_FCTL_STYPE) {
- case IEEE80211_STYPE_PROBE_RESP:
- rma = ieee80211_rx_mgmt_probe_resp(wk, mgmt, skb->len,
- rx_status);
- break;
- case IEEE80211_STYPE_AUTH:
- rma = ieee80211_rx_mgmt_auth(wk, mgmt, skb->len);
- break;
- case IEEE80211_STYPE_ASSOC_RESP:
- rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt,
- skb->len, false);
- break;
- case IEEE80211_STYPE_REASSOC_RESP:
- rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt,
- skb->len, true);
- break;
- default:
- WARN_ON(1);
- }
- /*
- * We've processed this frame for that work, so it can't
- * belong to another work struct.
- * NB: this is also required for correctness for 'rma'!
- */
- break;
- }
-
- switch (rma) {
- case WORK_ACT_NONE:
- break;
- case WORK_ACT_DONE:
- list_del_rcu(&wk->list);
- break;
- default:
- WARN(1, "unexpected: %d", rma);
- }
-
- mutex_unlock(&local->work_mtx);
-
- if (rma != WORK_ACT_DONE)
- goto out;
-
- switch (wk->done(wk, skb)) {
- case WORK_DONE_DESTROY:
- free_work(wk);
- break;
- case WORK_DONE_REQUEUE:
- synchronize_rcu();
- wk->started = false; /* restart */
- mutex_lock(&local->work_mtx);
- list_add_tail(&wk->list, &local->work_list);
- mutex_unlock(&local->work_mtx);
- }
-
- out:
- kfree_skb(skb);
-}
-
-static void ieee80211_work_timer(unsigned long data)
-{
- struct ieee80211_local *local = (void *) data;
-
- if (local->quiescing)
- return;
-
- ieee80211_queue_work(&local->hw, &local->work_work);
-}
-
-static void ieee80211_work_work(struct work_struct *work)
-{
- struct ieee80211_local *local =
- container_of(work, struct ieee80211_local, work_work);
- struct sk_buff *skb;
- struct ieee80211_work *wk, *tmp;
- LIST_HEAD(free_work);
- enum work_action rma;
- bool remain_off_channel = false;
-
- if (local->scanning)
- return;
-
- /*
- * ieee80211_queue_work() should have picked up most cases,
- * here we'll pick the the rest.
- */
- if (WARN(local->suspended, "work scheduled while going to suspend\n"))
- return;
-
- /* first process frames to avoid timing out while a frame is pending */
- while ((skb = skb_dequeue(&local->work_skb_queue)))
- ieee80211_work_rx_queued_mgmt(local, skb);
-
- ieee80211_recalc_idle(local);
-
- mutex_lock(&local->work_mtx);
-
- list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
- bool started = wk->started;
-
- /* mark work as started if it's on the current off-channel */
- if (!started && local->tmp_channel &&
- wk->chan == local->tmp_channel &&
- wk->chan_type == local->tmp_channel_type) {
- started = true;
- wk->timeout = jiffies;
- }
-
- if (!started && !local->tmp_channel) {
- /*
- * TODO: could optimize this by leaving the
- * station vifs in awake mode if they
- * happen to be on the same channel as
- * the requested channel
- */
- ieee80211_offchannel_stop_beaconing(local);
- ieee80211_offchannel_stop_station(local);
-
- local->tmp_channel = wk->chan;
- local->tmp_channel_type = wk->chan_type;
- ieee80211_hw_config(local, 0);
- started = true;
- wk->timeout = jiffies;
- }
-
- /* don't try to work with items that aren't started */
- if (!started)
- continue;
-
- if (time_is_after_jiffies(wk->timeout)) {
- /*
- * This work item isn't supposed to be worked on
- * right now, but take care to adjust the timer
- * properly.
- */
- run_again(local, wk->timeout);
- continue;
- }
-
- switch (wk->type) {
- default:
- WARN_ON(1);
- /* nothing */
- rma = WORK_ACT_NONE;
- break;
- case IEEE80211_WORK_ABORT:
- rma = WORK_ACT_TIMEOUT;
- case IEEE80211_WORK_DIRECT_PROBE:
- rma = ieee80211_direct_probe(wk);
- break;
- case IEEE80211_WORK_AUTH:
- rma = ieee80211_authenticate(wk);
- break;
- case IEEE80211_WORK_ASSOC:
- rma = ieee80211_associate(wk);
- break;
- case IEEE80211_WORK_REMAIN_ON_CHANNEL:
- rma = ieee80211_remain_on_channel_timeout(wk);
- break;
- }
-
- wk->started = started;
-
- switch (rma) {
- case WORK_ACT_NONE:
- /* might have changed the timeout */
- run_again(local, wk->timeout);
- break;
- case WORK_ACT_TIMEOUT:
- list_del_rcu(&wk->list);
- synchronize_rcu();
- list_add(&wk->list, &free_work);
- break;
- default:
- WARN(1, "unexpected: %d", rma);
- }
- }
-
- list_for_each_entry(wk, &local->work_list, list) {
- if (!wk->started)
- continue;
- if (wk->chan != local->tmp_channel)
- continue;
- if (wk->chan_type != local->tmp_channel_type)
- continue;
- remain_off_channel = true;
- }
-
- if (!remain_off_channel && local->tmp_channel) {
- local->tmp_channel = NULL;
- ieee80211_hw_config(local, 0);
- ieee80211_offchannel_return(local, true);
- /* give connection some time to breathe */
- run_again(local, jiffies + HZ/2);
- }
-
- if (list_empty(&local->work_list) && local->scan_req)
- ieee80211_queue_delayed_work(&local->hw,
- &local->scan_work,
- round_jiffies_relative(0));
-
- mutex_unlock(&local->work_mtx);
-
- ieee80211_recalc_idle(local);
-
- list_for_each_entry_safe(wk, tmp, &free_work, list) {
- wk->done(wk, NULL);
- list_del(&wk->list);
- kfree(wk);
- }
-}
-
-void ieee80211_add_work(struct ieee80211_work *wk)
-{
- struct ieee80211_local *local;
-
- if (WARN_ON(!wk->chan))
- return;
-
- if (WARN_ON(!wk->sdata))
- return;
-
- if (WARN_ON(!wk->done))
- return;
-
- if (WARN_ON(!ieee80211_sdata_running(wk->sdata)))
- return;
-
- wk->started = false;
-
- local = wk->sdata->local;
- mutex_lock(&local->work_mtx);
- list_add_tail(&wk->list, &local->work_list);
- mutex_unlock(&local->work_mtx);
-
- ieee80211_queue_work(&local->hw, &local->work_work);
-}
-
-void ieee80211_work_init(struct ieee80211_local *local)
-{
- mutex_init(&local->work_mtx);
- INIT_LIST_HEAD(&local->work_list);
- setup_timer(&local->work_timer, ieee80211_work_timer,
- (unsigned long)local);
- INIT_WORK(&local->work_work, ieee80211_work_work);
- skb_queue_head_init(&local->work_skb_queue);
-}
-
-void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_work *wk;
-
- mutex_lock(&local->work_mtx);
- list_for_each_entry(wk, &local->work_list, list) {
- if (wk->sdata != sdata)
- continue;
- wk->type = IEEE80211_WORK_ABORT;
- wk->started = true;
- wk->timeout = jiffies;
- }
- mutex_unlock(&local->work_mtx);
-
- /* run cleanups etc. */
- ieee80211_work_work(&local->work_work);
-
- mutex_lock(&local->work_mtx);
- list_for_each_entry(wk, &local->work_list, list) {
- if (wk->sdata != sdata)
- continue;
- WARN_ON(1);
- break;
- }
- mutex_unlock(&local->work_mtx);
-}
-
-ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb)
-{
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_mgmt *mgmt;
- struct ieee80211_work *wk;
- u16 fc;
-
- if (skb->len < 24)
- return RX_DROP_MONITOR;
-
- mgmt = (struct ieee80211_mgmt *) skb->data;
- fc = le16_to_cpu(mgmt->frame_control);
-
- list_for_each_entry_rcu(wk, &local->work_list, list) {
- if (sdata != wk->sdata)
- continue;
- if (compare_ether_addr(wk->filter_ta, mgmt->sa))
- continue;
- if (compare_ether_addr(wk->filter_ta, mgmt->bssid))
- continue;
-
- switch (fc & IEEE80211_FCTL_STYPE) {
- case IEEE80211_STYPE_AUTH:
- case IEEE80211_STYPE_PROBE_RESP:
- case IEEE80211_STYPE_ASSOC_RESP:
- case IEEE80211_STYPE_REASSOC_RESP:
- skb_queue_tail(&local->work_skb_queue, skb);
- ieee80211_queue_work(&local->hw, &local->work_work);
- return RX_QUEUED;
- }
- }
-
- return RX_CONTINUE;
-}
-
-static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk,
- struct sk_buff *skb)
-{
- /*
- * We are done serving the remain-on-channel command.
- */
- cfg80211_remain_on_channel_expired(wk->sdata->dev, (unsigned long) wk,
- wk->chan, wk->chan_type,
- GFP_KERNEL);
-
- return WORK_DONE_DESTROY;
-}
-
-int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- unsigned int duration, u64 *cookie)
-{
- struct ieee80211_work *wk;
-
- wk = kzalloc(sizeof(*wk), GFP_KERNEL);
- if (!wk)
- return -ENOMEM;
-
- wk->type = IEEE80211_WORK_REMAIN_ON_CHANNEL;
- wk->chan = chan;
- wk->chan_type = channel_type;
- wk->sdata = sdata;
- wk->done = ieee80211_remain_done;
-
- wk->remain.duration = duration;
-
- *cookie = (unsigned long) wk;
-
- ieee80211_add_work(wk);
-
- return 0;
-}
-
-int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata,
- u64 cookie)
-{
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_work *wk, *tmp;
- bool found = false;
-
- mutex_lock(&local->work_mtx);
- list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
- if ((unsigned long) wk == cookie) {
- wk->timeout = jiffies;
- found = true;
- break;
- }
- }
- mutex_unlock(&local->work_mtx);
-
- if (!found)
- return -ENOENT;
-
- ieee80211_queue_work(&local->hw, &local->work_work);
-
- return 0;
-}
diff --git a/trunk/net/mac80211/wpa.c b/trunk/net/mac80211/wpa.c
index f4971cd45c64..5332014cb229 100644
--- a/trunk/net/mac80211/wpa.c
+++ b/trunk/net/mac80211/wpa.c
@@ -31,8 +31,8 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
unsigned int hdrlen;
struct ieee80211_hdr *hdr;
struct sk_buff *skb = tx->skb;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int authenticator;
+ int wpa_test = 0;
int tail;
hdr = (struct ieee80211_hdr *)skb->data;
@@ -47,15 +47,16 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
data = skb->data + hdrlen;
data_len = skb->len - hdrlen;
- if (info->control.hw_key &&
+ if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
!(tx->flags & IEEE80211_TX_FRAGMENTED) &&
- !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
- /* hwaccel - with no need for SW-generated MMIC */
+ !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) &&
+ !wpa_test) {
+ /* hwaccel - with no need for preallocated room for MMIC */
return TX_CONTINUE;
}
tail = MICHAEL_MIC_LEN;
- if (!info->control.hw_key)
+ if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
tail += TKIP_ICV_LEN;
if (WARN_ON(skb_tailroom(skb) < tail ||
@@ -146,16 +147,17 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
int len, tail;
u8 *pos;
- if (info->control.hw_key &&
- !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
- /* hwaccel - with no need for software-generated IV */
+ if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
+ !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
+ /* hwaccel - with no need for preallocated room for IV/ICV */
+ info->control.hw_key = &tx->key->conf;
return 0;
}
hdrlen = ieee80211_hdrlen(hdr->frame_control);
len = skb->len - hdrlen;
- if (info->control.hw_key)
+ if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
tail = 0;
else
tail = TKIP_ICV_LEN;
@@ -173,11 +175,13 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
if (key->u.tkip.tx.iv16 == 0)
key->u.tkip.tx.iv32++;
- pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16);
+ if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
+ /* hwaccel - with preallocated room for IV */
+ ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16);
- /* hwaccel - with software IV */
- if (info->control.hw_key)
+ info->control.hw_key = &tx->key->conf;
return 0;
+ }
/* Add room for ICV */
skb_put(skb, TKIP_ICV_LEN);
@@ -359,20 +363,24 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
int hdrlen, len, tail;
u8 *pos, *pn;
int i;
+ bool skip_hw;
+
+ skip_hw = (tx->key->conf.flags & IEEE80211_KEY_FLAG_SW_MGMT) &&
+ ieee80211_is_mgmt(hdr->frame_control);
- if (info->control.hw_key &&
- !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
- /*
- * hwaccel has no need for preallocated room for CCMP
- * header or MIC fields
- */
+ if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
+ !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
+ !skip_hw) {
+ /* hwaccel - with no need for preallocated room for CCMP
+ * header or MIC fields */
+ info->control.hw_key = &tx->key->conf;
return 0;
}
hdrlen = ieee80211_hdrlen(hdr->frame_control);
len = skb->len - hdrlen;
- if (info->control.hw_key)
+ if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
tail = 0;
else
tail = CCMP_MIC_LEN;
@@ -397,9 +405,11 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
ccmp_pn2hdr(pos, pn, key->conf.keyidx);
- /* hwaccel - with software CCMP header */
- if (info->control.hw_key)
+ if ((key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && !skip_hw) {
+ /* hwaccel - with preallocated room for CCMP header */
+ info->control.hw_key = &tx->key->conf;
return 0;
+ }
pos += CCMP_HDR_LEN;
ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0);
@@ -515,8 +525,11 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
u8 *pn, aad[20];
int i;
- if (info->control.hw_key)
+ if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
+ /* hwaccel */
+ info->control.hw_key = &tx->key->conf;
return 0;
+ }
if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
return TX_DROP;
diff --git a/trunk/net/wireless/.gitignore b/trunk/net/wireless/.gitignore
deleted file mode 100644
index c33451b896d9..000000000000
--- a/trunk/net/wireless/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-regdb.c
diff --git a/trunk/net/wireless/Kconfig b/trunk/net/wireless/Kconfig
index d0ee29063e5d..90e93a5701aa 100644
--- a/trunk/net/wireless/Kconfig
+++ b/trunk/net/wireless/Kconfig
@@ -94,21 +94,20 @@ config CFG80211_DEBUGFS
If unsure, say N.
-config CFG80211_INTERNAL_REGDB
- bool "use statically compiled regulatory rules database" if EMBEDDED
+config WIRELESS_OLD_REGULATORY
+ bool "Old wireless static regulatory definitions"
default n
depends on CFG80211
---help---
- This option generates an internal data structure representing
- the wireless regulatory rules described in net/wireless/db.txt
- and includes code to query that database. This is an alternative
- to using CRDA for defining regulatory rules for the kernel.
+ This option enables the old static regulatory information
+ and uses it within the new framework. This option is available
+ for historical reasons and it is advised to leave it off.
For details see:
http://wireless.kernel.org/en/developers/Regulatory
- Most distributions have a CRDA package. So if unsure, say N.
+ Say N and if you say Y, please tell us why. The default is N.
config CFG80211_WEXT
bool "cfg80211 wireless extensions compatibility"
diff --git a/trunk/net/wireless/Makefile b/trunk/net/wireless/Makefile
index e77e508126fa..f07c8dc7aab2 100644
--- a/trunk/net/wireless/Makefile
+++ b/trunk/net/wireless/Makefile
@@ -13,11 +13,5 @@ cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o
cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
-cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o
ccflags-y += -D__CHECK_ENDIAN__
-
-$(obj)/regdb.c: $(src)/db.txt $(src)/genregdb.awk
- @$(AWK) -f $(srctree)/$(src)/genregdb.awk < $< > $@
-
-clean-files := regdb.c
diff --git a/trunk/net/wireless/chan.c b/trunk/net/wireless/chan.c
index bf1737fc9a7e..a46ac6c9b365 100644
--- a/trunk/net/wireless/chan.c
+++ b/trunk/net/wireless/chan.c
@@ -41,57 +41,44 @@ rdev_fixed_channel(struct cfg80211_registered_device *rdev,
return result;
}
-struct ieee80211_channel *
-rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
+int rdev_set_freq(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *for_wdev,
int freq, enum nl80211_channel_type channel_type)
{
struct ieee80211_channel *chan;
struct ieee80211_sta_ht_cap *ht_cap;
+ int result;
+
+ if (rdev_fixed_channel(rdev, for_wdev))
+ return -EBUSY;
+
+ if (!rdev->ops->set_channel)
+ return -EOPNOTSUPP;
chan = ieee80211_get_channel(&rdev->wiphy, freq);
/* Primary channel not allowed */
if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
- return NULL;
+ return -EINVAL;
if (channel_type == NL80211_CHAN_HT40MINUS &&
chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
- return NULL;
+ return -EINVAL;
else if (channel_type == NL80211_CHAN_HT40PLUS &&
chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
- return NULL;
+ return -EINVAL;
ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
if (channel_type != NL80211_CHAN_NO_HT) {
if (!ht_cap->ht_supported)
- return NULL;
+ return -EINVAL;
if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
- return NULL;
+ return -EINVAL;
}
- return chan;
-}
-
-int rdev_set_freq(struct cfg80211_registered_device *rdev,
- struct wireless_dev *for_wdev,
- int freq, enum nl80211_channel_type channel_type)
-{
- struct ieee80211_channel *chan;
- int result;
-
- if (rdev_fixed_channel(rdev, for_wdev))
- return -EBUSY;
-
- if (!rdev->ops->set_channel)
- return -EOPNOTSUPP;
-
- chan = rdev_freq_to_chan(rdev, freq, channel_type);
- if (!chan)
- return -EINVAL;
-
result = rdev->ops->set_channel(&rdev->wiphy, chan, channel_type);
if (result)
return result;
diff --git a/trunk/net/wireless/core.c b/trunk/net/wireless/core.c
index 7fdb9409ad2a..92b812442488 100644
--- a/trunk/net/wireless/core.c
+++ b/trunk/net/wireless/core.c
@@ -1,7 +1,7 @@
/*
* This is the linux wireless configuration interface.
*
- * Copyright 2006-2010 Johannes Berg
+ * Copyright 2006-2009 Johannes Berg
*/
#include
@@ -31,10 +31,15 @@ MODULE_AUTHOR("Johannes Berg");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("wireless configuration support");
-/* RCU-protected (and cfg80211_mutex for writers) */
+/* RCU might be appropriate here since we usually
+ * only read the list, and that can happen quite
+ * often because we need to do it for each command */
LIST_HEAD(cfg80211_rdev_list);
int cfg80211_rdev_list_generation;
+/*
+ * This is used to protect the cfg80211_rdev_list
+ */
DEFINE_MUTEX(cfg80211_mutex);
/* for debugfs */
@@ -397,7 +402,6 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
rdev->wiphy.retry_long = 4;
rdev->wiphy.frag_threshold = (u32) -1;
rdev->wiphy.rts_threshold = (u32) -1;
- rdev->wiphy.coverage_class = 0;
return &rdev->wiphy;
}
@@ -413,18 +417,6 @@ int wiphy_register(struct wiphy *wiphy)
int i;
u16 ifmodes = wiphy->interface_modes;
- if (WARN_ON(wiphy->addresses && !wiphy->n_addresses))
- return -EINVAL;
-
- if (WARN_ON(wiphy->addresses &&
- !is_zero_ether_addr(wiphy->perm_addr) &&
- memcmp(wiphy->perm_addr, wiphy->addresses[0].addr,
- ETH_ALEN)))
- return -EINVAL;
-
- if (wiphy->addresses)
- memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN);
-
/* sanity check ifmodes */
WARN_ON(!ifmodes);
ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1;
@@ -484,7 +476,7 @@ int wiphy_register(struct wiphy *wiphy)
/* set up regulatory info */
wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
- list_add_rcu(&rdev->list, &cfg80211_rdev_list);
+ list_add(&rdev->list, &cfg80211_rdev_list);
cfg80211_rdev_list_generation++;
mutex_unlock(&cfg80211_mutex);
@@ -561,8 +553,7 @@ void wiphy_unregister(struct wiphy *wiphy)
* it impossible to find from userspace.
*/
debugfs_remove_recursive(rdev->wiphy.debugfsdir);
- list_del_rcu(&rdev->list);
- synchronize_rcu();
+ list_del(&rdev->list);
/*
* Try to grab rdev->mtx. If a command is still in progress,
@@ -677,11 +668,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work);
INIT_LIST_HEAD(&wdev->event_list);
spin_lock_init(&wdev->event_lock);
- INIT_LIST_HEAD(&wdev->action_registrations);
- spin_lock_init(&wdev->action_registrations_lock);
-
mutex_lock(&rdev->devlist_mtx);
- list_add_rcu(&wdev->list, &rdev->netdev_list);
+ list_add(&wdev->list, &rdev->netdev_list);
rdev->devlist_generation++;
/* can only change netns with wiphy */
dev->features |= NETIF_F_NETNS_LOCAL;
@@ -698,21 +686,19 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
wdev->wext.default_key = -1;
wdev->wext.default_mgmt_key = -1;
wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
-#endif
-
if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT)
- wdev->ps = true;
+ wdev->wext.ps = true;
else
- wdev->ps = false;
- wdev->ps_timeout = 100;
+ wdev->wext.ps = false;
+ wdev->wext.ps_timeout = 100;
if (rdev->ops->set_power_mgmt)
if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
- wdev->ps,
- wdev->ps_timeout)) {
+ wdev->wext.ps,
+ wdev->wext.ps_timeout)) {
/* assume this means it's off */
- wdev->ps = false;
+ wdev->wext.ps = false;
}
-
+#endif
if (!dev->ethtool_ops)
dev->ethtool_ops = &cfg80211_ethtool_ops;
@@ -795,22 +781,13 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
*/
if (!list_empty(&wdev->list)) {
sysfs_remove_link(&dev->dev.kobj, "phy80211");
- list_del_rcu(&wdev->list);
+ list_del_init(&wdev->list);
rdev->devlist_generation++;
- cfg80211_mlme_purge_actions(wdev);
#ifdef CONFIG_CFG80211_WEXT
kfree(wdev->wext.keys);
#endif
}
mutex_unlock(&rdev->devlist_mtx);
- /*
- * synchronise (so that we won't find this netdev
- * from other code any more) and then clear the list
- * head so that the above code can safely check for
- * !list_empty() to avoid double-cleanup.
- */
- synchronize_rcu();
- INIT_LIST_HEAD(&wdev->list);
break;
case NETDEV_PRE_UP:
if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
diff --git a/trunk/net/wireless/core.h b/trunk/net/wireless/core.h
index d52da913145a..4ef3efc94106 100644
--- a/trunk/net/wireless/core.h
+++ b/trunk/net/wireless/core.h
@@ -1,7 +1,7 @@
/*
* Wireless configuration interface internals.
*
- * Copyright 2006-2010 Johannes Berg
+ * Copyright 2006-2009 Johannes Berg
*/
#ifndef __NET_WIRELESS_CORE_H
#define __NET_WIRELESS_CORE_H
@@ -48,7 +48,6 @@ struct cfg80211_registered_device {
/* associate netdev list */
struct mutex devlist_mtx;
- /* protected by devlist_mtx or RCU */
struct list_head netdev_list;
int devlist_generation;
int opencount; /* also protected by devlist_mtx */
@@ -112,8 +111,7 @@ struct cfg80211_internal_bss {
unsigned long ts;
struct kref ref;
atomic_t hold;
- bool beacon_ies_allocated;
- bool proberesp_ies_allocated;
+ bool ies_allocated;
/* must be last because of priv member */
struct cfg80211_bss pub;
@@ -329,15 +327,6 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
const u8 *resp_ie, size_t resp_ie_len,
u16 status, bool wextev,
struct cfg80211_bss *bss);
-int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid,
- const u8 *match_data, int match_len);
-void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid);
-void cfg80211_mlme_purge_actions(struct wireless_dev *wdev);
-int cfg80211_mlme_action(struct cfg80211_registered_device *rdev,
- struct net_device *dev,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- const u8 *buf, size_t len, u64 *cookie);
/* SME */
int __cfg80211_connect(struct cfg80211_registered_device *rdev,
@@ -385,15 +374,10 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);
struct ieee80211_channel *
rdev_fixed_channel(struct cfg80211_registered_device *rdev,
struct wireless_dev *for_wdev);
-struct ieee80211_channel *
-rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
- int freq, enum nl80211_channel_type channel_type);
int rdev_set_freq(struct cfg80211_registered_device *rdev,
struct wireless_dev *for_wdev,
int freq, enum nl80211_channel_type channel_type);
-u16 cfg80211_calculate_bitrate(struct rate_info *rate);
-
#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
#define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond)
#else
diff --git a/trunk/net/wireless/db.txt b/trunk/net/wireless/db.txt
deleted file mode 100644
index a2fc3a09ccdc..000000000000
--- a/trunk/net/wireless/db.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# This file is a placeholder to prevent accidental build breakage if someone
-# enables CONFIG_CFG80211_INTERNAL_REGDB. Almost no one actually needs to
-# enable that build option.
-#
-# You should be using CRDA instead. It is even better if you use the CRDA
-# package provided by your distribution, since they will probably keep it
-# up-to-date on your behalf.
-#
-# If you _really_ intend to use CONFIG_CFG80211_INTERNAL_REGDB then you will
-# need to replace this file with one containing appropriately formatted
-# regulatory rules that cover the regulatory domains you will be using. Your
-# best option is to extract the db.txt file from the wireless-regdb git
-# repository:
-#
-# git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-regdb.git
-#
diff --git a/trunk/net/wireless/genregdb.awk b/trunk/net/wireless/genregdb.awk
deleted file mode 100644
index 8316cf075ce9..000000000000
--- a/trunk/net/wireless/genregdb.awk
+++ /dev/null
@@ -1,118 +0,0 @@
-#!/usr/bin/awk -f
-#
-# genregdb.awk -- generate regdb.c from db.txt
-#
-# Actually, it reads from stdin (presumed to be db.txt) and writes
-# to stdout (presumed to be regdb.c), but close enough...
-#
-# Copyright 2009 John W. Linville
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-
-BEGIN {
- active = 0
- rules = 0;
- print "/*"
- print " * DO NOT EDIT -- file generated from data in db.txt"
- print " */"
- print ""
- print "#include "
- print "#include "
- print ""
- regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n"
-}
-
-/^[ \t]*#/ {
- /* Ignore */
-}
-
-!active && /^[ \t]*$/ {
- /* Ignore */
-}
-
-!active && /country/ {
- country=$2
- sub(/:/, "", country)
- printf "static const struct ieee80211_regdomain regdom_%s = {\n", country
- printf "\t.alpha2 = \"%s\",\n", country
- printf "\t.reg_rules = {\n"
- active = 1
- regdb = regdb "\t®dom_" country ",\n"
-}
-
-active && /^[ \t]*\(/ {
- start = $1
- sub(/\(/, "", start)
- end = $3
- bw = $5
- sub(/\),/, "", bw)
- gain = $6
- sub(/\(/, "", gain)
- sub(/,/, "", gain)
- power = $7
- sub(/\)/, "", power)
- sub(/,/, "", power)
- # power might be in mW...
- units = $8
- sub(/\)/, "", units)
- sub(/,/, "", units)
- if (units == "mW") {
- if (power == 100) {
- power = 20
- } else if (power == 200) {
- power = 23
- } else if (power == 500) {
- power = 27
- } else if (power == 1000) {
- power = 30
- } else {
- print "Unknown power value in database!"
- }
- }
- flagstr = ""
- for (i=8; i<=NF; i++)
- flagstr = flagstr $i
- split(flagstr, flagarray, ",")
- flags = ""
- for (arg in flagarray) {
- if (flagarray[arg] == "NO-OFDM") {
- flags = flags "\n\t\t\tNL80211_RRF_NO_OFDM | "
- } else if (flagarray[arg] == "NO-CCK") {
- flags = flags "\n\t\t\tNL80211_RRF_NO_CCK | "
- } else if (flagarray[arg] == "NO-INDOOR") {
- flags = flags "\n\t\t\tNL80211_RRF_NO_INDOOR | "
- } else if (flagarray[arg] == "NO-OUTDOOR") {
- flags = flags "\n\t\t\tNL80211_RRF_NO_OUTDOOR | "
- } else if (flagarray[arg] == "DFS") {
- flags = flags "\n\t\t\tNL80211_RRF_DFS | "
- } else if (flagarray[arg] == "PTP-ONLY") {
- flags = flags "\n\t\t\tNL80211_RRF_PTP_ONLY | "
- } else if (flagarray[arg] == "PTMP-ONLY") {
- flags = flags "\n\t\t\tNL80211_RRF_PTMP_ONLY | "
- } else if (flagarray[arg] == "PASSIVE-SCAN") {
- flags = flags "\n\t\t\tNL80211_RRF_PASSIVE_SCAN | "
- } else if (flagarray[arg] == "NO-IBSS") {
- flags = flags "\n\t\t\tNL80211_RRF_NO_IBSS | "
- }
- }
- flags = flags "0"
- printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags
- rules++
-}
-
-active && /^[ \t]*$/ {
- active = 0
- printf "\t},\n"
- printf "\t.n_reg_rules = %d\n", rules
- printf "};\n\n"
- rules = 0;
-}
-
-END {
- print regdb "};"
- print ""
- print "int reg_regdb_size = ARRAY_SIZE(reg_regdb);"
-}
diff --git a/trunk/net/wireless/lib80211_crypt_ccmp.c b/trunk/net/wireless/lib80211_crypt_ccmp.c
index b7fa31d5fd13..2301dc1edc4c 100644
--- a/trunk/net/wireless/lib80211_crypt_ccmp.c
+++ b/trunk/net/wireless/lib80211_crypt_ccmp.c
@@ -237,6 +237,7 @@ static int lib80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
return -1;
pos = skb->data + hdr_len + CCMP_HDR_LEN;
+ mic = skb_put(skb, CCMP_MIC_LEN);
hdr = (struct ieee80211_hdr *)skb->data;
ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
@@ -256,7 +257,6 @@ static int lib80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
pos += len;
}
- mic = skb_put(skb, CCMP_MIC_LEN);
for (i = 0; i < CCMP_MIC_LEN; i++)
mic[i] = b[i] ^ s0[i];
diff --git a/trunk/net/wireless/lib80211_crypt_tkip.c b/trunk/net/wireless/lib80211_crypt_tkip.c
index 8cbdb32ff316..c36287399d7e 100644
--- a/trunk/net/wireless/lib80211_crypt_tkip.c
+++ b/trunk/net/wireless/lib80211_crypt_tkip.c
@@ -36,8 +36,6 @@ MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("lib80211 crypt: TKIP");
MODULE_LICENSE("GPL");
-#define TKIP_HDR_LEN 8
-
struct lib80211_tkip_data {
#define TKIP_KEY_LEN 32
u8 key[TKIP_KEY_LEN];
@@ -316,12 +314,13 @@ static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
u8 * rc4key, int keylen, void *priv)
{
struct lib80211_tkip_data *tkey = priv;
+ int len;
u8 *pos;
struct ieee80211_hdr *hdr;
hdr = (struct ieee80211_hdr *)skb->data;
- if (skb_headroom(skb) < TKIP_HDR_LEN || skb->len < hdr_len)
+ if (skb_headroom(skb) < 8 || skb->len < hdr_len)
return -1;
if (rc4key == NULL || keylen < 16)
@@ -334,8 +333,9 @@ static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
}
tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
- pos = skb_push(skb, TKIP_HDR_LEN);
- memmove(pos, pos + TKIP_HDR_LEN, hdr_len);
+ len = skb->len - hdr_len;
+ pos = skb_push(skb, 8);
+ memmove(pos, pos + 8, hdr_len);
pos += hdr_len;
*pos++ = *rc4key;
@@ -353,7 +353,7 @@ static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
tkey->tx_iv32++;
}
- return TKIP_HDR_LEN;
+ return 8;
}
static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
@@ -384,8 +384,9 @@ static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
if ((lib80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0)
return -1;
- crc = ~crc32_le(~0, pos, len);
icv = skb_put(skb, 4);
+
+ crc = ~crc32_le(~0, pos, len);
icv[0] = crc;
icv[1] = crc >> 8;
icv[2] = crc >> 16;
@@ -433,7 +434,7 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
return -1;
}
- if (skb->len < hdr_len + TKIP_HDR_LEN + 4)
+ if (skb->len < hdr_len + 8 + 4)
return -1;
pos = skb->data + hdr_len;
@@ -461,7 +462,7 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
}
iv16 = (pos[0] << 8) | pos[2];
iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
- pos += TKIP_HDR_LEN;
+ pos += 8;
if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) {
#ifdef CONFIG_LIB80211_DEBUG
@@ -522,8 +523,8 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
tkey->rx_iv16_new = iv16;
/* Remove IV and ICV */
- memmove(skb->data + TKIP_HDR_LEN, skb->data, hdr_len);
- skb_pull(skb, TKIP_HDR_LEN);
+ memmove(skb->data + 8, skb->data, hdr_len);
+ skb_pull(skb, 8);
skb_trim(skb, skb->len - 4);
return keyidx;
diff --git a/trunk/net/wireless/mlme.c b/trunk/net/wireless/mlme.c
index 62bc8855e123..82e6002c8d67 100644
--- a/trunk/net/wireless/mlme.c
+++ b/trunk/net/wireless/mlme.c
@@ -148,23 +148,22 @@ void __cfg80211_send_deauth(struct net_device *dev,
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
const u8 *bssid = mgmt->bssid;
int i;
- bool found = false;
ASSERT_WDEV_LOCK(wdev);
+ nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL);
+
if (wdev->current_bss &&
memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
cfg80211_unhold_bss(wdev->current_bss);
cfg80211_put_bss(&wdev->current_bss->pub);
wdev->current_bss = NULL;
- found = true;
} else for (i = 0; i < MAX_AUTH_BSSES; i++) {
if (wdev->auth_bsses[i] &&
memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
cfg80211_unhold_bss(wdev->auth_bsses[i]);
cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
wdev->auth_bsses[i] = NULL;
- found = true;
break;
}
if (wdev->authtry_bsses[i] &&
@@ -172,16 +171,10 @@ void __cfg80211_send_deauth(struct net_device *dev,
cfg80211_unhold_bss(wdev->authtry_bsses[i]);
cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
wdev->authtry_bsses[i] = NULL;
- found = true;
break;
}
}
- if (!found)
- return;
-
- nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL);
-
if (wdev->sme_state == CFG80211_SME_CONNECTED) {
u16 reason_code;
bool from_ap;
@@ -691,206 +684,3 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
}
}
}
-
-void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- unsigned int duration, gfp_t gfp)
-{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
- struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
- nl80211_send_remain_on_channel(rdev, dev, cookie, chan, channel_type,
- duration, gfp);
-}
-EXPORT_SYMBOL(cfg80211_ready_on_channel);
-
-void cfg80211_remain_on_channel_expired(struct net_device *dev,
- u64 cookie,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- gfp_t gfp)
-{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
- struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
- nl80211_send_remain_on_channel_cancel(rdev, dev, cookie, chan,
- channel_type, gfp);
-}
-EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
-
-void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
- struct station_info *sinfo, gfp_t gfp)
-{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
- struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
- nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp);
-}
-EXPORT_SYMBOL(cfg80211_new_sta);
-
-struct cfg80211_action_registration {
- struct list_head list;
-
- u32 nlpid;
-
- int match_len;
-
- u8 match[];
-};
-
-int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid,
- const u8 *match_data, int match_len)
-{
- struct cfg80211_action_registration *reg, *nreg;
- int err = 0;
-
- nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL);
- if (!nreg)
- return -ENOMEM;
-
- spin_lock_bh(&wdev->action_registrations_lock);
-
- list_for_each_entry(reg, &wdev->action_registrations, list) {
- int mlen = min(match_len, reg->match_len);
-
- if (memcmp(reg->match, match_data, mlen) == 0) {
- err = -EALREADY;
- break;
- }
- }
-
- if (err) {
- kfree(nreg);
- goto out;
- }
-
- memcpy(nreg->match, match_data, match_len);
- nreg->match_len = match_len;
- nreg->nlpid = snd_pid;
- list_add(&nreg->list, &wdev->action_registrations);
-
- out:
- spin_unlock_bh(&wdev->action_registrations_lock);
- return err;
-}
-
-void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid)
-{
- struct cfg80211_action_registration *reg, *tmp;
-
- spin_lock_bh(&wdev->action_registrations_lock);
-
- list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) {
- if (reg->nlpid == nlpid) {
- list_del(®->list);
- kfree(reg);
- }
- }
-
- spin_unlock_bh(&wdev->action_registrations_lock);
-}
-
-void cfg80211_mlme_purge_actions(struct wireless_dev *wdev)
-{
- struct cfg80211_action_registration *reg, *tmp;
-
- spin_lock_bh(&wdev->action_registrations_lock);
-
- list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) {
- list_del(®->list);
- kfree(reg);
- }
-
- spin_unlock_bh(&wdev->action_registrations_lock);
-}
-
-int cfg80211_mlme_action(struct cfg80211_registered_device *rdev,
- struct net_device *dev,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- const u8 *buf, size_t len, u64 *cookie)
-{
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- const struct ieee80211_mgmt *mgmt;
-
- if (rdev->ops->action == NULL)
- return -EOPNOTSUPP;
- if (len < 24 + 1)
- return -EINVAL;
-
- mgmt = (const struct ieee80211_mgmt *) buf;
- if (!ieee80211_is_action(mgmt->frame_control))
- return -EINVAL;
- if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
- /* Verify that we are associated with the destination AP */
- if (!wdev->current_bss ||
- memcmp(wdev->current_bss->pub.bssid, mgmt->bssid,
- ETH_ALEN) != 0 ||
- memcmp(wdev->current_bss->pub.bssid, mgmt->da,
- ETH_ALEN) != 0)
- return -ENOTCONN;
- }
-
- if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0)
- return -EINVAL;
-
- /* Transmit the Action frame as requested by user space */
- return rdev->ops->action(&rdev->wiphy, dev, chan, channel_type,
- buf, len, cookie);
-}
-
-bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf,
- size_t len, gfp_t gfp)
-{
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct wiphy *wiphy = wdev->wiphy;
- struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- struct cfg80211_action_registration *reg;
- const u8 *action_data;
- int action_data_len;
- bool result = false;
-
- /* frame length - min size excluding category */
- action_data_len = len - (IEEE80211_MIN_ACTION_SIZE - 1);
-
- /* action data starts with category */
- action_data = buf + IEEE80211_MIN_ACTION_SIZE - 1;
-
- spin_lock_bh(&wdev->action_registrations_lock);
-
- list_for_each_entry(reg, &wdev->action_registrations, list) {
- if (reg->match_len > action_data_len)
- continue;
-
- if (memcmp(reg->match, action_data, reg->match_len))
- continue;
-
- /* found match! */
-
- /* Indicate the received Action frame to user space */
- if (nl80211_send_action(rdev, dev, reg->nlpid, freq,
- buf, len, gfp))
- continue;
-
- result = true;
- break;
- }
-
- spin_unlock_bh(&wdev->action_registrations_lock);
-
- return result;
-}
-EXPORT_SYMBOL(cfg80211_rx_action);
-
-void cfg80211_action_tx_status(struct net_device *dev, u64 cookie,
- const u8 *buf, size_t len, bool ack, gfp_t gfp)
-{
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct wiphy *wiphy = wdev->wiphy;
- struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
- /* Indicate TX status of the Action frame to user space */
- nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp);
-}
-EXPORT_SYMBOL(cfg80211_action_tx_status);
diff --git a/trunk/net/wireless/nl80211.c b/trunk/net/wireless/nl80211.c
index b0495a1da22e..a6028433e3a0 100644
--- a/trunk/net/wireless/nl80211.c
+++ b/trunk/net/wireless/nl80211.c
@@ -1,7 +1,7 @@
/*
* This is the new netlink-based wireless configuration interface.
*
- * Copyright 2006-2010 Johannes Berg
+ * Copyright 2006-2009 Johannes Berg
*/
#include
@@ -69,7 +69,6 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
[NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 },
[NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
[NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
- [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 },
[NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
[NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
@@ -142,13 +141,6 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
[NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
[NL80211_ATTR_PMKID] = { .type = NLA_BINARY,
.len = WLAN_PMKID_LEN },
- [NL80211_ATTR_DURATION] = { .type = NLA_U32 },
- [NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
- [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED },
- [NL80211_ATTR_FRAME] = { .type = NLA_BINARY,
- .len = IEEE80211_MAX_DATA_LEN },
- [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, },
- [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 },
};
/* policy for the attributes */
@@ -450,8 +442,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
dev->wiphy.frag_threshold);
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
dev->wiphy.rts_threshold);
- NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
- dev->wiphy.coverage_class);
NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
dev->wiphy.max_scan_ssids);
@@ -579,9 +569,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
CMD(set_pmksa, SET_PMKSA);
CMD(del_pmksa, DEL_PMKSA);
CMD(flush_pmksa, FLUSH_PMKSA);
- CMD(remain_on_channel, REMAIN_ON_CHANNEL);
- CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
- CMD(action, ACTION);
if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
i++;
NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS);
@@ -694,7 +681,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
u32 changed;
u8 retry_short = 0, retry_long = 0;
u32 frag_threshold = 0, rts_threshold = 0;
- u8 coverage_class = 0;
rtnl_lock();
@@ -817,16 +803,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
changed |= WIPHY_PARAM_RTS_THRESHOLD;
}
- if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) {
- coverage_class = nla_get_u8(
- info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]);
- changed |= WIPHY_PARAM_COVERAGE_CLASS;
- }
-
if (changed) {
u8 old_retry_short, old_retry_long;
u32 old_frag_threshold, old_rts_threshold;
- u8 old_coverage_class;
if (!rdev->ops->set_wiphy_params) {
result = -EOPNOTSUPP;
@@ -837,7 +816,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
old_retry_long = rdev->wiphy.retry_long;
old_frag_threshold = rdev->wiphy.frag_threshold;
old_rts_threshold = rdev->wiphy.rts_threshold;
- old_coverage_class = rdev->wiphy.coverage_class;
if (changed & WIPHY_PARAM_RETRY_SHORT)
rdev->wiphy.retry_short = retry_short;
@@ -847,8 +825,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
rdev->wiphy.frag_threshold = frag_threshold;
if (changed & WIPHY_PARAM_RTS_THRESHOLD)
rdev->wiphy.rts_threshold = rts_threshold;
- if (changed & WIPHY_PARAM_COVERAGE_CLASS)
- rdev->wiphy.coverage_class = coverage_class;
result = rdev->ops->set_wiphy_params(&rdev->wiphy, changed);
if (result) {
@@ -856,7 +832,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
rdev->wiphy.retry_long = old_retry_long;
rdev->wiphy.frag_threshold = old_frag_threshold;
rdev->wiphy.rts_threshold = old_rts_threshold;
- rdev->wiphy.coverage_class = old_coverage_class;
}
}
@@ -1662,9 +1637,42 @@ static int parse_station_flags(struct genl_info *info,
return 0;
}
+static u16 nl80211_calculate_bitrate(struct rate_info *rate)
+{
+ int modulation, streams, bitrate;
+
+ if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+ return rate->legacy;
+
+ /* the formula below does only work for MCS values smaller than 32 */
+ if (rate->mcs >= 32)
+ return 0;
+
+ modulation = rate->mcs & 7;
+ streams = (rate->mcs >> 3) + 1;
+
+ bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+ 13500000 : 6500000;
+
+ if (modulation < 4)
+ bitrate *= (modulation + 1);
+ else if (modulation == 4)
+ bitrate *= (modulation + 2);
+ else
+ bitrate *= (modulation + 3);
+
+ bitrate *= streams;
+
+ if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+ bitrate = (bitrate / 9) * 10;
+
+ /* do NOT round down here */
+ return (bitrate + 50000) / 100000;
+}
+
static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
int flags, struct net_device *dev,
- const u8 *mac_addr, struct station_info *sinfo)
+ u8 *mac_addr, struct station_info *sinfo)
{
void *hdr;
struct nlattr *sinfoattr, *txrate;
@@ -1708,8 +1716,8 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
if (!txrate)
goto nla_put_failure;
- /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
- bitrate = cfg80211_calculate_bitrate(&sinfo->txrate);
+ /* nl80211_calculate_bitrate will return 0 for mcs >= 32 */
+ bitrate = nl80211_calculate_bitrate(&sinfo->txrate);
if (bitrate > 0)
NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
@@ -2015,9 +2023,6 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
return -EINVAL;
- if (!info->attrs[NL80211_ATTR_STA_AID])
- return -EINVAL;
-
mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
params.supported_rates =
nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
@@ -2026,9 +2031,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
params.listen_interval =
nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
- params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
- if (!params.aid || params.aid > IEEE80211_MAX_AID)
- return -EINVAL;
+ if (info->attrs[NL80211_ATTR_STA_AID]) {
+ params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
+ if (!params.aid || params.aid > IEEE80211_MAX_AID)
+ return -EINVAL;
+ }
if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
params.ht_capa =
@@ -2043,12 +2050,6 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
if (err)
goto out_rtnl;
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) {
- err = -EINVAL;
- goto out;
- }
-
err = get_vlan(info, rdev, ¶ms.vlan);
if (err)
goto out;
@@ -2056,6 +2057,35 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
/* validate settings */
err = 0;
+ switch (dev->ieee80211_ptr->iftype) {
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_AP_VLAN:
+ /* all ok but must have AID */
+ if (!params.aid)
+ err = -EINVAL;
+ break;
+ case NL80211_IFTYPE_MESH_POINT:
+ /* disallow things mesh doesn't support */
+ if (params.vlan)
+ err = -EINVAL;
+ if (params.aid)
+ err = -EINVAL;
+ if (params.ht_capa)
+ err = -EINVAL;
+ if (params.listen_interval >= 0)
+ err = -EINVAL;
+ if (params.supported_rates)
+ err = -EINVAL;
+ if (params.sta_flags_mask)
+ err = -EINVAL;
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ if (err)
+ goto out;
+
if (!rdev->ops->add_station) {
err = -EOPNOTSUPP;
goto out;
@@ -2096,7 +2126,8 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
goto out_rtnl;
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) {
+ dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
+ dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
err = -EINVAL;
goto out;
}
@@ -2552,6 +2583,12 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
+#ifdef CONFIG_WIRELESS_OLD_REGULATORY
+ /* We ignore world regdom requests with the old regdom setup */
+ if (is_world_regdom(data))
+ return -EINVAL;
+#endif
+
r = regulatory_hint_user(data);
return r;
@@ -3145,10 +3182,6 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
NLA_PUT(msg, NL80211_BSS_INFORMATION_ELEMENTS,
res->len_information_elements,
res->information_elements);
- if (res->beacon_ies && res->len_beacon_ies &&
- res->beacon_ies != res->information_elements)
- NLA_PUT(msg, NL80211_BSS_BEACON_IES,
- res->len_beacon_ies, res->beacon_ies);
if (res->tsf)
NLA_PUT_U64(msg, NL80211_BSS_TSF, res->tsf);
if (res->beacon_interval)
@@ -3553,7 +3586,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev;
struct net_device *dev;
- struct wireless_dev *wdev;
struct cfg80211_crypto_settings crypto;
struct ieee80211_channel *chan, *fixedchan;
const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
@@ -3599,8 +3631,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
}
mutex_lock(&rdev->devlist_mtx);
- wdev = dev->ieee80211_ptr;
- fixedchan = rdev_fixed_channel(rdev, wdev);
+ fixedchan = rdev_fixed_channel(rdev, NULL);
if (fixedchan && chan != fixedchan) {
err = -EBUSY;
mutex_unlock(&rdev->devlist_mtx);
@@ -4291,498 +4322,7 @@ static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
}
-static int nl80211_remain_on_channel(struct sk_buff *skb,
- struct genl_info *info)
-{
- struct cfg80211_registered_device *rdev;
- struct net_device *dev;
- struct ieee80211_channel *chan;
- struct sk_buff *msg;
- void *hdr;
- u64 cookie;
- enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
- u32 freq, duration;
- int err;
-
- if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
- !info->attrs[NL80211_ATTR_DURATION])
- return -EINVAL;
-
- duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
-
- /*
- * We should be on that channel for at least one jiffie,
- * and more than 5 seconds seems excessive.
- */
- if (!duration || !msecs_to_jiffies(duration) || duration > 5000)
- return -EINVAL;
-
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto unlock_rtnl;
-
- if (!rdev->ops->remain_on_channel) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- if (!netif_running(dev)) {
- err = -ENETDOWN;
- goto out;
- }
-
- if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
- channel_type = nla_get_u32(
- info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
- if (channel_type != NL80211_CHAN_NO_HT &&
- channel_type != NL80211_CHAN_HT20 &&
- channel_type != NL80211_CHAN_HT40PLUS &&
- channel_type != NL80211_CHAN_HT40MINUS)
- err = -EINVAL;
- goto out;
- }
-
- freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
- chan = rdev_freq_to_chan(rdev, freq, channel_type);
- if (chan == NULL) {
- err = -EINVAL;
- goto out;
- }
-
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!msg) {
- err = -ENOMEM;
- goto out;
- }
-
- hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
- NL80211_CMD_REMAIN_ON_CHANNEL);
-
- if (IS_ERR(hdr)) {
- err = PTR_ERR(hdr);
- goto free_msg;
- }
-
- err = rdev->ops->remain_on_channel(&rdev->wiphy, dev, chan,
- channel_type, duration, &cookie);
-
- if (err)
- goto free_msg;
-
- NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
-
- genlmsg_end(msg, hdr);
- err = genlmsg_reply(msg, info);
- goto out;
-
- nla_put_failure:
- err = -ENOBUFS;
- free_msg:
- nlmsg_free(msg);
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- unlock_rtnl:
- rtnl_unlock();
- return err;
-}
-
-static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
- struct genl_info *info)
-{
- struct cfg80211_registered_device *rdev;
- struct net_device *dev;
- u64 cookie;
- int err;
-
- if (!info->attrs[NL80211_ATTR_COOKIE])
- return -EINVAL;
-
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto unlock_rtnl;
-
- if (!rdev->ops->cancel_remain_on_channel) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- if (!netif_running(dev)) {
- err = -ENETDOWN;
- goto out;
- }
-
- cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
-
- err = rdev->ops->cancel_remain_on_channel(&rdev->wiphy, dev, cookie);
-
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- unlock_rtnl:
- rtnl_unlock();
- return err;
-}
-
-static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
- u8 *rates, u8 rates_len)
-{
- u8 i;
- u32 mask = 0;
-
- for (i = 0; i < rates_len; i++) {
- int rate = (rates[i] & 0x7f) * 5;
- int ridx;
- for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
- struct ieee80211_rate *srate =
- &sband->bitrates[ridx];
- if (rate == srate->bitrate) {
- mask |= 1 << ridx;
- break;
- }
- }
- if (ridx == sband->n_bitrates)
- return 0; /* rate not found */
- }
-
- return mask;
-}
-
-static struct nla_policy
-nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] __read_mostly = {
- [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY,
- .len = NL80211_MAX_SUPP_RATES },
-};
-
-static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
- struct genl_info *info)
-{
- struct nlattr *tb[NL80211_TXRATE_MAX + 1];
- struct cfg80211_registered_device *rdev;
- struct cfg80211_bitrate_mask mask;
- int err, rem, i;
- struct net_device *dev;
- struct nlattr *tx_rates;
- struct ieee80211_supported_band *sband;
-
- if (info->attrs[NL80211_ATTR_TX_RATES] == NULL)
- return -EINVAL;
-
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto unlock_rtnl;
-
- if (!rdev->ops->set_bitrate_mask) {
- err = -EOPNOTSUPP;
- goto unlock;
- }
-
- memset(&mask, 0, sizeof(mask));
- /* Default to all rates enabled */
- for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
- sband = rdev->wiphy.bands[i];
- mask.control[i].legacy =
- sband ? (1 << sband->n_bitrates) - 1 : 0;
- }
-
- /*
- * The nested attribute uses enum nl80211_band as the index. This maps
- * directly to the enum ieee80211_band values used in cfg80211.
- */
- nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem)
- {
- enum ieee80211_band band = nla_type(tx_rates);
- if (band < 0 || band >= IEEE80211_NUM_BANDS) {
- err = -EINVAL;
- goto unlock;
- }
- sband = rdev->wiphy.bands[band];
- if (sband == NULL) {
- err = -EINVAL;
- goto unlock;
- }
- nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
- nla_len(tx_rates), nl80211_txattr_policy);
- if (tb[NL80211_TXRATE_LEGACY]) {
- mask.control[band].legacy = rateset_to_mask(
- sband,
- nla_data(tb[NL80211_TXRATE_LEGACY]),
- nla_len(tb[NL80211_TXRATE_LEGACY]));
- if (mask.control[band].legacy == 0) {
- err = -EINVAL;
- goto unlock;
- }
- }
- }
-
- err = rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, NULL, &mask);
-
- unlock:
- dev_put(dev);
- cfg80211_unlock_rdev(rdev);
- unlock_rtnl:
- rtnl_unlock();
- return err;
-}
-
-static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info)
-{
- struct cfg80211_registered_device *rdev;
- struct net_device *dev;
- int err;
-
- if (!info->attrs[NL80211_ATTR_FRAME_MATCH])
- return -EINVAL;
-
- if (nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]) < 1)
- return -EINVAL;
-
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto unlock_rtnl;
-
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- /* not much point in registering if we can't reply */
- if (!rdev->ops->action) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- err = cfg80211_mlme_register_action(dev->ieee80211_ptr, info->snd_pid,
- nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
- nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]));
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- unlock_rtnl:
- rtnl_unlock();
- return err;
-}
-
-static int nl80211_action(struct sk_buff *skb, struct genl_info *info)
-{
- struct cfg80211_registered_device *rdev;
- struct net_device *dev;
- struct ieee80211_channel *chan;
- enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
- u32 freq;
- int err;
- void *hdr;
- u64 cookie;
- struct sk_buff *msg;
-
- if (!info->attrs[NL80211_ATTR_FRAME] ||
- !info->attrs[NL80211_ATTR_WIPHY_FREQ])
- return -EINVAL;
-
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto unlock_rtnl;
-
- if (!rdev->ops->action) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- if (!netif_running(dev)) {
- err = -ENETDOWN;
- goto out;
- }
-
- if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
- channel_type = nla_get_u32(
- info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
- if (channel_type != NL80211_CHAN_NO_HT &&
- channel_type != NL80211_CHAN_HT20 &&
- channel_type != NL80211_CHAN_HT40PLUS &&
- channel_type != NL80211_CHAN_HT40MINUS)
- err = -EINVAL;
- goto out;
- }
-
- freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
- chan = rdev_freq_to_chan(rdev, freq, channel_type);
- if (chan == NULL) {
- err = -EINVAL;
- goto out;
- }
-
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!msg) {
- err = -ENOMEM;
- goto out;
- }
-
- hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
- NL80211_CMD_ACTION);
-
- if (IS_ERR(hdr)) {
- err = PTR_ERR(hdr);
- goto free_msg;
- }
- err = cfg80211_mlme_action(rdev, dev, chan, channel_type,
- nla_data(info->attrs[NL80211_ATTR_FRAME]),
- nla_len(info->attrs[NL80211_ATTR_FRAME]),
- &cookie);
- if (err)
- goto free_msg;
-
- NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
-
- genlmsg_end(msg, hdr);
- err = genlmsg_reply(msg, info);
- goto out;
-
- nla_put_failure:
- err = -ENOBUFS;
- free_msg:
- nlmsg_free(msg);
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
-unlock_rtnl:
- rtnl_unlock();
- return err;
-}
-
-static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
-{
- struct cfg80211_registered_device *rdev;
- struct wireless_dev *wdev;
- struct net_device *dev;
- u8 ps_state;
- bool state;
- int err;
-
- if (!info->attrs[NL80211_ATTR_PS_STATE]) {
- err = -EINVAL;
- goto out;
- }
-
- ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]);
-
- if (ps_state != NL80211_PS_DISABLED && ps_state != NL80211_PS_ENABLED) {
- err = -EINVAL;
- goto out;
- }
-
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto unlock_rdev;
-
- wdev = dev->ieee80211_ptr;
-
- if (!rdev->ops->set_power_mgmt) {
- err = -EOPNOTSUPP;
- goto unlock_rdev;
- }
-
- state = (ps_state == NL80211_PS_ENABLED) ? true : false;
-
- if (state == wdev->ps)
- goto unlock_rdev;
-
- wdev->ps = state;
-
- if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, wdev->ps,
- wdev->ps_timeout))
- /* assume this means it's off */
- wdev->ps = false;
-
-unlock_rdev:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- rtnl_unlock();
-
-out:
- return err;
-}
-
-static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
-{
- struct cfg80211_registered_device *rdev;
- enum nl80211_ps_state ps_state;
- struct wireless_dev *wdev;
- struct net_device *dev;
- struct sk_buff *msg;
- void *hdr;
- int err;
-
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto unlock_rtnl;
-
- wdev = dev->ieee80211_ptr;
-
- if (!rdev->ops->set_power_mgmt) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!msg) {
- err = -ENOMEM;
- goto out;
- }
-
- hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
- NL80211_CMD_GET_POWER_SAVE);
- if (!hdr) {
- err = -ENOMEM;
- goto free_msg;
- }
-
- if (wdev->ps)
- ps_state = NL80211_PS_ENABLED;
- else
- ps_state = NL80211_PS_DISABLED;
-
- NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state);
-
- genlmsg_end(msg, hdr);
- err = genlmsg_reply(msg, info);
- goto out;
-
-nla_put_failure:
- err = -ENOBUFS;
-
-free_msg:
- nlmsg_free(msg);
-
-out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
-
-unlock_rtnl:
- rtnl_unlock();
-
- return err;
-}
-
-static struct genl_ops nl80211_ops[] = {
+static struct genl_ops nl80211_ops[] = {
{
.cmd = NL80211_CMD_GET_WIPHY,
.doit = nl80211_get_wiphy,
@@ -5044,50 +4584,8 @@ static struct genl_ops nl80211_ops[] = {
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
},
- {
- .cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
- .doit = nl80211_remain_on_channel,
- .policy = nl80211_policy,
- .flags = GENL_ADMIN_PERM,
- },
- {
- .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
- .doit = nl80211_cancel_remain_on_channel,
- .policy = nl80211_policy,
- .flags = GENL_ADMIN_PERM,
- },
- {
- .cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
- .doit = nl80211_set_tx_bitrate_mask,
- .policy = nl80211_policy,
- .flags = GENL_ADMIN_PERM,
- },
- {
- .cmd = NL80211_CMD_REGISTER_ACTION,
- .doit = nl80211_register_action,
- .policy = nl80211_policy,
- .flags = GENL_ADMIN_PERM,
- },
- {
- .cmd = NL80211_CMD_ACTION,
- .doit = nl80211_action,
- .policy = nl80211_policy,
- .flags = GENL_ADMIN_PERM,
- },
- {
- .cmd = NL80211_CMD_SET_POWER_SAVE,
- .doit = nl80211_set_power_save,
- .policy = nl80211_policy,
- .flags = GENL_ADMIN_PERM,
- },
- {
- .cmd = NL80211_CMD_GET_POWER_SAVE,
- .doit = nl80211_get_power_save,
- .policy = nl80211_policy,
- /* can be retrieved by unprivileged users */
- },
-};
+};
static struct genl_multicast_group nl80211_mlme_mcgrp = {
.name = "mlme",
};
@@ -5675,193 +5173,6 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
nlmsg_free(msg);
}
-static void nl80211_send_remain_on_chan_event(
- int cmd, struct cfg80211_registered_device *rdev,
- struct net_device *netdev, u64 cookie,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- unsigned int duration, gfp_t gfp)
-{
- struct sk_buff *msg;
- void *hdr;
-
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
- if (!msg)
- return;
-
- hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
- if (!hdr) {
- nlmsg_free(msg);
- return;
- }
-
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq);
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, channel_type);
- NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
-
- if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL)
- NLA_PUT_U32(msg, NL80211_ATTR_DURATION, duration);
-
- if (genlmsg_end(msg, hdr) < 0) {
- nlmsg_free(msg);
- return;
- }
-
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
- return;
-
- nla_put_failure:
- genlmsg_cancel(msg, hdr);
- nlmsg_free(msg);
-}
-
-void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, u64 cookie,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- unsigned int duration, gfp_t gfp)
-{
- nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL,
- rdev, netdev, cookie, chan,
- channel_type, duration, gfp);
-}
-
-void nl80211_send_remain_on_channel_cancel(
- struct cfg80211_registered_device *rdev, struct net_device *netdev,
- u64 cookie, struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type, gfp_t gfp)
-{
- nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
- rdev, netdev, cookie, chan,
- channel_type, 0, gfp);
-}
-
-void nl80211_send_sta_event(struct cfg80211_registered_device *rdev,
- struct net_device *dev, const u8 *mac_addr,
- struct station_info *sinfo, gfp_t gfp)
-{
- struct sk_buff *msg;
-
- msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
- if (!msg)
- return;
-
- if (nl80211_send_station(msg, 0, 0, 0, dev, mac_addr, sinfo) < 0) {
- nlmsg_free(msg);
- return;
- }
-
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
-}
-
-int nl80211_send_action(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, u32 nlpid,
- int freq, const u8 *buf, size_t len, gfp_t gfp)
-{
- struct sk_buff *msg;
- void *hdr;
- int err;
-
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
- if (!msg)
- return -ENOMEM;
-
- hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION);
- if (!hdr) {
- nlmsg_free(msg);
- return -ENOMEM;
- }
-
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
- NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf);
-
- err = genlmsg_end(msg, hdr);
- if (err < 0) {
- nlmsg_free(msg);
- return err;
- }
-
- err = genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlpid);
- if (err < 0)
- return err;
- return 0;
-
- nla_put_failure:
- genlmsg_cancel(msg, hdr);
- nlmsg_free(msg);
- return -ENOBUFS;
-}
-
-void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, u64 cookie,
- const u8 *buf, size_t len, bool ack,
- gfp_t gfp)
-{
- struct sk_buff *msg;
- void *hdr;
-
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
- if (!msg)
- return;
-
- hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION_TX_STATUS);
- if (!hdr) {
- nlmsg_free(msg);
- return;
- }
-
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
- NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf);
- NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
- if (ack)
- NLA_PUT_FLAG(msg, NL80211_ATTR_ACK);
-
- if (genlmsg_end(msg, hdr) < 0) {
- nlmsg_free(msg);
- return;
- }
-
- genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
- return;
-
- nla_put_failure:
- genlmsg_cancel(msg, hdr);
- nlmsg_free(msg);
-}
-
-static int nl80211_netlink_notify(struct notifier_block * nb,
- unsigned long state,
- void *_notify)
-{
- struct netlink_notify *notify = _notify;
- struct cfg80211_registered_device *rdev;
- struct wireless_dev *wdev;
-
- if (state != NETLINK_URELEASE)
- return NOTIFY_DONE;
-
- rcu_read_lock();
-
- list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list)
- list_for_each_entry_rcu(wdev, &rdev->netdev_list, list)
- cfg80211_mlme_unregister_actions(wdev, notify->pid);
-
- rcu_read_unlock();
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block nl80211_netlink_notifier = {
- .notifier_call = nl80211_netlink_notify,
-};
-
/* initialisation/exit functions */
int nl80211_init(void)
@@ -5895,10 +5206,6 @@ int nl80211_init(void)
goto err_out;
#endif
- err = netlink_register_notifier(&nl80211_netlink_notifier);
- if (err)
- goto err_out;
-
return 0;
err_out:
genl_unregister_family(&nl80211_fam);
@@ -5907,6 +5214,5 @@ int nl80211_init(void)
void nl80211_exit(void)
{
- netlink_unregister_notifier(&nl80211_netlink_notifier);
genl_unregister_family(&nl80211_fam);
}
diff --git a/trunk/net/wireless/nl80211.h b/trunk/net/wireless/nl80211.h
index 4ca511102c6c..44cc2a76a1b0 100644
--- a/trunk/net/wireless/nl80211.h
+++ b/trunk/net/wireless/nl80211.h
@@ -59,27 +59,4 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *bssid,
gfp_t gfp);
-void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev,
- struct net_device *netdev,
- u64 cookie,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- unsigned int duration, gfp_t gfp);
-void nl80211_send_remain_on_channel_cancel(
- struct cfg80211_registered_device *rdev, struct net_device *netdev,
- u64 cookie, struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type, gfp_t gfp);
-
-void nl80211_send_sta_event(struct cfg80211_registered_device *rdev,
- struct net_device *dev, const u8 *mac_addr,
- struct station_info *sinfo, gfp_t gfp);
-
-int nl80211_send_action(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, u32 nlpid, int freq,
- const u8 *buf, size_t len, gfp_t gfp);
-void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, u64 cookie,
- const u8 *buf, size_t len, bool ack,
- gfp_t gfp);
-
#endif /* __NET_WIRELESS_NL80211_H */
diff --git a/trunk/net/wireless/radiotap.c b/trunk/net/wireless/radiotap.c
index 1332c445d1c7..f591871a7b4f 100644
--- a/trunk/net/wireless/radiotap.c
+++ b/trunk/net/wireless/radiotap.c
@@ -2,16 +2,6 @@
* Radiotap parser
*
* Copyright 2007 Andy Green
- * Copyright 2009 Johannes Berg
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See COPYING for more details.
*/
#include
@@ -20,35 +10,6 @@
/* function prototypes and related defs are in include/net/cfg80211.h */
-static const struct radiotap_align_size rtap_namespace_sizes[] = {
- [IEEE80211_RADIOTAP_TSFT] = { .align = 8, .size = 8, },
- [IEEE80211_RADIOTAP_FLAGS] = { .align = 1, .size = 1, },
- [IEEE80211_RADIOTAP_RATE] = { .align = 1, .size = 1, },
- [IEEE80211_RADIOTAP_CHANNEL] = { .align = 2, .size = 4, },
- [IEEE80211_RADIOTAP_FHSS] = { .align = 2, .size = 2, },
- [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = { .align = 1, .size = 1, },
- [IEEE80211_RADIOTAP_DBM_ANTNOISE] = { .align = 1, .size = 1, },
- [IEEE80211_RADIOTAP_LOCK_QUALITY] = { .align = 2, .size = 2, },
- [IEEE80211_RADIOTAP_TX_ATTENUATION] = { .align = 2, .size = 2, },
- [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = { .align = 2, .size = 2, },
- [IEEE80211_RADIOTAP_DBM_TX_POWER] = { .align = 1, .size = 1, },
- [IEEE80211_RADIOTAP_ANTENNA] = { .align = 1, .size = 1, },
- [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = { .align = 1, .size = 1, },
- [IEEE80211_RADIOTAP_DB_ANTNOISE] = { .align = 1, .size = 1, },
- [IEEE80211_RADIOTAP_RX_FLAGS] = { .align = 2, .size = 2, },
- [IEEE80211_RADIOTAP_TX_FLAGS] = { .align = 2, .size = 2, },
- [IEEE80211_RADIOTAP_RTS_RETRIES] = { .align = 1, .size = 1, },
- [IEEE80211_RADIOTAP_DATA_RETRIES] = { .align = 1, .size = 1, },
- /*
- * add more here as they are defined in radiotap.h
- */
-};
-
-static const struct ieee80211_radiotap_namespace radiotap_ns = {
- .n_bits = sizeof(rtap_namespace_sizes) / sizeof(rtap_namespace_sizes[0]),
- .align_size = rtap_namespace_sizes,
-};
-
/**
* ieee80211_radiotap_iterator_init - radiotap parser iterator initialization
* @iterator: radiotap_iterator to initialize
@@ -89,9 +50,9 @@ static const struct ieee80211_radiotap_namespace radiotap_ns = {
*/
int ieee80211_radiotap_iterator_init(
- struct ieee80211_radiotap_iterator *iterator,
- struct ieee80211_radiotap_header *radiotap_header,
- int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns)
+ struct ieee80211_radiotap_iterator *iterator,
+ struct ieee80211_radiotap_header *radiotap_header,
+ int max_length)
{
/* Linux only supports version 0 radiotap format */
if (radiotap_header->it_version)
@@ -101,24 +62,19 @@ int ieee80211_radiotap_iterator_init(
if (max_length < get_unaligned_le16(&radiotap_header->it_len))
return -EINVAL;
- iterator->_rtheader = radiotap_header;
- iterator->_max_length = get_unaligned_le16(&radiotap_header->it_len);
- iterator->_arg_index = 0;
- iterator->_bitmap_shifter = get_unaligned_le32(&radiotap_header->it_present);
- iterator->_arg = (uint8_t *)radiotap_header + sizeof(*radiotap_header);
- iterator->_reset_on_ext = 0;
- iterator->_next_bitmap = &radiotap_header->it_present;
- iterator->_next_bitmap++;
- iterator->_vns = vns;
- iterator->current_namespace = &radiotap_ns;
- iterator->is_radiotap_ns = 1;
+ iterator->rtheader = radiotap_header;
+ iterator->max_length = get_unaligned_le16(&radiotap_header->it_len);
+ iterator->arg_index = 0;
+ iterator->bitmap_shifter = get_unaligned_le32(&radiotap_header->it_present);
+ iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header);
+ iterator->this_arg = NULL;
/* find payload start allowing for extended bitmap(s) */
- if (iterator->_bitmap_shifter & (1<_arg) &
- (1 << IEEE80211_RADIOTAP_EXT)) {
- iterator->_arg += sizeof(uint32_t);
+ if (unlikely(iterator->bitmap_shifter & (1<arg) &
+ (1 << IEEE80211_RADIOTAP_EXT)) {
+ iterator->arg += sizeof(u32);
/*
* check for insanity where the present bitmaps
@@ -126,13 +82,12 @@ int ieee80211_radiotap_iterator_init(
* stated radiotap header length
*/
- if ((unsigned long)iterator->_arg -
- (unsigned long)iterator->_rtheader >
- (unsigned long)iterator->_max_length)
+ if (((ulong)iterator->arg -
+ (ulong)iterator->rtheader) > iterator->max_length)
return -EINVAL;
}
- iterator->_arg += sizeof(uint32_t);
+ iterator->arg += sizeof(u32);
/*
* no need to check again for blowing past stated radiotap
@@ -141,36 +96,12 @@ int ieee80211_radiotap_iterator_init(
*/
}
- iterator->this_arg = iterator->_arg;
-
/* we are all initialized happily */
return 0;
}
EXPORT_SYMBOL(ieee80211_radiotap_iterator_init);
-static void find_ns(struct ieee80211_radiotap_iterator *iterator,
- uint32_t oui, uint8_t subns)
-{
- int i;
-
- iterator->current_namespace = NULL;
-
- if (!iterator->_vns)
- return;
-
- for (i = 0; i < iterator->_vns->n_ns; i++) {
- if (iterator->_vns->ns[i].oui != oui)
- continue;
- if (iterator->_vns->ns[i].subns != subns)
- continue;
-
- iterator->current_namespace = &iterator->_vns->ns[i];
- break;
- }
-}
-
-
/**
* ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg
@@ -196,80 +127,99 @@ static void find_ns(struct ieee80211_radiotap_iterator *iterator,
*/
int ieee80211_radiotap_iterator_next(
- struct ieee80211_radiotap_iterator *iterator)
+ struct ieee80211_radiotap_iterator *iterator)
{
- while (1) {
- int hit = 0;
- int pad, align, size, subns, vnslen;
- uint32_t oui;
- /* if no more EXT bits, that's it */
- if ((iterator->_arg_index % 32) == IEEE80211_RADIOTAP_EXT &&
- !(iterator->_bitmap_shifter & 1))
- return -ENOENT;
+ /*
+ * small length lookup table for all radiotap types we heard of
+ * starting from b0 in the bitmap, so we can walk the payload
+ * area of the radiotap header
+ *
+ * There is a requirement to pad args, so that args
+ * of a given length must begin at a boundary of that length
+ * -- but note that compound args are allowed (eg, 2 x u16
+ * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not
+ * a reliable indicator of alignment requirement.
+ *
+ * upper nybble: content alignment for arg
+ * lower nybble: content length for arg
+ */
- if (!(iterator->_bitmap_shifter & 1))
- goto next_entry; /* arg not present */
+ static const u8 rt_sizes[] = {
+ [IEEE80211_RADIOTAP_TSFT] = 0x88,
+ [IEEE80211_RADIOTAP_FLAGS] = 0x11,
+ [IEEE80211_RADIOTAP_RATE] = 0x11,
+ [IEEE80211_RADIOTAP_CHANNEL] = 0x24,
+ [IEEE80211_RADIOTAP_FHSS] = 0x22,
+ [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11,
+ [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11,
+ [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22,
+ [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22,
+ [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22,
+ [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11,
+ [IEEE80211_RADIOTAP_ANTENNA] = 0x11,
+ [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11,
+ [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11,
+ [IEEE80211_RADIOTAP_RX_FLAGS] = 0x22,
+ [IEEE80211_RADIOTAP_TX_FLAGS] = 0x22,
+ [IEEE80211_RADIOTAP_RTS_RETRIES] = 0x11,
+ [IEEE80211_RADIOTAP_DATA_RETRIES] = 0x11,
+ /*
+ * add more here as they are defined in
+ * include/net/ieee80211_radiotap.h
+ */
+ };
- /* get alignment/size of data */
- switch (iterator->_arg_index % 32) {
- case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE:
- case IEEE80211_RADIOTAP_EXT:
- align = 1;
- size = 0;
- break;
- case IEEE80211_RADIOTAP_VENDOR_NAMESPACE:
- align = 2;
- size = 6;
- break;
- default:
- if (!iterator->current_namespace ||
- iterator->_arg_index >= iterator->current_namespace->n_bits) {
- if (iterator->current_namespace == &radiotap_ns)
- return -ENOENT;
- align = 0;
- } else {
- align = iterator->current_namespace->align_size[iterator->_arg_index].align;
- size = iterator->current_namespace->align_size[iterator->_arg_index].size;
- }
- if (!align) {
- /* skip all subsequent data */
- iterator->_arg = iterator->_next_ns_data;
- /* give up on this namespace */
- iterator->current_namespace = NULL;
- goto next_entry;
- }
- break;
- }
+ /*
+ * for every radiotap entry we can at
+ * least skip (by knowing the length)...
+ */
+
+ while (iterator->arg_index < sizeof(rt_sizes)) {
+ int hit = 0;
+ int pad;
+
+ if (!(iterator->bitmap_shifter & 1))
+ goto next_entry; /* arg not present */
/*
* arg is present, account for alignment padding
+ * 8-bit args can be at any alignment
+ * 16-bit args must start on 16-bit boundary
+ * 32-bit args must start on 32-bit boundary
+ * 64-bit args must start on 64-bit boundary
*
- * Note that these alignments are relative to the start
- * of the radiotap header. There is no guarantee
+ * note that total arg size can differ from alignment of
+ * elements inside arg, so we use upper nybble of length
+ * table to base alignment on
+ *
+ * also note: these alignments are ** relative to the
+ * start of the radiotap header **. There is no guarantee
* that the radiotap header itself is aligned on any
* kind of boundary.
*
- * The above is why get_unaligned() is used to dereference
- * multibyte elements from the radiotap area.
+ * the above is why get_unaligned() is used to dereference
+ * multibyte elements from the radiotap area
*/
- pad = ((unsigned long)iterator->_arg -
- (unsigned long)iterator->_rtheader) & (align - 1);
+ pad = (((ulong)iterator->arg) -
+ ((ulong)iterator->rtheader)) &
+ ((rt_sizes[iterator->arg_index] >> 4) - 1);
if (pad)
- iterator->_arg += align - pad;
+ iterator->arg +=
+ (rt_sizes[iterator->arg_index] >> 4) - pad;
/*
* this is what we will return to user, but we need to
* move on first so next call has something fresh to test
*/
- iterator->this_arg_index = iterator->_arg_index;
- iterator->this_arg = iterator->_arg;
- iterator->this_arg_size = size;
+ iterator->this_arg_index = iterator->arg_index;
+ iterator->this_arg = iterator->arg;
+ hit = 1;
/* internally move on the size of this arg */
- iterator->_arg += size;
+ iterator->arg += rt_sizes[iterator->arg_index] & 0x0f;
/*
* check for insanity where we are given a bitmap that
@@ -278,73 +228,32 @@ int ieee80211_radiotap_iterator_next(
* max_length on the last arg, never exceeding it.
*/
- if ((unsigned long)iterator->_arg -
- (unsigned long)iterator->_rtheader >
- (unsigned long)iterator->_max_length)
+ if (((ulong)iterator->arg - (ulong)iterator->rtheader) >
+ iterator->max_length)
return -EINVAL;
- /* these special ones are valid in each bitmap word */
- switch (iterator->_arg_index % 32) {
- case IEEE80211_RADIOTAP_VENDOR_NAMESPACE:
- iterator->_bitmap_shifter >>= 1;
- iterator->_arg_index++;
-
- iterator->_reset_on_ext = 1;
-
- vnslen = get_unaligned_le16(iterator->this_arg + 4);
- iterator->_next_ns_data = iterator->_arg + vnslen;
- oui = (*iterator->this_arg << 16) |
- (*(iterator->this_arg + 1) << 8) |
- *(iterator->this_arg + 2);
- subns = *(iterator->this_arg + 3);
-
- find_ns(iterator, oui, subns);
-
- iterator->is_radiotap_ns = 0;
- /* allow parsers to show this information */
- iterator->this_arg_index =
- IEEE80211_RADIOTAP_VENDOR_NAMESPACE;
- iterator->this_arg_size += vnslen;
- if ((unsigned long)iterator->this_arg +
- iterator->this_arg_size -
- (unsigned long)iterator->_rtheader >
- (unsigned long)(unsigned long)iterator->_max_length)
- return -EINVAL;
- hit = 1;
- break;
- case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE:
- iterator->_bitmap_shifter >>= 1;
- iterator->_arg_index++;
-
- iterator->_reset_on_ext = 1;
- iterator->current_namespace = &radiotap_ns;
- iterator->is_radiotap_ns = 1;
- break;
- case IEEE80211_RADIOTAP_EXT:
- /*
- * bit 31 was set, there is more
- * -- move to next u32 bitmap
- */
- iterator->_bitmap_shifter =
- get_unaligned_le32(iterator->_next_bitmap);
- iterator->_next_bitmap++;
- if (iterator->_reset_on_ext)
- iterator->_arg_index = 0;
- else
- iterator->_arg_index++;
- iterator->_reset_on_ext = 0;
- break;
- default:
- /* we've got a hit! */
- hit = 1;
- next_entry:
- iterator->_bitmap_shifter >>= 1;
- iterator->_arg_index++;
- }
+ next_entry:
+ iterator->arg_index++;
+ if (unlikely((iterator->arg_index & 31) == 0)) {
+ /* completed current u32 bitmap */
+ if (iterator->bitmap_shifter & 1) {
+ /* b31 was set, there is more */
+ /* move to next u32 bitmap */
+ iterator->bitmap_shifter =
+ get_unaligned_le32(iterator->next_bitmap);
+ iterator->next_bitmap++;
+ } else
+ /* no more bitmaps: end */
+ iterator->arg_index = sizeof(rt_sizes);
+ } else /* just try the next bit */
+ iterator->bitmap_shifter >>= 1;
/* if we found a valid arg earlier, return it now */
if (hit)
return 0;
}
+
+ /* we don't know how to handle any more args, we're done */
+ return -ENOENT;
}
EXPORT_SYMBOL(ieee80211_radiotap_iterator_next);
diff --git a/trunk/net/wireless/reg.c b/trunk/net/wireless/reg.c
index ed89c59bb431..7a0754c92df4 100644
--- a/trunk/net/wireless/reg.c
+++ b/trunk/net/wireless/reg.c
@@ -40,18 +40,8 @@
#include
#include "core.h"
#include "reg.h"
-#include "regdb.h"
#include "nl80211.h"
-#ifdef CONFIG_CFG80211_REG_DEBUG
-#define REG_DBG_PRINT(format, args...) \
- do { \
- printk(KERN_DEBUG format , ## args); \
- } while (0)
-#else
-#define REG_DBG_PRINT(args...)
-#endif
-
/* Receipt of information from last regulatory request */
static struct regulatory_request *last_request;
@@ -134,11 +124,82 @@ static const struct ieee80211_regdomain *cfg80211_world_regdom =
&world_regdom;
static char *ieee80211_regdom = "00";
-static char user_alpha2[2];
module_param(ieee80211_regdom, charp, 0444);
MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
+#ifdef CONFIG_WIRELESS_OLD_REGULATORY
+/*
+ * We assume 40 MHz bandwidth for the old regulatory work.
+ * We make emphasis we are using the exact same frequencies
+ * as before
+ */
+
+static const struct ieee80211_regdomain us_regdom = {
+ .n_reg_rules = 6,
+ .alpha2 = "US",
+ .reg_rules = {
+ /* IEEE 802.11b/g, channels 1..11 */
+ REG_RULE(2412-10, 2462+10, 40, 6, 27, 0),
+ /* IEEE 802.11a, channel 36..48 */
+ REG_RULE(5180-10, 5240+10, 40, 6, 17, 0),
+ /* IEEE 802.11a, channels 48..64 */
+ REG_RULE(5260-10, 5320+10, 40, 6, 20, NL80211_RRF_DFS),
+ /* IEEE 802.11a, channels 100..124 */
+ REG_RULE(5500-10, 5590+10, 40, 6, 20, NL80211_RRF_DFS),
+ /* IEEE 802.11a, channels 132..144 */
+ REG_RULE(5660-10, 5700+10, 40, 6, 20, NL80211_RRF_DFS),
+ /* IEEE 802.11a, channels 149..165, outdoor */
+ REG_RULE(5745-10, 5825+10, 40, 6, 30, 0),
+ }
+};
+
+static const struct ieee80211_regdomain jp_regdom = {
+ .n_reg_rules = 6,
+ .alpha2 = "JP",
+ .reg_rules = {
+ /* IEEE 802.11b/g, channels 1..11 */
+ REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
+ /* IEEE 802.11b/g, channels 12..13 */
+ REG_RULE(2467-10, 2472+10, 20, 6, 20, 0),
+ /* IEEE 802.11b/g, channel 14 */
+ REG_RULE(2484-10, 2484+10, 20, 6, 20, NL80211_RRF_NO_OFDM),
+ /* IEEE 802.11a, channels 36..48 */
+ REG_RULE(5180-10, 5240+10, 40, 6, 20, 0),
+ /* IEEE 802.11a, channels 52..64 */
+ REG_RULE(5260-10, 5320+10, 40, 6, 20, NL80211_RRF_DFS),
+ /* IEEE 802.11a, channels 100..144 */
+ REG_RULE(5500-10, 5700+10, 40, 6, 23, NL80211_RRF_DFS),
+ }
+};
+
+static const struct ieee80211_regdomain *static_regdom(char *alpha2)
+{
+ if (alpha2[0] == 'U' && alpha2[1] == 'S')
+ return &us_regdom;
+ if (alpha2[0] == 'J' && alpha2[1] == 'P')
+ return &jp_regdom;
+ /* Use world roaming rules for "EU", since it was a pseudo
+ domain anyway... */
+ if (alpha2[0] == 'E' && alpha2[1] == 'U')
+ return &world_regdom;
+ /* Default, world roaming rules */
+ return &world_regdom;
+}
+
+static bool is_old_static_regdom(const struct ieee80211_regdomain *rd)
+{
+ if (rd == &us_regdom || rd == &jp_regdom || rd == &world_regdom)
+ return true;
+ return false;
+}
+#else
+static inline bool is_old_static_regdom(const struct ieee80211_regdomain *rd)
+{
+ return false;
+}
+#endif
+
static void reset_regdomains(void)
{
/* avoid freeing static information or freeing something twice */
@@ -148,6 +209,8 @@ static void reset_regdomains(void)
cfg80211_world_regdom = NULL;
if (cfg80211_regdomain == &world_regdom)
cfg80211_regdomain = NULL;
+ if (is_old_static_regdom(cfg80211_regdomain))
+ cfg80211_regdomain = NULL;
kfree(cfg80211_regdomain);
kfree(cfg80211_world_regdom);
@@ -253,27 +316,6 @@ static bool regdom_changes(const char *alpha2)
return true;
}
-/*
- * The NL80211_REGDOM_SET_BY_USER regdom alpha2 is cached, this lets
- * you know if a valid regulatory hint with NL80211_REGDOM_SET_BY_USER
- * has ever been issued.
- */
-static bool is_user_regdom_saved(void)
-{
- if (user_alpha2[0] == '9' && user_alpha2[1] == '7')
- return false;
-
- /* This would indicate a mistake on the design */
- if (WARN((!is_world_regdom(user_alpha2) &&
- !is_an_alpha2(user_alpha2)),
- "Unexpected user alpha2: %c%c\n",
- user_alpha2[0],
- user_alpha2[1]))
- return false;
-
- return true;
-}
-
/**
* country_ie_integrity_changes - tells us if the country IE has changed
* @checksum: checksum of country IE of fields we are interested in
@@ -293,98 +335,6 @@ static bool country_ie_integrity_changes(u32 checksum)
return false;
}
-static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd,
- const struct ieee80211_regdomain *src_regd)
-{
- struct ieee80211_regdomain *regd;
- int size_of_regd = 0;
- unsigned int i;
-
- size_of_regd = sizeof(struct ieee80211_regdomain) +
- ((src_regd->n_reg_rules + 1) * sizeof(struct ieee80211_reg_rule));
-
- regd = kzalloc(size_of_regd, GFP_KERNEL);
- if (!regd)
- return -ENOMEM;
-
- memcpy(regd, src_regd, sizeof(struct ieee80211_regdomain));
-
- for (i = 0; i < src_regd->n_reg_rules; i++)
- memcpy(®d->reg_rules[i], &src_regd->reg_rules[i],
- sizeof(struct ieee80211_reg_rule));
-
- *dst_regd = regd;
- return 0;
-}
-
-#ifdef CONFIG_CFG80211_INTERNAL_REGDB
-struct reg_regdb_search_request {
- char alpha2[2];
- struct list_head list;
-};
-
-static LIST_HEAD(reg_regdb_search_list);
-static DEFINE_SPINLOCK(reg_regdb_search_lock);
-
-static void reg_regdb_search(struct work_struct *work)
-{
- struct reg_regdb_search_request *request;
- const struct ieee80211_regdomain *curdom, *regdom;
- int i, r;
-
- spin_lock(®_regdb_search_lock);
- while (!list_empty(®_regdb_search_list)) {
- request = list_first_entry(®_regdb_search_list,
- struct reg_regdb_search_request,
- list);
- list_del(&request->list);
-
- for (i=0; ialpha2, curdom->alpha2, 2)) {
- r = reg_copy_regd(®dom, curdom);
- if (r)
- break;
- spin_unlock(®_regdb_search_lock);
- mutex_lock(&cfg80211_mutex);
- set_regdom(regdom);
- mutex_unlock(&cfg80211_mutex);
- spin_lock(®_regdb_search_lock);
- break;
- }
- }
-
- kfree(request);
- }
- spin_unlock(®_regdb_search_lock);
-}
-
-static DECLARE_WORK(reg_regdb_work, reg_regdb_search);
-
-static void reg_regdb_query(const char *alpha2)
-{
- struct reg_regdb_search_request *request;
-
- if (!alpha2)
- return;
-
- request = kzalloc(sizeof(struct reg_regdb_search_request), GFP_KERNEL);
- if (!request)
- return;
-
- memcpy(request->alpha2, alpha2, 2);
-
- spin_lock(®_regdb_search_lock);
- list_add_tail(&request->list, ®_regdb_search_list);
- spin_unlock(®_regdb_search_lock);
-
- schedule_work(®_regdb_work);
-}
-#else
-static inline void reg_regdb_query(const char *alpha2) {}
-#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
-
/*
* This lets us keep regulatory code which is updated on a regulatory
* basis in userspace.
@@ -404,9 +354,6 @@ static int call_crda(const char *alpha2)
printk(KERN_INFO "cfg80211: Calling CRDA to update world "
"regulatory domain\n");
- /* query internal regulatory database (if it exists) */
- reg_regdb_query(alpha2);
-
country_env[8] = alpha2[0];
country_env[9] = alpha2[1];
@@ -506,205 +453,6 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
#undef ONE_GHZ_IN_KHZ
}
-/*
- * This is a work around for sanity checking ieee80211_channel_to_frequency()'s
- * work. ieee80211_channel_to_frequency() can for example currently provide a
- * 2 GHz channel when in fact a 5 GHz channel was desired. An example would be
- * an AP providing channel 8 on a country IE triplet when it sent this on the
- * 5 GHz band, that channel is designed to be channel 8 on 5 GHz, not a 2 GHz
- * channel.
- *
- * This can be removed once ieee80211_channel_to_frequency() takes in a band.
- */
-static bool chan_in_band(int chan, enum ieee80211_band band)
-{
- int center_freq = ieee80211_channel_to_frequency(chan);
-
- switch (band) {
- case IEEE80211_BAND_2GHZ:
- if (center_freq <= 2484)
- return true;
- return false;
- case IEEE80211_BAND_5GHZ:
- if (center_freq >= 5005)
- return true;
- return false;
- default:
- return false;
- }
-}
-
-/*
- * Some APs may send a country IE triplet for each channel they
- * support and while this is completely overkill and silly we still
- * need to support it. We avoid making a single rule for each channel
- * though and to help us with this we use this helper to find the
- * actual subband end channel. These type of country IE triplet
- * scenerios are handled then, all yielding two regulaotry rules from
- * parsing a country IE:
- *
- * [1]
- * [2]
- * [36]
- * [40]
- *
- * [1]
- * [2-4]
- * [5-12]
- * [36]
- * [40-44]
- *
- * [1-4]
- * [5-7]
- * [36-44]
- * [48-64]
- *
- * [36-36]
- * [40-40]
- * [44-44]
- * [48-48]
- * [52-52]
- * [56-56]
- * [60-60]
- * [64-64]
- * [100-100]
- * [104-104]
- * [108-108]
- * [112-112]
- * [116-116]
- * [120-120]
- * [124-124]
- * [128-128]
- * [132-132]
- * [136-136]
- * [140-140]
- *
- * Returns 0 if the IE has been found to be invalid in the middle
- * somewhere.
- */
-static int max_subband_chan(enum ieee80211_band band,
- int orig_cur_chan,
- int orig_end_channel,
- s8 orig_max_power,
- u8 **country_ie,
- u8 *country_ie_len)
-{
- u8 *triplets_start = *country_ie;
- u8 len_at_triplet = *country_ie_len;
- int end_subband_chan = orig_end_channel;
-
- /*
- * We'll deal with padding for the caller unless
- * its not immediate and we don't process any channels
- */
- if (*country_ie_len == 1) {
- *country_ie += 1;
- *country_ie_len -= 1;
- return orig_end_channel;
- }
-
- /* Move to the next triplet and then start search */
- *country_ie += 3;
- *country_ie_len -= 3;
-
- if (!chan_in_band(orig_cur_chan, band))
- return 0;
-
- while (*country_ie_len >= 3) {
- int end_channel = 0;
- struct ieee80211_country_ie_triplet *triplet =
- (struct ieee80211_country_ie_triplet *) *country_ie;
- int cur_channel = 0, next_expected_chan;
-
- /* means last triplet is completely unrelated to this one */
- if (triplet->ext.reg_extension_id >=
- IEEE80211_COUNTRY_EXTENSION_ID) {
- *country_ie -= 3;
- *country_ie_len += 3;
- break;
- }
-
- if (triplet->chans.first_channel == 0) {
- *country_ie += 1;
- *country_ie_len -= 1;
- if (*country_ie_len != 0)
- return 0;
- break;
- }
-
- if (triplet->chans.num_channels == 0)
- return 0;
-
- /* Monitonically increasing channel order */
- if (triplet->chans.first_channel <= end_subband_chan)
- return 0;
-
- if (!chan_in_band(triplet->chans.first_channel, band))
- return 0;
-
- /* 2 GHz */
- if (triplet->chans.first_channel <= 14) {
- end_channel = triplet->chans.first_channel +
- triplet->chans.num_channels - 1;
- }
- else {
- end_channel = triplet->chans.first_channel +
- (4 * (triplet->chans.num_channels - 1));
- }
-
- if (!chan_in_band(end_channel, band))
- return 0;
-
- if (orig_max_power != triplet->chans.max_power) {
- *country_ie -= 3;
- *country_ie_len += 3;
- break;
- }
-
- cur_channel = triplet->chans.first_channel;
-
- /* The key is finding the right next expected channel */
- if (band == IEEE80211_BAND_2GHZ)
- next_expected_chan = end_subband_chan + 1;
- else
- next_expected_chan = end_subband_chan + 4;
-
- if (cur_channel != next_expected_chan) {
- *country_ie -= 3;
- *country_ie_len += 3;
- break;
- }
-
- end_subband_chan = end_channel;
-
- /* Move to the next one */
- *country_ie += 3;
- *country_ie_len -= 3;
-
- /*
- * Padding needs to be dealt with if we processed
- * some channels.
- */
- if (*country_ie_len == 1) {
- *country_ie += 1;
- *country_ie_len -= 1;
- break;
- }
-
- /* If seen, the IE is invalid */
- if (*country_ie_len == 2)
- return 0;
- }
-
- if (end_subband_chan == orig_end_channel) {
- *country_ie = triplets_start;
- *country_ie_len = len_at_triplet;
- return orig_end_channel;
- }
-
- return end_subband_chan;
-}
-
/*
* Converts a country IE to a regulatory domain. A regulatory domain
* structure has a lot of information which the IE doesn't yet have,
@@ -712,7 +460,6 @@ static int max_subband_chan(enum ieee80211_band band,
* with our userspace regulatory agent to get lower bounds.
*/
static struct ieee80211_regdomain *country_ie_2_rd(
- enum ieee80211_band band,
u8 *country_ie,
u8 country_ie_len,
u32 *checksum)
@@ -774,29 +521,10 @@ static struct ieee80211_regdomain *country_ie_2_rd(
continue;
}
- /*
- * APs can add padding to make length divisible
- * by two, required by the spec.
- */
- if (triplet->chans.first_channel == 0) {
- country_ie++;
- country_ie_len--;
- /* This is expected to be at the very end only */
- if (country_ie_len != 0)
- return NULL;
- break;
- }
-
- if (triplet->chans.num_channels == 0)
- return NULL;
-
- if (!chan_in_band(triplet->chans.first_channel, band))
- return NULL;
-
/* 2 GHz */
- if (band == IEEE80211_BAND_2GHZ)
+ if (triplet->chans.first_channel <= 14)
end_channel = triplet->chans.first_channel +
- triplet->chans.num_channels - 1;
+ triplet->chans.num_channels;
else
/*
* 5 GHz -- For example in country IEs if the first
@@ -811,24 +539,6 @@ static struct ieee80211_regdomain *country_ie_2_rd(
(4 * (triplet->chans.num_channels - 1));
cur_channel = triplet->chans.first_channel;
-
- /*
- * Enhancement for APs that send a triplet for every channel
- * or for whatever reason sends triplets with multiple channels
- * separated when in fact they should be together.
- */
- end_channel = max_subband_chan(band,
- cur_channel,
- end_channel,
- triplet->chans.max_power,
- &country_ie,
- &country_ie_len);
- if (!end_channel)
- return NULL;
-
- if (!chan_in_band(end_channel, band))
- return NULL;
-
cur_sub_max_channel = end_channel;
/* Basic sanity check */
@@ -859,13 +569,10 @@ static struct ieee80211_regdomain *country_ie_2_rd(
last_sub_max_channel = cur_sub_max_channel;
+ country_ie += 3;
+ country_ie_len -= 3;
num_rules++;
- if (country_ie_len >= 3) {
- country_ie += 3;
- country_ie_len -= 3;
- }
-
/*
* Note: this is not a IEEE requirement but
* simply a memory requirement
@@ -908,12 +615,6 @@ static struct ieee80211_regdomain *country_ie_2_rd(
continue;
}
- if (triplet->chans.first_channel == 0) {
- country_ie++;
- country_ie_len--;
- break;
- }
-
reg_rule = &rd->reg_rules[i];
freq_range = ®_rule->freq_range;
power_rule = ®_rule->power_rule;
@@ -921,20 +622,13 @@ static struct ieee80211_regdomain *country_ie_2_rd(
reg_rule->flags = flags;
/* 2 GHz */
- if (band == IEEE80211_BAND_2GHZ)
+ if (triplet->chans.first_channel <= 14)
end_channel = triplet->chans.first_channel +
- triplet->chans.num_channels -1;
+ triplet->chans.num_channels;
else
end_channel = triplet->chans.first_channel +
(4 * (triplet->chans.num_channels - 1));
- end_channel = max_subband_chan(band,
- triplet->chans.first_channel,
- end_channel,
- triplet->chans.max_power,
- &country_ie,
- &country_ie_len);
-
/*
* The +10 is since the regulatory domain expects
* the actual band edge, not the center of freq for
@@ -955,15 +649,12 @@ static struct ieee80211_regdomain *country_ie_2_rd(
*/
freq_range->max_bandwidth_khz = MHZ_TO_KHZ(40);
power_rule->max_antenna_gain = DBI_TO_MBI(100);
- power_rule->max_eirp = DBM_TO_MBM(triplet->chans.max_power);
+ power_rule->max_eirp = DBM_TO_MBM(100);
+ country_ie += 3;
+ country_ie_len -= 3;
i++;
- if (country_ie_len >= 3) {
- country_ie += 3;
- country_ie_len -= 3;
- }
-
BUG_ON(i > NL80211_MAX_SUPP_REG_RULES);
}
@@ -1259,21 +950,25 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
if (r == -ERANGE &&
last_request->initiator ==
NL80211_REGDOM_SET_BY_COUNTRY_IE) {
- REG_DBG_PRINT("cfg80211: Leaving channel %d MHz "
+#ifdef CONFIG_CFG80211_REG_DEBUG
+ printk(KERN_DEBUG "cfg80211: Leaving channel %d MHz "
"intact on %s - no rule found in band on "
"Country IE\n",
- chan->center_freq, wiphy_name(wiphy));
+ chan->center_freq, wiphy_name(wiphy));
+#endif
} else {
/*
* In this case we know the country IE has at least one reg rule
* for the band so we respect its band definitions
*/
+#ifdef CONFIG_CFG80211_REG_DEBUG
if (last_request->initiator ==
NL80211_REGDOM_SET_BY_COUNTRY_IE)
- REG_DBG_PRINT("cfg80211: Disabling "
+ printk(KERN_DEBUG "cfg80211: Disabling "
"channel %d MHz on %s due to "
"Country IE\n",
chan->center_freq, wiphy_name(wiphy));
+#endif
flags |= IEEE80211_CHAN_DISABLED;
chan->flags = flags;
}
@@ -1647,6 +1342,30 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
}
EXPORT_SYMBOL(wiphy_apply_custom_regulatory);
+static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd,
+ const struct ieee80211_regdomain *src_regd)
+{
+ struct ieee80211_regdomain *regd;
+ int size_of_regd = 0;
+ unsigned int i;
+
+ size_of_regd = sizeof(struct ieee80211_regdomain) +
+ ((src_regd->n_reg_rules + 1) * sizeof(struct ieee80211_reg_rule));
+
+ regd = kzalloc(size_of_regd, GFP_KERNEL);
+ if (!regd)
+ return -ENOMEM;
+
+ memcpy(regd, src_regd, sizeof(struct ieee80211_regdomain));
+
+ for (i = 0; i < src_regd->n_reg_rules; i++)
+ memcpy(®d->reg_rules[i], &src_regd->reg_rules[i],
+ sizeof(struct ieee80211_reg_rule));
+
+ *dst_regd = regd;
+ return 0;
+}
+
/*
* Return value which can be used by ignore_request() to indicate
* it has been determined we should intersect two regulatory domains
@@ -1668,7 +1387,7 @@ static int ignore_request(struct wiphy *wiphy,
switch (pending_request->initiator) {
case NL80211_REGDOM_SET_BY_CORE:
- return 0;
+ return -EINVAL;
case NL80211_REGDOM_SET_BY_COUNTRY_IE:
last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
@@ -1699,6 +1418,8 @@ static int ignore_request(struct wiphy *wiphy,
return REG_INTERSECT;
case NL80211_REGDOM_SET_BY_DRIVER:
if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) {
+ if (is_old_static_regdom(cfg80211_regdomain))
+ return 0;
if (regdom_changes(pending_request->alpha2))
return 0;
return -EALREADY;
@@ -1735,7 +1456,8 @@ static int ignore_request(struct wiphy *wiphy,
return -EAGAIN;
}
- if (!regdom_changes(pending_request->alpha2))
+ if (!is_old_static_regdom(cfg80211_regdomain) &&
+ !regdom_changes(pending_request->alpha2))
return -EALREADY;
return 0;
@@ -1807,11 +1529,6 @@ static int __regulatory_hint(struct wiphy *wiphy,
pending_request = NULL;
- if (last_request->initiator == NL80211_REGDOM_SET_BY_USER) {
- user_alpha2[0] = last_request->alpha2[0];
- user_alpha2[1] = last_request->alpha2[1];
- }
-
/* When r == REG_INTERSECT we do need to call CRDA */
if (r < 0) {
/*
@@ -1931,16 +1648,12 @@ static void queue_regulatory_request(struct regulatory_request *request)
schedule_work(®_work);
}
-/*
- * Core regulatory hint -- happens during cfg80211_init()
- * and when we restore regulatory settings.
- */
+/* Core regulatory hint -- happens once during cfg80211_init() */
static int regulatory_hint_core(const char *alpha2)
{
struct regulatory_request *request;
- kfree(last_request);
- last_request = NULL;
+ BUG_ON(last_request);
request = kzalloc(sizeof(struct regulatory_request),
GFP_KERNEL);
@@ -1951,12 +1664,14 @@ static int regulatory_hint_core(const char *alpha2)
request->alpha2[1] = alpha2[1];
request->initiator = NL80211_REGDOM_SET_BY_CORE;
+ queue_regulatory_request(request);
+
/*
* This ensures last_request is populated once modules
* come swinging in and calling regulatory hints and
* wiphy_apply_custom_regulatory().
*/
- reg_process_hint(request);
+ flush_scheduled_work();
return 0;
}
@@ -2043,9 +1758,8 @@ static bool reg_same_country_ie_hint(struct wiphy *wiphy,
* therefore cannot iterate over the rdev list here.
*/
void regulatory_hint_11d(struct wiphy *wiphy,
- enum ieee80211_band band,
- u8 *country_ie,
- u8 country_ie_len)
+ u8 *country_ie,
+ u8 country_ie_len)
{
struct ieee80211_regdomain *rd = NULL;
char alpha2[2];
@@ -2091,11 +1805,9 @@ void regulatory_hint_11d(struct wiphy *wiphy,
wiphy_idx_valid(last_request->wiphy_idx)))
goto out;
- rd = country_ie_2_rd(band, country_ie, country_ie_len, &checksum);
- if (!rd) {
- REG_DBG_PRINT("cfg80211: Ignoring bogus country IE\n");
+ rd = country_ie_2_rd(country_ie, country_ie_len, &checksum);
+ if (!rd)
goto out;
- }
/*
* This will not happen right now but we leave it here for the
@@ -2138,123 +1850,6 @@ void regulatory_hint_11d(struct wiphy *wiphy,
mutex_unlock(®_mutex);
}
-static void restore_alpha2(char *alpha2, bool reset_user)
-{
- /* indicates there is no alpha2 to consider for restoration */
- alpha2[0] = '9';
- alpha2[1] = '7';
-
- /* The user setting has precedence over the module parameter */
- if (is_user_regdom_saved()) {
- /* Unless we're asked to ignore it and reset it */
- if (reset_user) {
- REG_DBG_PRINT("cfg80211: Restoring regulatory settings "
- "including user preference\n");
- user_alpha2[0] = '9';
- user_alpha2[1] = '7';
-
- /*
- * If we're ignoring user settings, we still need to
- * check the module parameter to ensure we put things
- * back as they were for a full restore.
- */
- if (!is_world_regdom(ieee80211_regdom)) {
- REG_DBG_PRINT("cfg80211: Keeping preference on "
- "module parameter ieee80211_regdom: %c%c\n",
- ieee80211_regdom[0],
- ieee80211_regdom[1]);
- alpha2[0] = ieee80211_regdom[0];
- alpha2[1] = ieee80211_regdom[1];
- }
- } else {
- REG_DBG_PRINT("cfg80211: Restoring regulatory settings "
- "while preserving user preference for: %c%c\n",
- user_alpha2[0],
- user_alpha2[1]);
- alpha2[0] = user_alpha2[0];
- alpha2[1] = user_alpha2[1];
- }
- } else if (!is_world_regdom(ieee80211_regdom)) {
- REG_DBG_PRINT("cfg80211: Keeping preference on "
- "module parameter ieee80211_regdom: %c%c\n",
- ieee80211_regdom[0],
- ieee80211_regdom[1]);
- alpha2[0] = ieee80211_regdom[0];
- alpha2[1] = ieee80211_regdom[1];
- } else
- REG_DBG_PRINT("cfg80211: Restoring regulatory settings\n");
-}
-
-/*
- * Restoring regulatory settings involves ingoring any
- * possibly stale country IE information and user regulatory
- * settings if so desired, this includes any beacon hints
- * learned as we could have traveled outside to another country
- * after disconnection. To restore regulatory settings we do
- * exactly what we did at bootup:
- *
- * - send a core regulatory hint
- * - send a user regulatory hint if applicable
- *
- * Device drivers that send a regulatory hint for a specific country
- * keep their own regulatory domain on wiphy->regd so that does does
- * not need to be remembered.
- */
-static void restore_regulatory_settings(bool reset_user)
-{
- char alpha2[2];
- struct reg_beacon *reg_beacon, *btmp;
-
- mutex_lock(&cfg80211_mutex);
- mutex_lock(®_mutex);
-
- reset_regdomains();
- restore_alpha2(alpha2, reset_user);
-
- /* Clear beacon hints */
- spin_lock_bh(®_pending_beacons_lock);
- if (!list_empty(®_pending_beacons)) {
- list_for_each_entry_safe(reg_beacon, btmp,
- ®_pending_beacons, list) {
- list_del(®_beacon->list);
- kfree(reg_beacon);
- }
- }
- spin_unlock_bh(®_pending_beacons_lock);
-
- if (!list_empty(®_beacon_list)) {
- list_for_each_entry_safe(reg_beacon, btmp,
- ®_beacon_list, list) {
- list_del(®_beacon->list);
- kfree(reg_beacon);
- }
- }
-
- /* First restore to the basic regulatory settings */
- cfg80211_regdomain = cfg80211_world_regdom;
-
- mutex_unlock(®_mutex);
- mutex_unlock(&cfg80211_mutex);
-
- regulatory_hint_core(cfg80211_regdomain->alpha2);
-
- /*
- * This restores the ieee80211_regdom module parameter
- * preference or the last user requested regulatory
- * settings, user regulatory settings takes precedence.
- */
- if (is_an_alpha2(alpha2))
- regulatory_hint_user(user_alpha2);
-}
-
-
-void regulatory_hint_disconnect(void)
-{
- REG_DBG_PRINT("cfg80211: All devices are disconnected, going to "
- "restore regulatory settings\n");
- restore_regulatory_settings(false);
-}
-
static bool freq_is_chan_12_13_14(u16 freq)
{
if (freq == ieee80211_channel_to_frequency(12) ||
@@ -2280,12 +1875,13 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy,
if (!reg_beacon)
return -ENOMEM;
- REG_DBG_PRINT("cfg80211: Found new beacon on "
- "frequency: %d MHz (Ch %d) on %s\n",
- beacon_chan->center_freq,
- ieee80211_frequency_to_channel(beacon_chan->center_freq),
- wiphy_name(wiphy));
-
+#ifdef CONFIG_CFG80211_REG_DEBUG
+ printk(KERN_DEBUG "cfg80211: Found new beacon on "
+ "frequency: %d MHz (Ch %d) on %s\n",
+ beacon_chan->center_freq,
+ ieee80211_frequency_to_channel(beacon_chan->center_freq),
+ wiphy_name(wiphy));
+#endif
memcpy(®_beacon->chan, beacon_chan,
sizeof(struct ieee80211_channel));
@@ -2443,7 +2039,8 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
* If someone else asked us to change the rd lets only bother
* checking if the alpha2 changes if CRDA was already called
*/
- if (!regdom_changes(rd->alpha2))
+ if (!is_old_static_regdom(cfg80211_regdomain) &&
+ !regdom_changes(rd->alpha2))
return -EINVAL;
}
@@ -2642,11 +2239,15 @@ int regulatory_init(void)
spin_lock_init(®_requests_lock);
spin_lock_init(®_pending_beacons_lock);
- cfg80211_regdomain = cfg80211_world_regdom;
+#ifdef CONFIG_WIRELESS_OLD_REGULATORY
+ cfg80211_regdomain = static_regdom(ieee80211_regdom);
- user_alpha2[0] = '9';
- user_alpha2[1] = '7';
+ printk(KERN_INFO "cfg80211: Using static regulatory domain info\n");
+ print_regdomain_info(cfg80211_regdomain);
+#else
+ cfg80211_regdomain = cfg80211_world_regdom;
+#endif
/* We always try to get an update for the static regdomain */
err = regulatory_hint_core(cfg80211_regdomain->alpha2);
if (err) {
diff --git a/trunk/net/wireless/reg.h b/trunk/net/wireless/reg.h
index b26224a9f3bc..3362c7c069b2 100644
--- a/trunk/net/wireless/reg.h
+++ b/trunk/net/wireless/reg.h
@@ -41,44 +41,15 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy,
* regulatory_hint_11d - hints a country IE as a regulatory domain
* @wiphy: the wireless device giving the hint (used only for reporting
* conflicts)
- * @band: the band on which the country IE was received on. This determines
- * the band we'll process the country IE channel triplets for.
* @country_ie: pointer to the country IE
* @country_ie_len: length of the country IE
*
* We will intersect the rd with the what CRDA tells us should apply
* for the alpha2 this country IE belongs to, this prevents APs from
* sending us incorrect or outdated information against a country.
- *
- * The AP is expected to provide Country IE channel triplets for the
- * band it is on. It is technically possible for APs to send channel
- * country IE triplets even for channels outside of the band they are
- * in but for that they would have to use the regulatory extension
- * in combination with a triplet but this behaviour is currently
- * not observed. For this reason if a triplet is seen with channel
- * information for a band the BSS is not present in it will be ignored.
*/
void regulatory_hint_11d(struct wiphy *wiphy,
- enum ieee80211_band band,
u8 *country_ie,
u8 country_ie_len);
-/**
- * regulatory_hint_disconnect - informs all devices have been disconneted
- *
- * Regulotory rules can be enhanced further upon scanning and upon
- * connection to an AP. These rules become stale if we disconnect
- * and go to another country, whether or not we suspend and resume.
- * If we suspend, go to another country and resume we'll automatically
- * get disconnected shortly after resuming and things will be reset as well.
- * This routine is a helper to restore regulatory settings to how they were
- * prior to our first connect attempt. This includes ignoring country IE and
- * beacon regulatory hints. The ieee80211_regdom module parameter will always
- * be respected but if a user had set the regulatory domain that will take
- * precedence.
- *
- * Must be called from process context.
- */
-void regulatory_hint_disconnect(void);
-
#endif /* __NET_WIRELESS_REG_H */
diff --git a/trunk/net/wireless/regdb.h b/trunk/net/wireless/regdb.h
deleted file mode 100644
index 818222c92513..000000000000
--- a/trunk/net/wireless/regdb.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __REGDB_H__
-#define __REGDB_H__
-
-extern const struct ieee80211_regdomain *reg_regdb[];
-extern int reg_regdb_size;
-
-#endif /* __REGDB_H__ */
diff --git a/trunk/net/wireless/scan.c b/trunk/net/wireless/scan.c
index 978cac3414b5..0c2cbbebca95 100644
--- a/trunk/net/wireless/scan.c
+++ b/trunk/net/wireless/scan.c
@@ -100,10 +100,8 @@ static void bss_release(struct kref *ref)
if (bss->pub.free_priv)
bss->pub.free_priv(&bss->pub);
- if (bss->beacon_ies_allocated)
- kfree(bss->pub.beacon_ies);
- if (bss->proberesp_ies_allocated)
- kfree(bss->pub.proberesp_ies);
+ if (bss->ies_allocated)
+ kfree(bss->pub.information_elements);
BUG_ON(atomic_read(&bss->hold));
@@ -143,9 +141,9 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
dev->bss_generation++;
}
-const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
+static u8 *find_ie(u8 num, u8 *ies, int len)
{
- while (len > 2 && ies[0] != eid) {
+ while (len > 2 && ies[0] != num) {
len -= ies[1] + 2;
ies += ies[1] + 2;
}
@@ -155,12 +153,11 @@ const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
return NULL;
return ies;
}
-EXPORT_SYMBOL(cfg80211_find_ie);
static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2)
{
- const u8 *ie1 = cfg80211_find_ie(num, ies1, len1);
- const u8 *ie2 = cfg80211_find_ie(num, ies2, len2);
+ const u8 *ie1 = find_ie(num, ies1, len1);
+ const u8 *ie2 = find_ie(num, ies2, len2);
int r;
if (!ie1 && !ie2)
@@ -186,9 +183,9 @@ static bool is_bss(struct cfg80211_bss *a,
if (!ssid)
return true;
- ssidie = cfg80211_find_ie(WLAN_EID_SSID,
- a->information_elements,
- a->len_information_elements);
+ ssidie = find_ie(WLAN_EID_SSID,
+ a->information_elements,
+ a->len_information_elements);
if (!ssidie)
return false;
if (ssidie[1] != ssid_len)
@@ -205,9 +202,9 @@ static bool is_mesh(struct cfg80211_bss *a,
if (!is_zero_ether_addr(a->bssid))
return false;
- ie = cfg80211_find_ie(WLAN_EID_MESH_ID,
- a->information_elements,
- a->len_information_elements);
+ ie = find_ie(WLAN_EID_MESH_ID,
+ a->information_elements,
+ a->len_information_elements);
if (!ie)
return false;
if (ie[1] != meshidlen)
@@ -215,9 +212,9 @@ static bool is_mesh(struct cfg80211_bss *a,
if (memcmp(ie + 2, meshid, meshidlen))
return false;
- ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
- a->information_elements,
- a->len_information_elements);
+ ie = find_ie(WLAN_EID_MESH_CONFIG,
+ a->information_elements,
+ a->len_information_elements);
if (!ie)
return false;
if (ie[1] != sizeof(struct ieee80211_meshconf_ie))
@@ -378,7 +375,8 @@ rb_find_bss(struct cfg80211_registered_device *dev,
static struct cfg80211_internal_bss *
cfg80211_bss_update(struct cfg80211_registered_device *dev,
- struct cfg80211_internal_bss *res)
+ struct cfg80211_internal_bss *res,
+ bool overwrite)
{
struct cfg80211_internal_bss *found = NULL;
const u8 *meshid, *meshcfg;
@@ -396,12 +394,11 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
if (is_zero_ether_addr(res->pub.bssid)) {
/* must be mesh, verify */
- meshid = cfg80211_find_ie(WLAN_EID_MESH_ID,
- res->pub.information_elements,
- res->pub.len_information_elements);
- meshcfg = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
- res->pub.information_elements,
- res->pub.len_information_elements);
+ meshid = find_ie(WLAN_EID_MESH_ID, res->pub.information_elements,
+ res->pub.len_information_elements);
+ meshcfg = find_ie(WLAN_EID_MESH_CONFIG,
+ res->pub.information_elements,
+ res->pub.len_information_elements);
if (!meshid || !meshcfg ||
meshcfg[1] != sizeof(struct ieee80211_meshconf_ie)) {
/* bogus mesh */
@@ -421,64 +418,28 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
found->pub.capability = res->pub.capability;
found->ts = res->ts;
- /* Update IEs */
- if (res->pub.proberesp_ies) {
+ /* overwrite IEs */
+ if (overwrite) {
size_t used = dev->wiphy.bss_priv_size + sizeof(*res);
- size_t ielen = res->pub.len_proberesp_ies;
-
- if (found->pub.proberesp_ies &&
- !found->proberesp_ies_allocated &&
- ksize(found) >= used + ielen) {
- memcpy(found->pub.proberesp_ies,
- res->pub.proberesp_ies, ielen);
- found->pub.len_proberesp_ies = ielen;
- } else {
- u8 *ies = found->pub.proberesp_ies;
-
- if (found->proberesp_ies_allocated)
- ies = krealloc(ies, ielen, GFP_ATOMIC);
- else
- ies = kmalloc(ielen, GFP_ATOMIC);
-
- if (ies) {
- memcpy(ies, res->pub.proberesp_ies,
- ielen);
- found->proberesp_ies_allocated = true;
- found->pub.proberesp_ies = ies;
- found->pub.len_proberesp_ies = ielen;
- }
- }
+ size_t ielen = res->pub.len_information_elements;
- /* Override possible earlier Beacon frame IEs */
- found->pub.information_elements =
- found->pub.proberesp_ies;
- found->pub.len_information_elements =
- found->pub.len_proberesp_ies;
- }
- if (res->pub.beacon_ies) {
- size_t used = dev->wiphy.bss_priv_size + sizeof(*res);
- size_t ielen = res->pub.len_beacon_ies;
-
- if (found->pub.beacon_ies &&
- !found->beacon_ies_allocated &&
- ksize(found) >= used + ielen) {
- memcpy(found->pub.beacon_ies,
- res->pub.beacon_ies, ielen);
- found->pub.len_beacon_ies = ielen;
+ if (!found->ies_allocated && ksize(found) >= used + ielen) {
+ memcpy(found->pub.information_elements,
+ res->pub.information_elements, ielen);
+ found->pub.len_information_elements = ielen;
} else {
- u8 *ies = found->pub.beacon_ies;
+ u8 *ies = found->pub.information_elements;
- if (found->beacon_ies_allocated)
+ if (found->ies_allocated)
ies = krealloc(ies, ielen, GFP_ATOMIC);
else
ies = kmalloc(ielen, GFP_ATOMIC);
if (ies) {
- memcpy(ies, res->pub.beacon_ies,
- ielen);
- found->beacon_ies_allocated = true;
- found->pub.beacon_ies = ies;
- found->pub.len_beacon_ies = ielen;
+ memcpy(ies, res->pub.information_elements, ielen);
+ found->ies_allocated = true;
+ found->pub.information_elements = ies;
+ found->pub.len_information_elements = ielen;
}
}
}
@@ -528,26 +489,14 @@ cfg80211_inform_bss(struct wiphy *wiphy,
res->pub.tsf = timestamp;
res->pub.beacon_interval = beacon_interval;
res->pub.capability = capability;
- /*
- * Since we do not know here whether the IEs are from a Beacon or Probe
- * Response frame, we need to pick one of the options and only use it
- * with the driver that does not provide the full Beacon/Probe Response
- * frame. Use Beacon frame pointer to avoid indicating that this should
- * override the information_elements pointer should we have received an
- * earlier indication of Probe Response data.
- *
- * The initial buffer for the IEs is allocated with the BSS entry and
- * is located after the private area.
- */
- res->pub.beacon_ies = (u8 *)res + sizeof(*res) + privsz;
- memcpy(res->pub.beacon_ies, ie, ielen);
- res->pub.len_beacon_ies = ielen;
- res->pub.information_elements = res->pub.beacon_ies;
- res->pub.len_information_elements = res->pub.len_beacon_ies;
+ /* point to after the private area */
+ res->pub.information_elements = (u8 *)res + sizeof(*res) + privsz;
+ memcpy(res->pub.information_elements, ie, ielen);
+ res->pub.len_information_elements = ielen;
kref_init(&res->ref);
- res = cfg80211_bss_update(wiphy_to_dev(wiphy), res);
+ res = cfg80211_bss_update(wiphy_to_dev(wiphy), res, 0);
if (!res)
return NULL;
@@ -568,6 +517,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
struct cfg80211_internal_bss *res;
size_t ielen = len - offsetof(struct ieee80211_mgmt,
u.probe_resp.variable);
+ bool overwrite;
size_t privsz = wiphy->bss_priv_size;
if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC &&
@@ -588,28 +538,16 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
res->pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
res->pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
res->pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
- /*
- * The initial buffer for the IEs is allocated with the BSS entry and
- * is located after the private area.
- */
- if (ieee80211_is_probe_resp(mgmt->frame_control)) {
- res->pub.proberesp_ies = (u8 *) res + sizeof(*res) + privsz;
- memcpy(res->pub.proberesp_ies, mgmt->u.probe_resp.variable,
- ielen);
- res->pub.len_proberesp_ies = ielen;
- res->pub.information_elements = res->pub.proberesp_ies;
- res->pub.len_information_elements = res->pub.len_proberesp_ies;
- } else {
- res->pub.beacon_ies = (u8 *) res + sizeof(*res) + privsz;
- memcpy(res->pub.beacon_ies, mgmt->u.beacon.variable, ielen);
- res->pub.len_beacon_ies = ielen;
- res->pub.information_elements = res->pub.beacon_ies;
- res->pub.len_information_elements = res->pub.len_beacon_ies;
- }
+ /* point to after the private area */
+ res->pub.information_elements = (u8 *)res + sizeof(*res) + privsz;
+ memcpy(res->pub.information_elements, mgmt->u.probe_resp.variable, ielen);
+ res->pub.len_information_elements = ielen;
kref_init(&res->ref);
- res = cfg80211_bss_update(wiphy_to_dev(wiphy), res);
+ overwrite = ieee80211_is_probe_resp(mgmt->frame_control);
+
+ res = cfg80211_bss_update(wiphy_to_dev(wiphy), res, overwrite);
if (!res)
return NULL;
diff --git a/trunk/net/wireless/sme.c b/trunk/net/wireless/sme.c
index 17fde0da1b08..dc0fc4989d54 100644
--- a/trunk/net/wireless/sme.c
+++ b/trunk/net/wireless/sme.c
@@ -34,44 +34,6 @@ struct cfg80211_conn {
bool auto_auth, prev_bssid_valid;
};
-bool cfg80211_is_all_idle(void)
-{
- struct cfg80211_registered_device *rdev;
- struct wireless_dev *wdev;
- bool is_all_idle = true;
-
- mutex_lock(&cfg80211_mutex);
-
- /*
- * All devices must be idle as otherwise if you are actively
- * scanning some new beacon hints could be learned and would
- * count as new regulatory hints.
- */
- list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
- cfg80211_lock_rdev(rdev);
- list_for_each_entry(wdev, &rdev->netdev_list, list) {
- wdev_lock(wdev);
- if (wdev->sme_state != CFG80211_SME_IDLE)
- is_all_idle = false;
- wdev_unlock(wdev);
- }
- cfg80211_unlock_rdev(rdev);
- }
-
- mutex_unlock(&cfg80211_mutex);
-
- return is_all_idle;
-}
-
-static void disconnect_work(struct work_struct *work)
-{
- if (!cfg80211_is_all_idle())
- return;
-
- regulatory_hint_disconnect();
-}
-
-static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
static int cfg80211_conn_scan(struct wireless_dev *wdev)
{
@@ -492,7 +454,6 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
* - and country_ie[1] which is the IE length
*/
regulatory_hint_11d(wdev->wiphy,
- bss->channel->band,
country_ie + 2,
country_ie[1]);
}
@@ -696,8 +657,6 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
wdev->wext.connect.ssid_len = 0;
#endif
-
- schedule_work(&cfg80211_disconnect_work);
}
void cfg80211_disconnected(struct net_device *dev, u16 reason,
diff --git a/trunk/net/wireless/sysfs.c b/trunk/net/wireless/sysfs.c
index 9f2cef3e0ca0..efe3c5c92b2d 100644
--- a/trunk/net/wireless/sysfs.c
+++ b/trunk/net/wireless/sysfs.c
@@ -33,30 +33,10 @@ static ssize_t name ## _show(struct device *dev, \
SHOW_FMT(index, "%d", wiphy_idx);
SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);
-SHOW_FMT(address_mask, "%pM", wiphy.addr_mask);
-
-static ssize_t addresses_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy;
- char *start = buf;
- int i;
-
- if (!wiphy->addresses)
- return sprintf(buf, "%pM\n", wiphy->perm_addr);
-
- for (i = 0; i < wiphy->n_addresses; i++)
- buf += sprintf(buf, "%pM\n", &wiphy->addresses[i].addr);
-
- return buf - start;
-}
static struct device_attribute ieee80211_dev_attrs[] = {
__ATTR_RO(index),
__ATTR_RO(macaddress),
- __ATTR_RO(address_mask),
- __ATTR_RO(addresses),
{}
};
diff --git a/trunk/net/wireless/util.c b/trunk/net/wireless/util.c
index be2ab8c59e3a..59361fdcb5d0 100644
--- a/trunk/net/wireless/util.c
+++ b/trunk/net/wireless/util.c
@@ -227,11 +227,8 @@ unsigned int ieee80211_hdrlen(__le16 fc)
if (ieee80211_is_data(fc)) {
if (ieee80211_has_a4(fc))
hdrlen = 30;
- if (ieee80211_is_data_qos(fc)) {
+ if (ieee80211_is_data_qos(fc))
hdrlen += IEEE80211_QOS_CTL_LEN;
- if (ieee80211_has_order(fc))
- hdrlen += IEEE80211_HT_CTL_LEN;
- }
goto out;
}
@@ -288,7 +285,7 @@ static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
}
}
-int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
+int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr,
enum nl80211_iftype iftype)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -386,7 +383,7 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
}
EXPORT_SYMBOL(ieee80211_data_to_8023);
-int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
+int ieee80211_data_from_8023(struct sk_buff *skb, u8 *addr,
enum nl80211_iftype iftype, u8 *bssid, bool qos)
{
struct ieee80211_hdr hdr;
@@ -500,101 +497,6 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
}
EXPORT_SYMBOL(ieee80211_data_from_8023);
-
-void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
- const u8 *addr, enum nl80211_iftype iftype,
- const unsigned int extra_headroom)
-{
- struct sk_buff *frame = NULL;
- u16 ethertype;
- u8 *payload;
- const struct ethhdr *eth;
- int remaining, err;
- u8 dst[ETH_ALEN], src[ETH_ALEN];
-
- err = ieee80211_data_to_8023(skb, addr, iftype);
- if (err)
- goto out;
-
- /* skip the wrapping header */
- eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr));
- if (!eth)
- goto out;
-
- while (skb != frame) {
- u8 padding;
- __be16 len = eth->h_proto;
- unsigned int subframe_len = sizeof(struct ethhdr) + ntohs(len);
-
- remaining = skb->len;
- memcpy(dst, eth->h_dest, ETH_ALEN);
- memcpy(src, eth->h_source, ETH_ALEN);
-
- padding = (4 - subframe_len) & 0x3;
- /* the last MSDU has no padding */
- if (subframe_len > remaining)
- goto purge;
-
- skb_pull(skb, sizeof(struct ethhdr));
- /* reuse skb for the last subframe */
- if (remaining <= subframe_len + padding)
- frame = skb;
- else {
- unsigned int hlen = ALIGN(extra_headroom, 4);
- /*
- * Allocate and reserve two bytes more for payload
- * alignment since sizeof(struct ethhdr) is 14.
- */
- frame = dev_alloc_skb(hlen + subframe_len + 2);
- if (!frame)
- goto purge;
-
- skb_reserve(frame, hlen + sizeof(struct ethhdr) + 2);
- memcpy(skb_put(frame, ntohs(len)), skb->data,
- ntohs(len));
-
- eth = (struct ethhdr *)skb_pull(skb, ntohs(len) +
- padding);
- if (!eth) {
- dev_kfree_skb(frame);
- goto purge;
- }
- }
-
- skb_reset_network_header(frame);
- frame->dev = skb->dev;
- frame->priority = skb->priority;
-
- payload = frame->data;
- ethertype = (payload[6] << 8) | payload[7];
-
- if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&
- ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
- compare_ether_addr(payload,
- bridge_tunnel_header) == 0)) {
- /* remove RFC1042 or Bridge-Tunnel
- * encapsulation and replace EtherType */
- skb_pull(frame, 6);
- memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
- memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
- } else {
- memcpy(skb_push(frame, sizeof(__be16)), &len,
- sizeof(__be16));
- memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
- memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
- }
- __skb_queue_tail(list, frame);
- }
-
- return;
-
- purge:
- __skb_queue_purge(list);
- out:
- dev_kfree_skb(skb);
-}
-EXPORT_SYMBOL(ieee80211_amsdu_to_8023s);
-
/* Given a data frame determine the 802.1p/1d tag to use. */
unsigned int cfg80211_classify8021d(struct sk_buff *skb)
{
@@ -818,36 +720,3 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
return err;
}
-
-u16 cfg80211_calculate_bitrate(struct rate_info *rate)
-{
- int modulation, streams, bitrate;
-
- if (!(rate->flags & RATE_INFO_FLAGS_MCS))
- return rate->legacy;
-
- /* the formula below does only work for MCS values smaller than 32 */
- if (rate->mcs >= 32)
- return 0;
-
- modulation = rate->mcs & 7;
- streams = (rate->mcs >> 3) + 1;
-
- bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
- 13500000 : 6500000;
-
- if (modulation < 4)
- bitrate *= (modulation + 1);
- else if (modulation == 4)
- bitrate *= (modulation + 2);
- else
- bitrate *= (modulation + 3);
-
- bitrate *= streams;
-
- if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
- bitrate = (bitrate / 9) * 10;
-
- /* do NOT round down here */
- return (bitrate + 50000) / 100000;
-}
diff --git a/trunk/net/wireless/wext-compat.c b/trunk/net/wireless/wext-compat.c
index 9ab51838849e..54face3d4424 100644
--- a/trunk/net/wireless/wext-compat.c
+++ b/trunk/net/wireless/wext-compat.c
@@ -1099,8 +1099,8 @@ int cfg80211_wext_siwpower(struct net_device *dev,
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
- bool ps = wdev->ps;
- int timeout = wdev->ps_timeout;
+ bool ps = wdev->wext.ps;
+ int timeout = wdev->wext.ps_timeout;
int err;
if (wdev->iftype != NL80211_IFTYPE_STATION)
@@ -1133,8 +1133,8 @@ int cfg80211_wext_siwpower(struct net_device *dev,
if (err)
return err;
- wdev->ps = ps;
- wdev->ps_timeout = timeout;
+ wdev->wext.ps = ps;
+ wdev->wext.ps_timeout = timeout;
return 0;
@@ -1147,7 +1147,7 @@ int cfg80211_wext_giwpower(struct net_device *dev,
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
- wrq->disabled = !wdev->ps;
+ wrq->disabled = !wdev->wext.ps;
return 0;
}
@@ -1204,47 +1204,21 @@ int cfg80211_wext_siwrate(struct net_device *dev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
struct cfg80211_bitrate_mask mask;
- u32 fixed, maxrate;
- struct ieee80211_supported_band *sband;
- int band, ridx;
- bool match = false;
if (!rdev->ops->set_bitrate_mask)
return -EOPNOTSUPP;
- memset(&mask, 0, sizeof(mask));
- fixed = 0;
- maxrate = (u32)-1;
+ mask.fixed = 0;
+ mask.maxrate = 0;
if (rate->value < 0) {
/* nothing */
} else if (rate->fixed) {
- fixed = rate->value / 100000;
+ mask.fixed = rate->value / 1000; /* kbps */
} else {
- maxrate = rate->value / 100000;
+ mask.maxrate = rate->value / 1000; /* kbps */
}
- for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
- sband = wdev->wiphy->bands[band];
- if (sband == NULL)
- continue;
- for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
- struct ieee80211_rate *srate = &sband->bitrates[ridx];
- if (fixed == srate->bitrate) {
- mask.control[band].legacy = 1 << ridx;
- match = true;
- break;
- }
- if (srate->bitrate <= maxrate) {
- mask.control[band].legacy |= 1 << ridx;
- match = true;
- }
- }
- }
-
- if (!match)
- return -EINVAL;
-
return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask);
}
EXPORT_SYMBOL_GPL(cfg80211_wext_siwrate);
@@ -1283,7 +1257,10 @@ int cfg80211_wext_giwrate(struct net_device *dev,
if (!(sinfo.filled & STATION_INFO_TX_BITRATE))
return -EOPNOTSUPP;
- rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate);
+ rate->value = 0;
+
+ if (!(sinfo.txrate.flags & RATE_INFO_FLAGS_MCS))
+ rate->value = 100000 * sinfo.txrate.legacy;
return 0;
}