* [WT PATCH 6/6] mac80211: Tell user why beacons fail to parse.
From: greearb @ 2013-06-29 22:58 UTC (permalink / raw)
To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <1372546738-25827-1-git-send-email-greearb@candelatech.com>
From: Ben Greear <greearb@candelatech.com>
Should help better debug dodgy APs and such.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
net/mac80211/ieee80211_i.h | 2 +
net/mac80211/mlme.c | 4 +-
net/mac80211/scan.c | 6 +++
net/mac80211/util.c | 79 +++++++++++++++++++++++++++++++++++++++----
4 files changed, 81 insertions(+), 10 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f36f120..809c9a5 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -110,6 +110,7 @@ struct ieee80211_bss {
/* Keep track of what bits of information we have valid info for. */
u8 valid_data;
+ char corrupt_elems_msg[80];
};
/**
@@ -1258,6 +1259,7 @@ struct ieee802_11_elems {
/* whether a parse error occurred while retrieving these elements */
bool parse_error;
+ char parse_err_msg[80];
};
static inline struct ieee80211_local *hw_to_local(
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index ae31968..42edd6c 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -4341,8 +4341,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
corrupt_type = "beacon";
} else if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_PROBE_RESP)
corrupt_type = "probe response";
- sdata_info(sdata, "associating with AP with corrupt %s\n",
- corrupt_type);
+ sdata_info(sdata, "associating with AP with corrupt %s, reason: %s\n",
+ corrupt_type, bss->corrupt_elems_msg);
}
return 0;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 1b122a7..9dc9c98 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -86,6 +86,8 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
bss->device_ts_presp = rx_status->device_timestamp;
if (elems->parse_error) {
+ strncpy(bss->corrupt_elems_msg, elems->parse_err_msg,
+ sizeof(bss->corrupt_elems_msg));
if (beacon)
bss->corrupt_data |= IEEE80211_BSS_CORRUPT_BEACON;
else
@@ -95,6 +97,10 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_BEACON;
else
bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_PROBE_RESP;
+ if (!(bss->corrupt_data &
+ (IEEE80211_BSS_CORRUPT_BEACON |
+ IEEE80211_BSS_CORRUPT_PROBE_RESP)))
+ bss->corrupt_elems_msg[0] = 0;
}
/* save the ERP value so that it is available at association time */
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 2265445..7e6a4f3 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -692,6 +692,10 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
if (elen > left) {
elems->parse_error = true;
+ snprintf(elems->parse_err_msg,
+ sizeof(elems->parse_err_msg),
+ "elen: %hhu > left: %zu",
+ elen, left);
break;
}
@@ -731,6 +735,9 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
*/
if (test_bit(id, seen_elems)) {
elems->parse_error = true;
+ snprintf(elems->parse_err_msg,
+ sizeof(elems->parse_err_msg),
+ "seen id: %i already", id);
left -= elen;
pos += elen;
continue;
@@ -762,8 +769,14 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
if (elen >= sizeof(struct ieee80211_tim_ie)) {
elems->tim = (void *)pos;
elems->tim_len = elen;
- } else
+ } else {
elem_parse_failed = true;
+ snprintf(elems->parse_err_msg,
+ sizeof(elems->parse_err_msg),
+ "EID_TIM size wrong, elen: %hhu sizeof(tim_ie): %zu",
+ elen,
+ sizeof(struct ieee80211_tim_ie));
+ }
break;
case WLAN_EID_CHALLENGE:
elems->challenge = pos;
@@ -806,32 +819,61 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
case WLAN_EID_HT_CAPABILITY:
if (elen >= sizeof(struct ieee80211_ht_cap))
elems->ht_cap_elem = (void *)pos;
- else
+ else {
elem_parse_failed = true;
+ snprintf(elems->parse_err_msg,
+ sizeof(elems->parse_err_msg),
+ "HT_CAPAB size wrong, elen: %hhu sizeof(ht_cap): %zu",
+ elen,
+ sizeof(struct ieee80211_ht_cap));
+ }
break;
case WLAN_EID_HT_OPERATION:
if (elen >= sizeof(struct ieee80211_ht_operation))
elems->ht_operation = (void *)pos;
- else
+ else {
elem_parse_failed = true;
+ snprintf(elems->parse_err_msg,
+ sizeof(elems->parse_err_msg),
+ "HT_OPER size wrong, elen: %hhu sizeof(ht_oper): %zu",
+ elen,
+ sizeof(struct ieee80211_ht_operation));
+ }
break;
case WLAN_EID_VHT_CAPABILITY:
if (elen >= sizeof(struct ieee80211_vht_cap))
elems->vht_cap_elem = (void *)pos;
- else
+ else {
elem_parse_failed = true;
+ snprintf(elems->parse_err_msg,
+ sizeof(elems->parse_err_msg),
+ "EID_VHT size wrong, elen: %hhu sizeof(vht_cap): %zu",
+ elen,
+ sizeof(struct ieee80211_vht_cap));
+ }
break;
case WLAN_EID_VHT_OPERATION:
if (elen >= sizeof(struct ieee80211_vht_operation))
elems->vht_operation = (void *)pos;
- else
+ else {
elem_parse_failed = true;
+ snprintf(elems->parse_err_msg,
+ sizeof(elems->parse_err_msg),
+ "VHT_OPER size wrong, elen: %hhu sizeof(vht_oper): %zu",
+ elen,
+ sizeof(struct ieee80211_vht_operation));
+ }
break;
case WLAN_EID_OPMODE_NOTIF:
if (elen > 0)
elems->opmode_notif = pos;
- else
+ else {
elem_parse_failed = true;
+ snprintf(elems->parse_err_msg,
+ sizeof(elems->parse_err_msg),
+ "OPMODE_NOTIF has elen > 0: %hhu",
+ elen);
+ }
break;
case WLAN_EID_MESH_ID:
elems->mesh_id = pos;
@@ -840,8 +882,14 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
case WLAN_EID_MESH_CONFIG:
if (elen >= sizeof(struct ieee80211_meshconf_ie))
elems->mesh_config = (void *)pos;
- else
+ else {
elem_parse_failed = true;
+ snprintf(elems->parse_err_msg,
+ sizeof(elems->parse_err_msg),
+ "MESH_CONFIG size wrong, elen: %hhu sizeof(meshconf_ie): %zu",
+ elen,
+ sizeof(struct ieee80211_meshconf_ie));
+ }
break;
case WLAN_EID_PEER_MGMT:
elems->peering = pos;
@@ -866,12 +914,23 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
case WLAN_EID_RANN:
if (elen >= sizeof(struct ieee80211_rann_ie))
elems->rann = (void *)pos;
- else
+ else {
elem_parse_failed = true;
+ snprintf(elems->parse_err_msg,
+ sizeof(elems->parse_err_msg),
+ "EID_RANN size wrong, elen: %hhu sizeof(rann_ie): %zu",
+ elen,
+ sizeof(struct ieee80211_rann_ie));
+ }
break;
case WLAN_EID_CHANNEL_SWITCH:
if (elen != sizeof(struct ieee80211_channel_sw_ie)) {
elem_parse_failed = true;
+ snprintf(elems->parse_err_msg,
+ sizeof(elems->parse_err_msg),
+ "CH_SWITCH size wrong, elen: %hhu sizeof(sw_ie): %zu",
+ elen,
+ sizeof(struct ieee80211_channel_sw_ie));
break;
}
elems->ch_switch_ie = (void *)pos;
@@ -925,6 +984,10 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
case WLAN_EID_PWR_CONSTRAINT:
if (elen != 1) {
elem_parse_failed = true;
+ snprintf(elems->parse_err_msg,
+ sizeof(elems->parse_err_msg),
+ "PWR_CONSTRAINT size not 1, elen: %hhu",
+ elen);
break;
}
elems->pwr_constr_elem = pos;
--
1.7.3.4
^ permalink raw reply related
* [WT PATCH 4/6] mac80211: Add per-sdata station hash, and sdata hash.
From: greearb @ 2013-06-29 22:58 UTC (permalink / raw)
To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <1372546738-25827-1-git-send-email-greearb@candelatech.com>
From: Ben Greear <greearb@candelatech.com>
Add sdata hash (based on sdata->vif.addr) to local
structure.
Add sta_vhash (based on sta->sta.addr) to sdata struct.
Make STA_HASH give a better hash spread more often.
Use new hashes where we can. Might be able to completely
get rid of the local->sta_hash, but didn't want to try that
quite yet.
This significantly improves performance when using lots
of station VIFs connected to the same AP. It will likely
help other cases where the old hash logic failed to create
a decent spread.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
net/mac80211/ieee80211_i.h | 34 +++++++++++++++
net/mac80211/iface.c | 50 ++++++++++++++++++++++-
net/mac80211/rx.c | 16 +++++++
net/mac80211/sta_info.c | 97 +++++++++++++++++++++++++++++++++++---------
net/mac80211/sta_info.h | 18 +++++++-
net/mac80211/status.c | 6 +++
6 files changed, 198 insertions(+), 23 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 8412a30..f36f120 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -670,6 +670,10 @@ struct ieee80211_chanctx {
struct ieee80211_sub_if_data {
struct list_head list;
+ struct ieee80211_sub_if_data *hnext; /* sdata hash list pointer */
+
+ /* Protected by local->sta_mtx */
+ struct sta_info __rcu *sta_vhash[STA_HASH_SIZE]; /* By station addr */
struct wireless_dev wdev;
@@ -794,6 +798,34 @@ sdata_assert_lock(struct ieee80211_sub_if_data *sdata)
lockdep_assert_held(&sdata->wdev.mtx);
}
+static inline
+void for_each_sdata_type_check(struct ieee80211_local *local,
+ const u8 *addr,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sub_if_data *nxt)
+{
+}
+
+/* This deals with multiple sdata having same MAC */
+#define for_each_sdata(local, _addr, _sdata, nxt) \
+ for ( /* initialise loop */ \
+ _sdata = rcu_dereference(local->sdata_hash[STA_HASH(_addr)]), \
+ nxt = _sdata ? rcu_dereference(_sdata->hnext) : NULL; \
+ /* typecheck */ \
+ for_each_sdata_type_check(local, (_addr), _sdata, nxt), \
+ /* continue condition */ \
+ _sdata; \
+ /* advance loop */ \
+ _sdata = nxt, \
+ nxt = _sdata ? rcu_dereference(_sdata->hnext) : NULL \
+ ) \
+ /* compare address and run code only if it matches */ \
+ if (ether_addr_equal(_sdata->vif.addr, (_addr)))
+
+
+struct ieee80211_sub_if_data*
+ieee80211_find_sdata(struct ieee80211_local *local, const u8 *vif_addr);
+
static inline enum ieee80211_band
ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata)
{
@@ -1009,6 +1041,8 @@ struct ieee80211_local {
u32 wep_iv;
/* see iface.c */
+ /* Hash interfaces by VIF mac addr */
+ struct ieee80211_sub_if_data __rcu *sdata_hash[STA_HASH_SIZE];
struct list_head interfaces;
struct mutex iflist_mtx;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index a2a8250..1bf7996 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -208,6 +208,47 @@ static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr,
return ret;
}
+
+static void __ieee80211_if_add_hash(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_local *local = sdata->local;
+ int idx = STA_HASH(sdata->vif.addr);
+
+ lockdep_assert_held(&local->iflist_mtx);
+ sdata->hnext = local->sdata_hash[idx];
+ rcu_assign_pointer(local->sdata_hash[idx], sdata);
+}
+
+static int __ieee80211_if_remove_hash(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_sub_if_data *s;
+ struct ieee80211_local *local = sdata->local;
+ int idx = STA_HASH(sdata->vif.addr);
+
+ lockdep_assert_held(&local->iflist_mtx);
+ s = rcu_dereference_protected(local->sdata_hash[idx],
+ lockdep_is_held(&local->iflist_mtx));
+ if (!s)
+ return -ENOENT;
+
+ if (s == sdata) {
+ rcu_assign_pointer(local->sdata_hash[idx], s->hnext);
+ return 0;
+ }
+
+ while (rcu_access_pointer(s->hnext) &&
+ rcu_access_pointer(s->hnext) != sdata)
+ s = rcu_dereference_protected(s->hnext,
+ lockdep_is_held(&local->iflist_mtx));
+
+ if (rcu_access_pointer(s->hnext)) {
+ rcu_assign_pointer(s->hnext, sdata->hnext);
+ return 0;
+ }
+ return -ENOENT;
+}
+
+
static int ieee80211_change_mac(struct net_device *dev, void *addr)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -228,8 +269,13 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
ret = eth_mac_addr(dev, sa);
- if (ret == 0)
+ if (ret == 0) {
+ mutex_lock(&sdata->local->iflist_mtx);
+ __ieee80211_if_remove_hash(sdata);
memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
+ __ieee80211_if_add_hash(sdata);
+ mutex_unlock(&sdata->local->iflist_mtx);
+ }
return ret;
}
@@ -1688,6 +1734,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
mutex_lock(&local->iflist_mtx);
list_add_tail_rcu(&sdata->list, &local->interfaces);
+ __ieee80211_if_add_hash(sdata);
mutex_unlock(&local->iflist_mtx);
if (new_wdev)
@@ -1702,6 +1749,7 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata)
mutex_lock(&sdata->local->iflist_mtx);
list_del_rcu(&sdata->list);
+ __ieee80211_if_remove_hash(sdata);
mutex_unlock(&sdata->local->iflist_mtx);
synchronize_rcu();
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 23dbcfc..67efa59 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3172,6 +3172,21 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
if (ieee80211_is_data(fc)) {
prev_sta = NULL;
+ /* Check for Station VIFS by hashing on the destination MAC
+ * (ie, local sdata MAC). This changes 'promisc' behaviour,
+ * but not sure that is a bad thing.
+ */
+ if ((!is_multicast_ether_addr(hdr->addr1)) &&
+ (local->monitors == 0) && (local->cooked_mntrs == 0)) {
+ sta = sta_info_get_by_vif(local, hdr->addr1,
+ hdr->addr2);
+ if (sta) {
+ rx.sta = sta;
+ rx.sdata = sta->sdata;
+ goto rx_and_done;
+ }
+ }
+
for_each_sta_info(local, hdr->addr2, sta, tmp) {
if (!prev_sta) {
prev_sta = sta;
@@ -3189,6 +3204,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
rx.sta = prev_sta;
rx.sdata = prev_sta->sdata;
+rx_and_done:
if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
return;
goto out;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index aeb967a..44bb89b 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -68,27 +68,54 @@ static int sta_info_hash_del(struct ieee80211_local *local,
struct sta_info *sta)
{
struct sta_info *s;
+ int rv = -ENOENT;
+ int idx = STA_HASH(sta->sta.addr);
+ struct ieee80211_sub_if_data *sdata = sta->sdata;
- s = rcu_dereference_protected(local->sta_hash[STA_HASH(sta->sta.addr)],
+ s = rcu_dereference_protected(local->sta_hash[idx],
lockdep_is_held(&local->sta_mtx));
if (!s)
- return -ENOENT;
+ /* If station is not in the main hash, then it definitely
+ * should not be in the vhash, so we can just return.
+ */
+ return rv;
+
if (s == sta) {
- rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)],
- s->hnext);
- return 0;
+ rcu_assign_pointer(local->sta_hash[idx], s->hnext);
+ rv = 0;
+ goto try_vhash;
}
while (rcu_access_pointer(s->hnext) &&
rcu_access_pointer(s->hnext) != sta)
s = rcu_dereference_protected(s->hnext,
- lockdep_is_held(&local->sta_mtx));
+ lockdep_is_held(&local->sta_mtx));
if (rcu_access_pointer(s->hnext)) {
rcu_assign_pointer(s->hnext, sta->hnext);
- return 0;
+ rv = 0;
+ goto try_vhash;
}
+ return rv;
- return -ENOENT;
+try_vhash:
+ s = rcu_dereference_protected(sdata->sta_vhash[idx],
+ lockdep_is_held(&local->sta_mtx));
+ if (!s)
+ return rv;
+
+ if (s == sta) {
+ rcu_assign_pointer(sdata->sta_vhash[idx], s->vnext);
+ return rv;
+ }
+
+ while (rcu_access_pointer(s->vnext) &&
+ rcu_access_pointer(s->vnext) != sta)
+ s = rcu_dereference_protected(s->vnext,
+ lockdep_is_held(&local->sta_mtx));
+ if (rcu_access_pointer(s->vnext))
+ rcu_assign_pointer(s->vnext, sta->vnext);
+
+ return rv;
}
static void cleanup_single_sta(struct sta_info *sta)
@@ -195,17 +222,15 @@ static void free_sta_rcu(struct rcu_head *h)
struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
const u8 *addr)
{
- struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
- sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
- lockdep_is_held(&local->sta_mtx));
+ sta = rcu_dereference_check(sdata->sta_vhash[STA_HASH(addr)],
+ lockdep_is_held(&sdata->local->sta_mtx));
while (sta) {
- if (sta->sdata == sdata &&
- ether_addr_equal(sta->sta.addr, addr))
+ if (ether_addr_equal(sta->sta.addr, addr))
break;
- sta = rcu_dereference_check(sta->hnext,
- lockdep_is_held(&local->sta_mtx));
+ sta = rcu_dereference_check(sta->vnext,
+ lockdep_is_held(&sdata->local->sta_mtx));
}
return sta;
}
@@ -220,6 +245,13 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
+ sta = sta_info_get(sdata, addr);
+ if (sta)
+ return sta;
+
+ /* Maybe it's on some other sdata matching the bss, try
+ * a bit harder.
+ */
sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
lockdep_is_held(&local->sta_mtx));
while (sta) {
@@ -233,6 +265,22 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
return sta;
}
+struct sta_info *sta_info_get_by_vif(struct ieee80211_local *local,
+ const u8 *vif_addr, const u8 *sta_addr)
+{
+ struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_sub_if_data *nxt;
+ struct sta_info *sta;
+
+ for_each_sdata(local, vif_addr, sdata, nxt) {
+ sta = sta_info_get(sdata, sta_addr);
+ if (sta)
+ return sta;
+ }
+ return NULL;
+}
+
+
struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
int idx)
{
@@ -278,9 +326,14 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
static void sta_info_hash_add(struct ieee80211_local *local,
struct sta_info *sta)
{
+ int idx = STA_HASH(sta->sta.addr);
+
lockdep_assert_held(&local->sta_mtx);
- sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)];
- rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta);
+ sta->hnext = local->sta_hash[idx];
+ rcu_assign_pointer(local->sta_hash[idx], sta);
+
+ sta->vnext = sta->sdata->sta_vhash[idx];
+ rcu_assign_pointer(sta->sdata->sta_vhash[idx], sta);
}
static void sta_unblock(struct work_struct *wk)
@@ -975,14 +1028,18 @@ struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
{
struct sta_info *sta, *nxt;
+ if (localaddr) {
+ sta = sta_info_get_by_vif(hw_to_local(hw), localaddr, addr);
+ if (sta && sta->uploaded)
+ return &sta->sta;
+ return NULL;
+ }
+
/*
* Just return a random station if localaddr is NULL
* ... first in list.
*/
for_each_sta_info(hw_to_local(hw), addr, sta, nxt) {
- if (localaddr &&
- !ether_addr_equal(sta->sdata->vif.addr, localaddr))
- continue;
if (!sta->uploaded)
return NULL;
return &sta->sta;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 4208dbd..963de5e 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -15,6 +15,7 @@
#include <linux/workqueue.h>
#include <linux/average.h>
#include <linux/etherdevice.h>
+#include <linux/hash.h>
#include "key.h"
/**
@@ -228,7 +229,8 @@ struct sta_ampdu_mlme {
* mac80211 is communicating with.
*
* @list: global linked list entry
- * @hnext: hash table linked list pointer
+ * @hnext: hash table linked list pointer, used by local->sta_hash
+ * @vnext: hash table linked list pointer, used by sdata->sta_vhash.
* @local: pointer to the global information
* @sdata: virtual interface this station belongs to
* @ptk: peer key negotiated with this station, if any
@@ -307,6 +309,7 @@ struct sta_info {
struct list_head list;
struct rcu_head rcu_head;
struct sta_info __rcu *hnext;
+ struct sta_info __rcu *vnext;
struct ieee80211_local *local;
struct ieee80211_sub_if_data *sdata;
struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
@@ -492,7 +495,12 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid)
}
#define STA_HASH_SIZE 256
-#define STA_HASH(sta) (sta[5])
+static inline u32 STA_HASH(const unsigned char *addr)
+{
+ u32 v = (addr[0] << 8) | addr[1];
+ v ^= (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5];
+ return hash_32(v, 8);
+}
/* Maximum number of frames to buffer per power saving station per AC */
@@ -514,6 +522,12 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
const u8 *addr);
+/*
+ * Uses the local->sdata hash and sdata->sta_hash for fast lookup
+ * base on VIF (sdata) address and remote station address.
+ */
+struct sta_info *sta_info_get_by_vif(struct ieee80211_local *local,
+ const u8 *vif_addr, const u8 *sta_addr);
static inline
void for_each_sta_info_type_check(struct ieee80211_local *local,
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 4343920..0ecab1a 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -453,11 +453,16 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
sband = local->hw.wiphy->bands[info->band];
fc = hdr->frame_control;
+ sta = sta_info_get_by_vif(local, hdr->addr2, hdr->addr1);
+ if (sta)
+ goto found_it;
+
for_each_sta_info(local, hdr->addr1, sta, tmp) {
/* skip wrong virtual interface */
if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr))
continue;
+found_it:
if (info->flags & IEEE80211_TX_STATUS_EOSP)
clear_sta_flag(sta, WLAN_STA_SP);
@@ -553,6 +558,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
if (acked)
sta->last_ack_signal = info->status.ack_signal;
+ break;
}
rcu_read_unlock();
--
1.7.3.4
^ permalink raw reply related
* [WT PATCH 3/6] wireless: Add memory usage debugging.
From: greearb @ 2013-06-29 22:58 UTC (permalink / raw)
To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <1372546738-25827-1-git-send-email-greearb@candelatech.com>
From: Ben Greear <greearb@candelatech.com>
The bss objects are reference counted, and the ies
are also tricky to keep track of. Add module option to
track allocation and freeing of the ies and bss objects,
and add debugfs files to show the current objects.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
net/wireless/core.c | 9 +++-
net/wireless/core.h | 16 ++++++
net/wireless/debugfs.c | 113 +++++++++++++++++++++++++++++++++++++++
net/wireless/debugfs.h | 2 +
net/wireless/scan.c | 139 ++++++++++++++++++++++++++++++++++++++++++-----
5 files changed, 262 insertions(+), 17 deletions(-)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 672459b..861fc37 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -50,6 +50,10 @@ static bool cfg80211_disable_40mhz_24ghz;
module_param(cfg80211_disable_40mhz_24ghz, bool, 0644);
MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz,
"Disable 40MHz support in the 2.4GHz band");
+bool cfg80211_mem_debugging;
+module_param(cfg80211_mem_debugging, bool, 0644);
+MODULE_PARM_DESC(cfg80211_mem_debugging,
+ "Enable memory tracking for ies and bss objects.");
struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
{
@@ -996,6 +1000,7 @@ static int __init cfg80211_init(void)
goto out_fail_nl80211;
ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL);
+ ieee80211_debugfs_add_glbl(ieee80211_debugfs_dir);
err = regulatory_init();
if (err)
@@ -1012,7 +1017,7 @@ static int __init cfg80211_init(void)
out_fail_wq:
regulatory_exit();
out_fail_reg:
- debugfs_remove(ieee80211_debugfs_dir);
+ debugfs_remove_recursive(ieee80211_debugfs_dir);
out_fail_nl80211:
unregister_netdevice_notifier(&cfg80211_netdev_notifier);
out_fail_notifier:
@@ -1026,7 +1031,7 @@ subsys_initcall(cfg80211_init);
static void __exit cfg80211_exit(void)
{
- debugfs_remove(ieee80211_debugfs_dir);
+ debugfs_remove_recursive(ieee80211_debugfs_dir);
nl80211_exit();
unregister_netdevice_notifier(&cfg80211_netdev_notifier);
wiphy_sysfs_exit();
diff --git a/net/wireless/core.h b/net/wireless/core.h
index a6b45bf..74d694f 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -114,6 +114,22 @@ extern struct workqueue_struct *cfg80211_wq;
extern struct list_head cfg80211_rdev_list;
extern int cfg80211_rdev_list_generation;
+extern bool cfg80211_mem_debugging; /* module option */
+#ifdef CONFIG_CFG80211_DEBUGFS
+struct wifi_mem_tracker {
+ struct list_head mylist;
+ char buf[40];
+ void *ptr;
+};
+extern struct list_head ies_list;
+extern spinlock_t ies_lock;
+extern atomic_t ies_count;
+
+extern struct list_head bss_list;
+extern spinlock_t bss_lock;
+extern atomic_t bss_count;
+#endif
+
struct cfg80211_internal_bss {
struct list_head list;
struct list_head hidden_list;
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
index 90d0500..fd52bb1 100644
--- a/net/wireless/debugfs.c
+++ b/net/wireless/debugfs.c
@@ -31,6 +31,108 @@ static const struct file_operations name## _ops = { \
.llseek = generic_file_llseek, \
};
+#define DEBUGFS_READONLY_FILE_OPS(name) \
+static const struct file_operations name## _ops = { \
+ .read = name## _read, \
+ .open = simple_open, \
+ .llseek = generic_file_llseek, \
+};
+
+static ssize_t all_ies_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ int mxln = 31500;
+ char *buf = kzalloc(mxln, GFP_KERNEL);
+ int q, res = 0;
+ struct wifi_mem_tracker *iesm;
+
+ if (!buf)
+ return 0;
+
+ spin_lock_bh(&ies_lock);
+ res += sprintf(buf + res, "Total: %i\n", atomic_read(&ies_count));
+ list_for_each_entry(iesm, &ies_list, mylist) {
+ res += sprintf(buf + res, "%p: %s\n",
+ iesm->ptr, iesm->buf);
+ if (res >= mxln) {
+ res = mxln;
+ break;
+ }
+ }
+ spin_unlock_bh(&ies_lock);
+
+ q = simple_read_from_buffer(user_buf, count, ppos, buf, res);
+ kfree(buf);
+ return q;
+}
+
+static ssize_t all_bss_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ int mxln = 31500;
+ char *buf = kzalloc(mxln, GFP_KERNEL);
+ int q, res = 0;
+ struct wifi_mem_tracker *bssm;
+
+ if (!buf)
+ return 0;
+
+ spin_lock_bh(&bss_lock);
+ res += sprintf(buf + res, "Total: %i\n", atomic_read(&bss_count));
+ list_for_each_entry(bssm, &bss_list, mylist) {
+ struct cfg80211_internal_bss *bss;
+ bss = (struct cfg80211_internal_bss *)(bssm->ptr);
+ res += sprintf(buf + res, "%p: #%lu %s\n",
+ bssm->ptr, bss->refcount, bssm->buf);
+ if (res >= mxln) {
+ res = mxln;
+ break;
+ }
+ }
+ spin_unlock_bh(&bss_lock);
+
+ q = simple_read_from_buffer(user_buf, count, ppos, buf, res);
+ kfree(buf);
+ return q;
+}
+
+DEBUGFS_READONLY_FILE_OPS(all_ies);
+DEBUGFS_READONLY_FILE_OPS(all_bss);
+
+
+static ssize_t bss_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wiphy *wiphy = file->private_data;
+ struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
+ int mxln = 31500;
+ char *buf = kzalloc(mxln, GFP_KERNEL);
+ int q, res = 0;
+ struct cfg80211_internal_bss *bss;
+
+ if (!buf)
+ return 0;
+
+ spin_lock_bh(&dev->bss_lock);
+ list_for_each_entry(bss, &dev->bss_list, list) {
+ res += sprintf(buf + res,
+ "%p: #%lu bcn: %p pr: %p hidden: %p\n",
+ bss, bss->refcount,
+ rcu_access_pointer(bss->pub.beacon_ies),
+ rcu_access_pointer(bss->pub.proberesp_ies),
+ bss->pub.hidden_beacon_bss);
+ if (res >= mxln) {
+ res = mxln;
+ break;
+ }
+ }
+ spin_unlock_bh(&dev->bss_lock);
+
+ q = simple_read_from_buffer(user_buf, count, ppos, buf, res);
+ kfree(buf);
+ return q;
+}
+
DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
wiphy->rts_threshold)
DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
@@ -39,6 +141,7 @@ DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d",
wiphy->retry_short)
DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
wiphy->retry_long);
+DEBUGFS_READONLY_FILE_OPS(bss);
static int ht_print_chan(struct ieee80211_channel *chan,
char *buf, int buf_size, int offset)
@@ -112,4 +215,14 @@ void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev)
DEBUGFS_ADD(short_retry_limit);
DEBUGFS_ADD(long_retry_limit);
DEBUGFS_ADD(ht40allow_map);
+ DEBUGFS_ADD(bss);
+}
+
+#define DEBUGFS_ADD_GLBL(name) \
+ debugfs_create_file(#name, S_IRUGO, dir, NULL, &name## _ops);
+
+void ieee80211_debugfs_add_glbl(struct dentry *dir)
+{
+ DEBUGFS_ADD_GLBL(all_ies);
+ DEBUGFS_ADD_GLBL(all_bss);
}
diff --git a/net/wireless/debugfs.h b/net/wireless/debugfs.h
index 74fdd38..f644869 100644
--- a/net/wireless/debugfs.h
+++ b/net/wireless/debugfs.h
@@ -3,9 +3,11 @@
#ifdef CONFIG_CFG80211_DEBUGFS
void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev);
+void ieee80211_debugfs_add_glbl(struct dentry *dir);
#else
static inline
void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev) {}
+static inline void ieee80211_debugfs_add_glbl(struct dentry *dir) { }
#endif
#endif /* __CFG80211_DEBUGFS_H */
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index ae8c186..2d66334 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -57,6 +57,118 @@
#define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ)
+#ifdef CONFIG_CFG80211_DEBUGFS
+/* memory debugging structures, only useful when debugfs
+ * is enabled.
+ */
+LIST_HEAD(ies_list);
+DEFINE_SPINLOCK(ies_lock);
+atomic_t ies_count = ATOMIC_INIT(0);
+
+LIST_HEAD(bss_list);
+DEFINE_SPINLOCK(bss_lock);
+atomic_t bss_count = ATOMIC_INIT(0);
+
+
+static void my_kfree_rcu_ies(struct cfg80211_bss_ies *ies)
+{
+ if (cfg80211_mem_debugging) {
+ struct wifi_mem_tracker *iesm;
+ spin_lock_bh(&ies_lock);
+ list_for_each_entry(iesm, &ies_list, mylist) {
+ if (iesm->ptr == ies) {
+ list_del(&iesm->mylist);
+ kfree(iesm);
+ break;
+ }
+ }
+ spin_unlock_bh(&ies_lock);
+ }
+ atomic_sub(1, &ies_count);
+ kfree_rcu(ies, rcu_head);
+}
+
+#define my_kmalloc_ies(s, g) \
+ _my_kmalloc_ies(s, g, __LINE__);
+
+static void* _my_kmalloc_ies(size_t s, gfp_t gfp, int l)
+{
+ void *rv = kmalloc(s, gfp);
+ if (rv) {
+ atomic_add(1, &ies_count);
+ if (cfg80211_mem_debugging) {
+ struct wifi_mem_tracker *iesm;
+ iesm = kmalloc(sizeof(*iesm), gfp);
+ if (iesm) {
+ snprintf(iesm->buf, sizeof(iesm->buf), "%i", l);
+ iesm->buf[sizeof(iesm->buf)-1] = 0;
+ iesm->ptr = rv;
+ INIT_LIST_HEAD(&iesm->mylist);
+ spin_lock_bh(&ies_lock);
+ list_add(&iesm->mylist, &ies_list);
+ spin_unlock_bh(&ies_lock);
+ } else {
+ pr_err("ERROR: Could not allocate iesm.\n");
+ }
+ }
+ }
+ return rv;
+}
+
+static void my_kfree_bss(struct cfg80211_internal_bss *bss)
+{
+ if (cfg80211_mem_debugging) {
+ struct wifi_mem_tracker *bssm;
+ spin_lock_bh(&bss_lock);
+ list_for_each_entry(bssm, &bss_list, mylist) {
+ if (bssm->ptr == bss) {
+ list_del(&bssm->mylist);
+ kfree(bssm);
+ break;
+ }
+ }
+ spin_unlock_bh(&bss_lock);
+ }
+ atomic_sub(1, &bss_count);
+ kfree(bss);
+}
+
+#define my_kzalloc_bss(s, g) \
+ _my_kzalloc_bss(s, g, __LINE__);
+
+static void* _my_kzalloc_bss(size_t s, gfp_t gfp, int l)
+{
+ void *rv = kmalloc(s, gfp);
+ if (rv) {
+ atomic_add(1, &bss_count);
+ if (cfg80211_mem_debugging) {
+ struct wifi_mem_tracker *bssm;
+ bssm = kmalloc(sizeof(*bssm), gfp);
+ if (bssm) {
+ snprintf(bssm->buf, sizeof(bssm->buf), "%i", l);
+ bssm->buf[sizeof(bssm->buf)-1] = 0;
+ bssm->ptr = rv;
+ INIT_LIST_HEAD(&bssm->mylist);
+ spin_lock_bh(&bss_lock);
+ list_add(&bssm->mylist, &bss_list);
+ spin_unlock_bh(&bss_lock);
+ } else {
+ pr_err("ERROR: Could not allocate bssm for bss.\n");
+ }
+ }
+ }
+ return rv;
+}
+
+#else
+
+#define my_kfree_rcu_ies(ies) kfree_rcu(ies, rcu_head)
+#define my_kmalloc_ies(s, g) kmalloc(s, g)
+#define my_kfree_bss(a) kfree(a)
+#define my_kzalloc_bss(s, g) kzalloc(s, g)
+
+#endif
+
static void bss_free(struct cfg80211_internal_bss *bss)
{
struct cfg80211_bss_ies *ies;
@@ -66,10 +178,10 @@ static void bss_free(struct cfg80211_internal_bss *bss)
ies = (void *)rcu_access_pointer(bss->pub.beacon_ies);
if (ies && !bss->pub.hidden_beacon_bss)
- kfree_rcu(ies, rcu_head);
+ my_kfree_rcu_ies(ies);
ies = (void *)rcu_access_pointer(bss->pub.proberesp_ies);
if (ies)
- kfree_rcu(ies, rcu_head);
+ my_kfree_rcu_ies(ies);
/*
* This happens when the module is removed, it doesn't
@@ -78,7 +190,7 @@ static void bss_free(struct cfg80211_internal_bss *bss)
if (!list_empty(&bss->hidden_list))
list_del(&bss->hidden_list);
- kfree(bss);
+ my_kfree_bss(bss);
}
static inline void bss_ref_get(struct cfg80211_registered_device *dev,
@@ -713,8 +825,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
rcu_assign_pointer(found->pub.ies,
tmp->pub.proberesp_ies);
if (old)
- kfree_rcu((struct cfg80211_bss_ies *)old,
- rcu_head);
+ my_kfree_rcu_ies((struct cfg80211_bss_ies *)old);
} else if (rcu_access_pointer(tmp->pub.beacon_ies)) {
const struct cfg80211_bss_ies *old;
struct cfg80211_internal_bss *bss;
@@ -734,8 +845,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
*/
f = rcu_access_pointer(tmp->pub.beacon_ies);
- kfree_rcu((struct cfg80211_bss_ies *)f,
- rcu_head);
+ my_kfree_rcu_ies((struct cfg80211_bss_ies *)f);
goto drop;
}
@@ -762,8 +872,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
}
if (old)
- kfree_rcu((struct cfg80211_bss_ies *)old,
- rcu_head);
+ my_kfree_rcu_ies((struct cfg80211_bss_ies *)old);
}
found->pub.beacon_interval = tmp->pub.beacon_interval;
@@ -780,15 +889,15 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
* is allocated on the stack since it's not needed in the
* more common case of an update
*/
- new = kzalloc(sizeof(*new) + dev->wiphy.bss_priv_size,
- GFP_ATOMIC);
+ new = my_kzalloc_bss(sizeof(*new) + dev->wiphy.bss_priv_size,
+ GFP_ATOMIC);
if (!new) {
ies = (void *)rcu_dereference(tmp->pub.beacon_ies);
if (ies)
- kfree_rcu(ies, rcu_head);
+ my_kfree_rcu_ies(ies);
ies = (void *)rcu_dereference(tmp->pub.proberesp_ies);
if (ies)
- kfree_rcu(ies, rcu_head);
+ my_kfree_rcu_ies(ies);
goto drop;
}
memcpy(new, tmp, sizeof(*new));
@@ -903,7 +1012,7 @@ cfg80211_inform_bss(struct wiphy *wiphy,
* override the IEs pointer should we have received an earlier
* indication of Probe Response data.
*/
- ies = kmalloc(sizeof(*ies) + ielen, gfp);
+ ies = my_kmalloc_ies(sizeof(*ies) + ielen, gfp);
if (!ies)
return NULL;
ies->len = ielen;
@@ -961,7 +1070,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
if (!channel)
return NULL;
- ies = kmalloc(sizeof(*ies) + ielen, gfp);
+ ies = my_kmalloc_ies(sizeof(*ies) + ielen, gfp);
if (!ies)
return NULL;
ies->len = ielen;
--
1.7.3.4
^ permalink raw reply related
* [WT PATCH 2/6] mac80211: Make un-found-rate splat a warn-once.
From: greearb @ 2013-06-29 22:58 UTC (permalink / raw)
To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <1372546738-25827-1-git-send-email-greearb@candelatech.com>
From: Ben Greear <greearb@candelatech.com>
After that, print it out with net_ratelimit. We saw a system
continually hit this warning, for reasons unknown, and it
seems it bogged the system down enough to make it go OOM.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
net/mac80211/tx.c | 21 ++++++++++++++-------
1 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 4105d0c..8601f3f 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -678,14 +678,21 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
* Lets not bother rate control if we're associated and cannot
* talk to the sta. This should not happen.
*/
- if (WARN(test_bit(SCAN_SW_SCANNING, &tx->local->scanning) && assoc &&
- !rate_usable_index_exists(sband, &tx->sta->sta),
- "%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,
- info->band ? 5 : 2))
+ if (test_bit(SCAN_SW_SCANNING, &tx->local->scanning) && assoc &&
+ !rate_usable_index_exists(sband, &tx->sta->sta)) {
+ static bool do_once = true;
+ if (do_once) {
+ WARN(1, "%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,
+ info->band ? 5 : 2);
+ do_once = false;
+ } else {
+ net_info_ratelimited("%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,
+ info->band ? 5 : 2);
+ }
return TX_DROP;
+ }
/*
* If we're associated with the sta at this point we know we can at
--
1.7.3.4
^ permalink raw reply related
* [WT PATCH 1/6] mac80211: Add debugfs file to show station-hash counts.
From: greearb @ 2013-06-29 22:58 UTC (permalink / raw)
To: linux-wireless; +Cc: Ben Greear
From: Ben Greear <greearb@candelatech.com>
Helps debug bad hash spreads, like when you have lots of
station interfaces all connected to the same AP.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
net/mac80211/debugfs.c | 37 +++++++++++++++++++++++++++++++++++++
1 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index b0e32d6..2bbe377 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -175,8 +175,44 @@ static ssize_t queues_read(struct file *file, char __user *user_buf,
return simple_read_from_buffer(user_buf, count, ppos, buf, res);
}
+static ssize_t sta_hash_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_local *local = file->private_data;
+ int mxln = STA_HASH_SIZE * 10;
+ char *buf = kzalloc(mxln, GFP_KERNEL);
+ int q, res = 0;
+ struct sta_info *sta;
+
+ if (!buf)
+ return 0;
+
+ mutex_lock(&local->sta_mtx);
+ for (q = 0; q < STA_HASH_SIZE; q++) {
+ int cnt = 0;
+ sta = local->sta_hash[q];
+ while (sta) {
+ cnt++;
+ sta = sta->hnext;
+ }
+ if (cnt) {
+ res += sprintf(buf + res, "%i: %i\n", q, cnt);
+ if (res >= (STA_HASH_SIZE * 10)) {
+ res = STA_HASH_SIZE * 10;
+ break;
+ }
+ }
+ }
+ mutex_unlock(&local->sta_mtx);
+
+ q = simple_read_from_buffer(user_buf, count, ppos, buf, res);
+ kfree(buf);
+ return q;
+}
+
DEBUGFS_READONLY_FILE_OPS(hwflags);
DEBUGFS_READONLY_FILE_OPS(queues);
+DEBUGFS_READONLY_FILE_OPS(sta_hash);
/* statistics stuff */
@@ -245,6 +281,7 @@ void debugfs_hw_add(struct ieee80211_local *local)
DEBUGFS_ADD(total_ps_buffered);
DEBUGFS_ADD(wep_iv);
DEBUGFS_ADD(queues);
+ DEBUGFS_ADD(sta_hash);
#ifdef CONFIG_PM
DEBUGFS_ADD_MODE(reset, 0200);
#endif
--
1.7.3.4
^ permalink raw reply related
* Re: [RFC v2] mac80211: Use libnl-configurable values for retry counts
From: Felix Fietkau @ 2013-06-29 20:08 UTC (permalink / raw)
To: Jean-Pierre Tosoni; +Cc: linux-wireless
In-Reply-To: <1372351227-25575-1-git-send-email-jp.tosoni@acksys.fr>
On 2013-06-27 6:40 PM, Jean-Pierre Tosoni wrote:
> From: J.P. Tosoni <jp.tosoni@acksys.fr>
>
> In the rate control algorithms, the maximum retry count is limited by
> a) a constant value obtained from the hardware driver
> b) a constant limit (6ms) on the time allowed for all
> retries of each frame.
>
> Replace the retry count by existing configurable values from nl80211.
> Use wiphy->retry_long for frames whose length exceed rts_threshold.
> Use wiphy->retry_short for all other frames.
> Check that the configured value does not exceed driver capabilities.
> Use the new values as soon as the next frame is transmitted.
>
> Caveat: the retry count for frames sent outside the context of a STA is
> still taken from the hardware driver.
> ---
> What I am seeking with this patch:
> I believe the configuration of the retries will help making recovery
> much faster when an AP (in infrastructure mode) or a peer (in mesh
> mode) suddenly disappears.
I'm all for reducing retries, but I think the way you're applying the
limit is problematic.
If minstrel decides to use many retries for a high rate and you're
simply cutting off all retries that exceed the configured limit, you're
potentially inviting quite a bit of unnecessary packet loss.
I'm planning to remove the use of retry rate slot 4 (fallback to lowest
rate) from minstrel, since max_prob_rate should already provide quite
decent reliability.
- Felix
^ permalink raw reply
* Re: [rt2x00-users] [PATCH 00/19] rt2x00: add experimental support for RT3593
From: Andreas Hartmann @ 2013-06-29 15:04 UTC (permalink / raw)
To: Gabor Juhos, John Linville; +Cc: linux-wireless, users
In-Reply-To: <1372446753-11408-1-git-send-email-juhosg@openwrt.org>
Hello Gabor,
Gabor Juhos wrote:
> This patch-set implements experiemental support for the
> RT3593 chipset. The patches are tested on the Linksys
> AE3000 USB device only, however other USB devices which
> are using the RT3573 chips might work as well.
I tested your patchset (and all the others) with the same device you
used for developing in a real life scenario. My AP
http://wikidevi.com/wiki/TP-LINK_TL-WDN4800 is configured for 2.4 GHz,
40MHz, 802.11n, EAP-TLS.
The AE3000 is used with a notebook / core i5 processor.
The test was done *during a parallel running full hd video* in the
same net with another AE3000 running on raspberry pi with ralinks own
driver *always w/o any stuttering* (that's why I'm buying such devices)!
There is a reinforced-concrete floor between AP and the STAs.
>From /var/log/messages:
kernel: [33425.890174] cfg80211: Calling CRDA to update world regulatory domain
kernel: [33425.894221] cfg80211: World regulatory domain updated:
kernel: [33425.894230] cfg80211: (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
kernel: [33425.894232] cfg80211: (2402000 KHz - 2472000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
kernel: [33425.894234] cfg80211: (2457000 KHz - 2482000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)
kernel: [33425.894236] cfg80211: (2474000 KHz - 2494000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)
kernel: [33425.894238] cfg80211: (5170000 KHz - 5250000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
kernel: [33425.894240] cfg80211: (5735000 KHz - 5835000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
kernel: [33425.973578] usb 2-1.5: reset high-speed USB device number 3 using ehci-pci
kernel: [33426.070273] ieee80211 phy0: rt2x00_set_rt: Info - RT chipset 3593, rev 0402 detected
kernel: [33426.102833] ieee80211 phy0: rt2x00_set_rf: Info - RF chipset 000d detected
kernel: [33426.103387] ieee80211 phy0: Selected rate control algorithm 'minstrel_ht'
kernel: [33426.104122] usbcore: registered new interface driver rt2800usb
kernel: [33429.115258] ieee80211 phy0: rt2x00lib_request_firmware: Info - Loading firmware file 'rt2870.bin'
kernel: [33429.115305] ieee80211 phy0: rt2x00lib_request_firmware: Info - Firmware detected - version: 0.33
kernel: [33429.359196] IPv6: ADDRCONF(NETDEV_UP): wlan2: link is not ready
kernel: [33432.884764] wlan2: authenticate with 11:22:33:44:55:66
kernel: [33432.937069] wlan2: send auth to 11:22:33:44:55:66 (try 1/3)
kernel: [33432.939615] wlan2: authenticated
kernel: [33432.940177] wlan2: associate with 11:22:33:44:55:66 (try 1/3)
kernel: [33432.943876] wlan2: RX AssocResp from 11:22:33:44:55:66 (capab=0x431 status=0 aid=1)
kernel: [33432.953244] wlan2: associated
kernel: [33432.953278] IPv6: ADDRCONF(NETDEV_CHANGE): wlan2: link becomes ready
kernel: [33432.953322] cfg80211: Calling CRDA for country: DE
kernel: [33432.957301] cfg80211: Regulatory domain changed to country: DE
kernel: [33432.957306] cfg80211: (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
kernel: [33432.957310] cfg80211: (2400000 KHz - 2483500 KHz @ 40000 KHz), (N/A, 2000 mBm)
kernel: [33432.957313] cfg80211: (5150000 KHz - 5250000 KHz @ 40000 KHz), (N/A, 2000 mBm)
kernel: [33432.957316] cfg80211: (5250000 KHz - 5350000 KHz @ 40000 KHz), (N/A, 2000 mBm)
kernel: [33432.957319] cfg80211: (5470000 KHz - 5725000 KHz @ 40000 KHz), (N/A, 2698 mBm)
netperf gives with rt2800usb on the notebook:
MIGRATED TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to server () port 0 AF_INET : demo
enable_enobufs failed: setsockopt
Recv Send Send
Socket Socket Message Elapsed
Size Size Size Time Throughput
bytes bytes bytes secs. 10^6bits/sec
87380 16384 16384 10.01 78.41
MIGRATED TCP MAERTS TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET from server () port 0 AF_INET : demo
enable_enobufs failed: setsockopt
Recv Send Send
Socket Socket Message Elapsed
Size Size Size Time Throughput
bytes bytes bytes secs. 10^6bits/sec
87380 16384 16384 10.00 115.92
TCP SENDFILE TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to server () port 0 AF_INET : demo
Recv Send Send
Socket Socket Message Elapsed
Size Size Size Time Throughput
bytes bytes bytes secs. 10^6bits/sec
87380 16384 16384 10.02 86.46
The exactly same (=unchanged conditions) done with
DPO_RT5572_LinuxSTA_2.6.1.3_20121022 on the notebook gives:
MIGRATED TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to server () port 0 AF_INET : demo
enable_enobufs failed: setsockopt
Recv Send Send
Socket Socket Message Elapsed
Size Size Size Time Throughput
bytes bytes bytes secs. 10^6bits/sec
87380 16384 16384 10.02 130.36
MIGRATED TCP MAERTS TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET from server () port 0 AF_INET : demo
enable_enobufs failed: setsockopt
Recv Send Send
Socket Socket Message Elapsed
Size Size Size Time Throughput
bytes bytes bytes secs. 10^6bits/sec
87380 16384 16384 10.00 131.23
TCP SENDFILE TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to server () port 0 AF_INET : demo
Recv Send Send
Socket Socket Message Elapsed
Size Size Size Time Throughput
bytes bytes bytes secs. 10^6bits/sec
87380 16384 16384 10.03 131.33
Thanks,
kind regards,
Andreas
^ permalink raw reply
* Re: [PATCH 19/19] rt2x00: rt2800usb: add USB device ID for Linksys AE3000
From: Gabor Juhos @ 2013-06-29 11:38 UTC (permalink / raw)
To: Xose Vazquez Perez; +Cc: users@rt2x00.serialmonkey.com, linux-wireless
In-Reply-To: <51CE0DA4.7090608@gmail.com>
2013.06.29. 0:26 keltezéssel, Xose Vazquez Perez írta:
> Gabor Juhos wrote:
>
>> diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
>> index c24c1fd..6136871 100644
>> --- a/drivers/net/wireless/rt2x00/rt2800usb.c
>> +++ b/drivers/net/wireless/rt2x00/rt2800usb.c
>> @@ -1183,6 +1183,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
>> { USB_DEVICE(0x04bb, 0x0944) },
>> /* Linksys */
>> { USB_DEVICE(0x13b1, 0x002f) },
>> + { USB_DEVICE(0x13b1, 0x003b) },
>> { USB_DEVICE(0x1737, 0x0079) },
>> /* Ralink */
>> { USB_DEVICE(0x148f, 0x3572) },
>> --
>
> You should separate RT3573 and RT3572 devices.
> Rename CONFIG_RT2800USB_RT35XX to CONFIG_RT2800USB_RT3572
> and do a new CONFIG_RT2800USB_RT3573 section.
Renaming a config option is not a good idea IMO. I would simply add a
CONFIG_RT2800USB_RT3573 symbol which depends on CONFIG_RT2800USB_RT35XX instead.
> And also you can add safely this usb-ids. All of them
> are RT3573 devices:
>
> 0x1b75, 0x7733 AirLive 450Mbps Wireless-N Dual Band USB Adapter
> 0x0b05, 0x17bc ASUS USB-N66 450Mbps Dual Band USB Adapter
> 0x0b05, 0x17ad ASUS USB-N66 Dual Band N Network Adapter
> 0x050d, 0x1103 Belkin Wireless Adapter
> 0x148f, 0xf301 Cameo Ralink3573 3x3 single band USB dongle
> 0x7392, 0x7733 Edimax
> 0x0e66, 0x0020 Hawking HD45U Dual Band USB Wireless-N Adapter
> 0x0e66, 0x0021 Hawking HD45U Dual Band Wls-450N Adapter
> 0x04bb, 0x094e I-O DATA WN-AG450U Wireless LAN Adapter
> 0x0789, 0x016b Logitec LAN-W450AN/U2
> 0x0846, 0x9012 NETGEAR WNDA4100 N900 Wireless Dual Band USB Adapter
> 0x0846, 0x9019 NETGEAR WNDA4200D Wireless Dual Band USB Adapter
> 0x2019, 0xed19 Planex GW-USDual450
> 0x148f, 0x3573 Ralink 802.11n USB Wireless LAN Card
> 0x0df6, 0x0067 Sitecom Wireless Dualband Network Adapter N750 X6
> 0x0df6, 0x006a Sitecom Wireless Dualband Network Adapter N900 X7
> 0x0586, 0x3421 ZyXEL Dual-Band Wireless N450 USB Adapter
I did not test any of these devices and I don't even know from where did you get
these IDs. Only a subset of these IDs is present in the Ralink driver.
If you feel that all of these can be added safely, you can send a follow-up patch.
-Gabor
^ permalink raw reply
* Re: [PATCH 02/19] rt2x00: rt2800lib: add RFCSR register initialization for RT3593
From: Gabor Juhos @ 2013-06-29 11:17 UTC (permalink / raw)
To: Xose Vazquez Perez; +Cc: linux-wireless, users@rt2x00.serialmonkey.com
In-Reply-To: <51CE0330.7090007@gmail.com>
2013.06.28. 23:42 keltezéssel, Xose Vazquez Perez írta:
> Gabor Juhos wrote:
>
>> Based on the Ralink DPO_RT5572_LinuxSTA_2.6.0.1_20120629
>> driver.
>
> There is a more recent version: DPO_RT5572_LinuxSTA_2.6.1.3_20121022
Yes, I know. However I wanted to test AP mode with the vendor driver and that is
only supported in the '2.6.0.1_20120629' version.
>
>> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
>> index 32ecd1a..0041b2c 100644
>> --- a/drivers/net/wireless/rt2x00/rt2800lib.c
>> +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
>> [...]
>> + /* Initialize default register values */
>> + rt2800_rfcsr_write(rt2x00dev, 1, 0x03);
>> + rt2800_rfcsr_write(rt2x00dev, 3, 0x80);
>
> from ./20120911_RT3573_Linux_STA_v2.5.0.0_Rev1_DPO/chips/rt3593.c
>
> {RF_R02, 0x80}
>
> but it was deleted in ./DPO_RT5572_LinuxSTA_2.6.1.3_20121022/chips/rt3593.c
>
> Was it deliberate ? or a mistake ??
It is intentional. The patch is based on the *2.6.0.1* driver, and the value is
not present in that.
-Gabor
^ permalink raw reply
* Re: [rt2x00-users] [PATCH 01/19] rt2x00: rt2800lib: add BBP register initialization for RT3593
From: Gabor Juhos @ 2013-06-29 11:18 UTC (permalink / raw)
To: Andreas Hartmann; +Cc: John Linville, linux-wireless, users
In-Reply-To: <51CE6FB5.2000706@01019freenet.de>
[-- Attachment #1: Type: text/plain, Size: 1947 bytes --]
Hi Adnreas,
> thanks for your submission. I tried to test it, but stuck at the problem
> mentioned below.
>
>
> Regards,
> Andreas
>
> Gabor Juhos wrote:
>> Based on the Ralink DPO_RT5572_LinuxSTA_2.6.0.1_20120629
>> driver.
>>
>> References:
>> NICInitRT3593BbpRegisters in chips/rt3593.c
>> NICInitBBP in common/rtmp_init.c
>> NICInitAsicFromEEPROM in common/rtmp_init.c
>>
>> Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
>> ---
>> drivers/net/wireless/rt2x00/rt2800lib.c | 19 +++++++++++++++++++
>> 1 file changed, 19 insertions(+)
>>
>> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
>> index 6f58ceb..32ecd1a 100644
>> --- a/drivers/net/wireless/rt2x00/rt2800lib.c
>> +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
>> @@ -4505,6 +4505,22 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev)
>> rt2800_disable_unused_dac_adc(rt2x00dev);
>> }
>>
>> +static void rt2800_init_bbp_3593(struct rt2x00_dev *rt2x00dev)
>> +{
>> + rt2800_init_bbp_early(rt2x00dev);
>> +
>> + rt2800_bbp_write(rt2x00dev, 79, 0x13);
>> + rt2800_bbp_write(rt2x00dev, 80, 0x05);
>> + rt2800_bbp_write(rt2x00dev, 81, 0x33);
>> + rt2800_bbp_write(rt2x00dev, 137, 0x0f);
>> +
>> + rt2800_bbp_write(rt2x00dev, 84, 0x19);
>> +
>> + /* Enable DC filter */
>> + if (rt2x00_rt_rev_gte(rt2x00dev, RT3593, REV_RT3593E))
>
> Where is REV_RT3593E defined?
>
> /tmp/backports-20130617/drivers/net/wireless/rt2x00/rt2800lib.c: In
> function ‘rt2800_init_bbp_3593’:
> /tmp/backports-20130617/drivers/net/wireless/rt2x00/rt2800lib.c:5325:43:
> error: ‘REV_RT3593E’ undeclared (first use in this function)
You are right, the patch-set should have contained 20 patches, but the first one
is missing. I will post that along with the second version of the series.
However if you want to try it in the meantime, you can find the patch in the
attachment. It must be applied before the other patches.
-Gabor
[-- Attachment #2: 0001-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch --]
[-- Type: text/x-patch, Size: 2227 bytes --]
>From 9afda5e728c713da1a3e55ba0860a3705e5a2cd6 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Thu, 9 May 2013 14:20:09 +0200
Subject: [PATCH v2 01/20] rt2x00: rt2800lib: add MAC register initialization
for RT3593
Based on the Ralink DPO_RT5572_LinuxSTA_2.6.0.1_20120629
driver.
Reference:
NICInitRT3593MacRegisters in chips/rt3593.c
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800.h | 1 +
drivers/net/wireless/rt2x00/rt2800lib.c | 17 +++++++++++++++++
2 files changed, 18 insertions(+)
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index 9216834..02bc80d 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -88,6 +88,7 @@
#define REV_RT3071E 0x0211
#define REV_RT3090E 0x0211
#define REV_RT3390E 0x0211
+#define REV_RT3593E 0x0211
#define REV_RT5390F 0x0502
#define REV_RT5390R 0x1502
#define REV_RT5592C 0x0221
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 7b216f9..6f58ceb 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -3715,6 +3715,23 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
} else if (rt2x00_rt(rt2x00dev, RT3572)) {
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+ } else if (rt2x00_rt(rt2x00dev, RT3593)) {
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
+ if (rt2x00_rt_rev_lt(rt2x00dev, RT3593, REV_RT3593E)) {
+ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1,
+ &eeprom);
+ if (rt2x00_get_field16(eeprom,
+ EEPROM_NIC_CONF1_DAC_TEST))
+ rt2800_register_write(rt2x00dev, TX_SW_CFG2,
+ 0x0000001f);
+ else
+ rt2800_register_write(rt2x00dev, TX_SW_CFG2,
+ 0x0000000f);
+ } else {
+ rt2800_register_write(rt2x00dev, TX_SW_CFG2,
+ 0x00000000);
+ }
} else if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392) ||
rt2x00_rt(rt2x00dev, RT5592)) {
--
1.7.10
^ permalink raw reply related
* Re: [rt2x00-users] [PATCH 01/19] rt2x00: rt2800lib: add BBP register initialization for RT3593
From: Andreas Hartmann @ 2013-06-29 5:25 UTC (permalink / raw)
To: Gabor Juhos, John Linville; +Cc: linux-wireless, users
In-Reply-To: <1372446753-11408-2-git-send-email-juhosg@openwrt.org>
Hi Gabor,
thanks for your submission. I tried to test it, but stuck at the problem
mentioned below.
Regards,
Andreas
Gabor Juhos wrote:
> Based on the Ralink DPO_RT5572_LinuxSTA_2.6.0.1_20120629
> driver.
>
> References:
> NICInitRT3593BbpRegisters in chips/rt3593.c
> NICInitBBP in common/rtmp_init.c
> NICInitAsicFromEEPROM in common/rtmp_init.c
>
> Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
> ---
> drivers/net/wireless/rt2x00/rt2800lib.c | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
> index 6f58ceb..32ecd1a 100644
> --- a/drivers/net/wireless/rt2x00/rt2800lib.c
> +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
> @@ -4505,6 +4505,22 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev)
> rt2800_disable_unused_dac_adc(rt2x00dev);
> }
>
> +static void rt2800_init_bbp_3593(struct rt2x00_dev *rt2x00dev)
> +{
> + rt2800_init_bbp_early(rt2x00dev);
> +
> + rt2800_bbp_write(rt2x00dev, 79, 0x13);
> + rt2800_bbp_write(rt2x00dev, 80, 0x05);
> + rt2800_bbp_write(rt2x00dev, 81, 0x33);
> + rt2800_bbp_write(rt2x00dev, 137, 0x0f);
> +
> + rt2800_bbp_write(rt2x00dev, 84, 0x19);
> +
> + /* Enable DC filter */
> + if (rt2x00_rt_rev_gte(rt2x00dev, RT3593, REV_RT3593E))
Where is REV_RT3593E defined?
/tmp/backports-20130617/drivers/net/wireless/rt2x00/rt2800lib.c: In
function ‘rt2800_init_bbp_3593’:
/tmp/backports-20130617/drivers/net/wireless/rt2x00/rt2800lib.c:5325:43:
error: ‘REV_RT3593E’ undeclared (first use in this function)
Thanks,
Andreas
^ permalink raw reply
* Re: [PATCH v3] iwl3945: better skb management in rx path
From: Steinar H. Gunderson @ 2013-06-28 23:05 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Paul Stewart, John W. Linville, linux-wireless, netdev
In-Reply-To: <1372431906.3301.283.camel@edumazet-glaptop>
2013/6/28 Eric Dumazet <eric.dumazet@gmail.com>:
> Steinar reported reallocations of skb->head with IPv6, leading to
> a warning in skb_try_coalesce()
>
> It turns out iwl3945 has several problems :
>
> 1) skb->truesize is underestimated.
> We really consume PAGE_SIZE bytes for a fragment,
> not the frame length.
> 2) 128 bytes of initial headroom is a bit low and forces reallocations.
> 3) We can avoid consuming a full page for small enough frames.
I'm running 3.9.8 plus this patch (hand-applied since GMail mangled
it…), and so far, it seems to work fine. Well, network-manager still
doesn't like Cisco's band-select feature, so from time to time I get
network freezes while it's trying to roam from 5 GHz to 2.4 GHz, but
that's hardly iwl3945's fault.
/* Steinar */
--
Software Engineer, Google Switzerland
^ permalink raw reply
* Re: [PATCH 19/19] rt2x00: rt2800usb: add USB device ID for Linksys AE3000
From: Xose Vazquez Perez @ 2013-06-28 22:26 UTC (permalink / raw)
To: Gabor Juhos, users@rt2x00.serialmonkey.com, linux-wireless
Gabor Juhos wrote:
> diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
> index c24c1fd..6136871 100644
> --- a/drivers/net/wireless/rt2x00/rt2800usb.c
> +++ b/drivers/net/wireless/rt2x00/rt2800usb.c
> @@ -1183,6 +1183,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
> { USB_DEVICE(0x04bb, 0x0944) },
> /* Linksys */
> { USB_DEVICE(0x13b1, 0x002f) },
> + { USB_DEVICE(0x13b1, 0x003b) },
> { USB_DEVICE(0x1737, 0x0079) },
> /* Ralink */
> { USB_DEVICE(0x148f, 0x3572) },
> --
You should separate RT3573 and RT3572 devices.
Rename CONFIG_RT2800USB_RT35XX to CONFIG_RT2800USB_RT3572
and do a new CONFIG_RT2800USB_RT3573 section.
And also you can add safely this usb-ids. All of them
are RT3573 devices:
0x1b75, 0x7733 AirLive 450Mbps Wireless-N Dual Band USB Adapter
0x0b05, 0x17bc ASUS USB-N66 450Mbps Dual Band USB Adapter
0x0b05, 0x17ad ASUS USB-N66 Dual Band N Network Adapter
0x050d, 0x1103 Belkin Wireless Adapter
0x148f, 0xf301 Cameo Ralink3573 3x3 single band USB dongle
0x7392, 0x7733 Edimax
0x0e66, 0x0020 Hawking HD45U Dual Band USB Wireless-N Adapter
0x0e66, 0x0021 Hawking HD45U Dual Band Wls-450N Adapter
0x04bb, 0x094e I-O DATA WN-AG450U Wireless LAN Adapter
0x0789, 0x016b Logitec LAN-W450AN/U2
0x0846, 0x9012 NETGEAR WNDA4100 N900 Wireless Dual Band USB Adapter
0x0846, 0x9019 NETGEAR WNDA4200D Wireless Dual Band USB Adapter
0x2019, 0xed19 Planex GW-USDual450
0x148f, 0x3573 Ralink 802.11n USB Wireless LAN Card
0x0df6, 0x0067 Sitecom Wireless Dualband Network Adapter N750 X6
0x0df6, 0x006a Sitecom Wireless Dualband Network Adapter N900 X7
0x0586, 0x3421 ZyXEL Dual-Band Wireless N450 USB Adapter
-thank you-
^ permalink raw reply
* Re: [PATCH 02/19] rt2x00: rt2800lib: add RFCSR register initialization for RT3593
From: Xose Vazquez Perez @ 2013-06-28 21:42 UTC (permalink / raw)
To: Gabor Juhos, linux-wireless, users@rt2x00.serialmonkey.com
Gabor Juhos wrote:
> Based on the Ralink DPO_RT5572_LinuxSTA_2.6.0.1_20120629
> driver.
There is a more recent version: DPO_RT5572_LinuxSTA_2.6.1.3_20121022
> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
> index 32ecd1a..0041b2c 100644
> --- a/drivers/net/wireless/rt2x00/rt2800lib.c
> +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
> [...]
> + /* Initialize default register values */
> + rt2800_rfcsr_write(rt2x00dev, 1, 0x03);
> + rt2800_rfcsr_write(rt2x00dev, 3, 0x80);
from ./20120911_RT3573_Linux_STA_v2.5.0.0_Rev1_DPO/chips/rt3593.c
{RF_R02, 0x80}
but it was deleted in ./DPO_RT5572_LinuxSTA_2.6.1.3_20121022/chips/rt3593.c
Was it deliberate ? or a mistake ??
^ permalink raw reply
* [PATCH v5 1/2] iw: use updated structures and enums for packet pattern
From: Bing Zhao @ 2013-06-28 19:53 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Amitkumar Karwar, Bing Zhao
From: Amitkumar Karwar <akarwar@marvell.com>
They are renamed in new nl80211.h so that they can be used for
new feature. This patch uses those updated structures and enums
to make the code look nicer.
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
depends on nl80211.h patch:
cfg80211/nl80211: rename packet pattern related structures and enums
v3: use new structure/enum names to make the code look nicer
v5: no change since v3. Resend as v5 series
info.c | 2 +-
wowlan.c | 32 ++++++++++++++++----------------
2 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/info.c b/info.c
index 54d9a8d..d893ffc 100644
--- a/info.c
+++ b/info.c
@@ -432,7 +432,7 @@ broken_combination:
[NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG },
[NL80211_WOWLAN_TRIG_TCP_CONNECTION] = { .type = NLA_NESTED },
};
- struct nl80211_wowlan_pattern_support *pat;
+ struct nl80211_pattern_support *pat;
int err;
err = nla_parse_nested(tb_wowlan, MAX_NL80211_WOWLAN_TRIG,
diff --git a/wowlan.c b/wowlan.c
index b4a2715..d323ca7 100644
--- a/wowlan.c
+++ b/wowlan.c
@@ -261,11 +261,11 @@ static int handle_wowlan_enable(struct nl80211_state *state, struct nl_cb *cb,
}
pattern = nla_nest_start(patterns, ++patnum);
- NLA_PUT(patterns, NL80211_WOWLAN_PKTPAT_MASK,
+ NLA_PUT(patterns, NL80211_PKTPAT_MASK,
DIV_ROUND_UP(patlen, 8), mask);
- NLA_PUT(patterns, NL80211_WOWLAN_PKTPAT_PATTERN,
- patlen, pat);
- NLA_PUT_U32(patterns, NL80211_WOWLAN_PKTPAT_OFFSET, pkt_offset);
+ NLA_PUT(patterns, NL80211_PKTPAT_PATTERN, patlen, pat);
+ NLA_PUT_U32(patterns, NL80211_PKTPAT_OFFSET,
+ pkt_offset);
nla_nest_end(patterns, pattern);
free(mask);
free(pat);
@@ -356,29 +356,29 @@ static int print_wowlan_handler(struct nl_msg *msg, void *arg)
nla_for_each_nested(pattern,
trig[NL80211_WOWLAN_TRIG_PKT_PATTERN],
rem_pattern) {
- struct nlattr *patattr[NUM_NL80211_WOWLAN_PKTPAT];
+ struct nlattr *patattr[NUM_NL80211_PKTPAT];
int i, patlen, masklen, pkt_offset;
uint8_t *mask, *pat;
- nla_parse(patattr, MAX_NL80211_WOWLAN_PKTPAT,
- nla_data(pattern), nla_len(pattern),
- NULL);
- if (!patattr[NL80211_WOWLAN_PKTPAT_MASK] ||
- !patattr[NL80211_WOWLAN_PKTPAT_PATTERN] ||
- !patattr[NL80211_WOWLAN_PKTPAT_OFFSET]) {
+ nla_parse(patattr, MAX_NL80211_PKTPAT,
+ nla_data(pattern), nla_len(pattern), NULL);
+ if (!patattr[NL80211_PKTPAT_MASK] ||
+ !patattr[NL80211_PKTPAT_PATTERN] ||
+ !patattr[NL80211_PKTPAT_OFFSET]) {
printf(" * (invalid pattern specification)\n");
continue;
}
- masklen = nla_len(patattr[NL80211_WOWLAN_PKTPAT_MASK]);
- patlen = nla_len(patattr[NL80211_WOWLAN_PKTPAT_PATTERN]);
- pkt_offset = nla_get_u32(patattr[NL80211_WOWLAN_PKTPAT_OFFSET]);
+ masklen = nla_len(patattr[NL80211_PKTPAT_MASK]);
+ patlen = nla_len(patattr[NL80211_PKTPAT_PATTERN]);
+ pkt_offset =
+ nla_get_u32(patattr[NL80211_PKTPAT_OFFSET]);
if (DIV_ROUND_UP(patlen, 8) != masklen) {
printf(" * (invalid pattern specification)\n");
continue;
}
printf(" * wake up on packet offset: %d", pkt_offset);
printf(" pattern: ");
- pat = nla_data(patattr[NL80211_WOWLAN_PKTPAT_PATTERN]);
- mask = nla_data(patattr[NL80211_WOWLAN_PKTPAT_MASK]);
+ pat = nla_data(patattr[NL80211_PKTPAT_PATTERN]);
+ mask = nla_data(patattr[NL80211_PKTPAT_MASK]);
for (i = 0; i < patlen; i++) {
if (mask[i / 8] & (1 << (i % 8)))
printf("%.2x", pat[i]);
--
1.8.0
^ permalink raw reply related
* [PATCH v5 2/2] iw: add coalesce support
From: Bing Zhao @ 2013-06-28 19:53 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Amitkumar Karwar, Bing Zhao
In-Reply-To: <1372449225-10652-1-git-send-email-bzhao@marvell.com>
From: Amitkumar Karwar <akarwar@marvell.com>
User can configure multiple coalesce rules using 'iw coalesce
enable <config-file>' command. The setting can be cleared using
'iw coalesce disable' command. 'iw coalesce show' displays current
configuration.
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
depends on nl80211.h patch:
cfg80211/nl80211: Add packet coalesce support
v3: match cfg80211/nl80211 structures v3 patchset
v5: match cfg80211/nl80211 structures v5 patchset
provide coalesce configurations through file
Makefile | 2 +-
coalesce.c | 285 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
info.c | 15 ++++
3 files changed, 301 insertions(+), 1 deletion(-)
create mode 100644 coalesce.c
diff --git a/Makefile b/Makefile
index c485b5e..f042e30 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ OBJS = iw.o genl.o event.o info.o phy.o \
interface.o ibss.o station.o survey.o util.o \
mesh.o mpath.o scan.o reg.o version.o \
reason.o status.o connect.o link.o offch.o ps.o cqm.o \
- bitrate.o wowlan.o roc.o p2p.o
+ bitrate.o wowlan.o coalesce.o roc.o p2p.o
OBJS += sections.o
OBJS-$(HWSIM) += hwsim.o
diff --git a/coalesce.c b/coalesce.c
new file mode 100644
index 0000000..22d1534
--- /dev/null
+++ b/coalesce.c
@@ -0,0 +1,285 @@
+#include <net/if.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+
+#include <arpa/inet.h>
+
+#include "nl80211.h"
+#include "iw.h"
+
+SECTION(coalesce);
+
+static int handle_coalesce_enable(struct nl80211_state *state, struct nl_cb *cb,
+ struct nl_msg *msg, int argc, char **argv,
+ enum id_input id)
+{
+ struct nlattr *nl_rules, *nl_rule = NULL, *nl_pats, *nl_pat;
+ unsigned char *pat, *mask;
+ size_t patlen;
+ int patnum = 0, pkt_offset, err = 1;
+ char *eptr, *value1, *value2, *sptr = NULL, *end, buf[16768];
+ enum nl80211_coalesce_condition condition;
+ FILE *f = fopen(argv[0], "r");
+ enum {
+ PS_DELAY,
+ PS_CONDITION,
+ PS_PATTERNS
+ } parse_state = PS_DELAY;
+ int rule_num = 0;
+
+ if (!f)
+ return 1;
+
+ nl_rules = nla_nest_start(msg, NL80211_ATTR_COALESCE_RULE);
+ if (!nl_rules)
+ return -ENOBUFS;
+
+ while (!feof(f)) {
+ char *eol;
+
+ if (!fgets(buf, sizeof(buf), f))
+ break;
+
+ eol = strchr(buf + 5, '\r');
+ if (eol)
+ *eol = 0;
+ eol = strchr(buf + 5, '\n');
+ if (eol)
+ *eol = 0;
+
+ switch (parse_state) {
+ case PS_DELAY:
+ if (strncmp(buf, "delay=", 6) == 0) {
+ char *delay = buf + 6;
+
+ rule_num++;
+ nl_rule = nla_nest_start(msg, rule_num);
+ if (!nl_rule)
+ goto close;
+
+ NLA_PUT_U32(msg, NL80211_ATTR_COALESCE_RULE_DELAY,
+ strtoul(delay, &end, 10));
+ if (*end != '\0')
+ goto close;
+ parse_state = PS_CONDITION;
+ } else {
+ goto close;
+ }
+ break;
+ case PS_CONDITION:
+ if (strncmp(buf, "condition=", 10) == 0) {
+ char *cond = buf + 10;
+
+ condition = strtoul(cond, &end, 10);
+ if (*end != '\0')
+ goto close;
+ NLA_PUT_U32(msg, NL80211_ATTR_COALESCE_RULE_CONDITION,
+ condition);
+ parse_state = PS_PATTERNS;
+ } else {
+ goto close;
+ }
+ break;
+ case PS_PATTERNS:
+ if (strncmp(buf, "patterns=", 9) == 0) {
+ char *cur_pat = buf + 9;
+ char *next_pat = strchr(buf + 9, ',');
+
+ if (next_pat) {
+ *next_pat = 0;
+ next_pat++;
+ }
+
+ nl_pats = nla_nest_start(msg, NL80211_ATTR_COALESCE_RULE_PKT_PATTERN);
+ while (1) {
+ value1 = strtok_r(cur_pat, "+", &sptr);
+ value2 = strtok_r(NULL, "+", &sptr);
+
+ if (!value2) {
+ pkt_offset = 0;
+ if (!value1)
+ goto close;
+ value2 = value1;
+ } else {
+ pkt_offset = strtoul(value1, &eptr, 10);
+ if (eptr != value1 + strlen(value1))
+ goto close;
+ }
+
+ if (parse_hex_mask(value2, &pat, &patlen, &mask))
+ goto close;
+
+ nl_pat = nla_nest_start(msg, ++patnum);
+ NLA_PUT(msg, NL80211_PKTPAT_MASK,
+ DIV_ROUND_UP(patlen, 8), mask);
+ NLA_PUT(msg, NL80211_PKTPAT_PATTERN, patlen, pat);
+ NLA_PUT_U32(msg, NL80211_PKTPAT_OFFSET,
+ pkt_offset);
+ nla_nest_end(msg, nl_pat);
+ free(mask);
+ free(pat);
+
+ if (!next_pat)
+ break;
+ cur_pat = next_pat;
+ next_pat = strchr(cur_pat, ',');
+ if (next_pat) {
+ *next_pat = 0;
+ next_pat++;
+ }
+ }
+ nla_nest_end(msg, nl_pats);
+ nla_nest_end(msg, nl_rule);
+ parse_state = PS_DELAY;
+
+ } else {
+ goto close;
+ }
+ break;
+ default:
+ if (buf[0] == '#')
+ continue;
+ goto close;
+ }
+ }
+
+ if (parse_state == PS_DELAY)
+ err = 0;
+ else
+ err = 1;
+ goto close;
+nla_put_failure:
+ err = -ENOBUFS;
+close:
+ fclose(f);
+ nla_nest_end(msg, nl_rules);
+ return err;
+}
+
+COMMAND(coalesce, enable, "<config-file>",
+ NL80211_CMD_SET_COALESCE, 0, CIB_PHY, handle_coalesce_enable,
+ "Enable coalesce with given configuration.\n"
+ "The configuration file contains coalesce rules:\n"
+ " delay=<delay>\n"
+ " condition=<condition>\n"
+ " patterns=<[offset1+]<pattern1>,<[offset2+]<pattern2>,...>\n"
+ " delay=<delay>\n"
+ " condition=<condition>\n"
+ " patterns=<[offset1+]<pattern1>,<[offset2+]<pattern2>,...>\n"
+ " ...\n"
+ "delay: maximum coalescing delay in msec.\n"
+ "condition: 0/1 i.e. 'not match'/'match' the patterns\n"
+ "patterns: each pattern is given as a bytestring with '-' in\n"
+ "places where any byte may be present, e.g. 00:11:22:-:44 will\n"
+ "match 00:11:22:33:44 and 00:11:22:33:ff:44 etc. Offset and\n"
+ "pattern should be separated by '+', e.g. 18+43:34:00:12 will\n"
+ "match '43:34:00:12' after 18 bytes of offset in Rx packet.\n");
+
+static int
+handle_coalesce_disable(struct nl80211_state *state, struct nl_cb *cb,
+ struct nl_msg *msg, int argc, char **argv,
+ enum id_input id)
+{
+ /* just a set w/o coalesce attribute */
+ return 0;
+}
+COMMAND(coalesce, disable, "", NL80211_CMD_SET_COALESCE, 0, CIB_PHY,
+ handle_coalesce_disable, "Disable coalesce.");
+
+static int print_coalesce_handler(struct nl_msg *msg, void *arg)
+{
+ struct nlattr *attrs[NL80211_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct nlattr *pattern, *rule;
+ int rem_pattern, rem_rule;
+ enum nl80211_coalesce_condition condition;
+ int delay;
+
+ nla_parse(attrs, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ if (!attrs[NL80211_ATTR_COALESCE_RULE]) {
+ printf("Coalesce is disabled.\n");
+ return NL_SKIP;
+ }
+
+ printf("Coalesce is enabled:\n");
+
+ nla_for_each_nested(rule, attrs[NL80211_ATTR_COALESCE_RULE], rem_rule) {
+ struct nlattr *ruleattr[NUM_NL80211_ATTR_COALESCE_RULE];
+
+ nla_parse(ruleattr, NL80211_ATTR_COALESCE_RULE_MAX,
+ nla_data(rule), nla_len(rule), NULL);
+
+ delay = nla_get_u32(ruleattr[NL80211_ATTR_COALESCE_RULE_DELAY]);
+ condition =
+ nla_get_u32(ruleattr[NL80211_ATTR_COALESCE_RULE_CONDITION]);
+
+ printf("Rule - max coalescing delay: %dmsec condition:", delay);
+ if (condition)
+ printf("match\n");
+ else
+ printf("not match\n");
+
+ if (ruleattr[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN]) {
+ nla_for_each_nested(pattern,
+ ruleattr[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
+ rem_pattern) {
+ struct nlattr *patattr[NUM_NL80211_PKTPAT];
+ int i, patlen, masklen, pkt_offset;
+ uint8_t *mask, *pat;
+
+ nla_parse(patattr, MAX_NL80211_PKTPAT,
+ nla_data(pattern), nla_len(pattern),
+ NULL);
+ if (!patattr[NL80211_PKTPAT_MASK] ||
+ !patattr[NL80211_PKTPAT_PATTERN] ||
+ !patattr[NL80211_PKTPAT_OFFSET]) {
+ printf(" * (invalid pattern specification)\n");
+ continue;
+ }
+ masklen = nla_len(patattr[NL80211_PKTPAT_MASK]);
+ patlen = nla_len(patattr[NL80211_PKTPAT_PATTERN]);
+ pkt_offset = nla_get_u32(patattr[NL80211_PKTPAT_OFFSET]);
+ if (DIV_ROUND_UP(patlen, 8) != masklen) {
+ printf(" * (invalid pattern specification)\n");
+ continue;
+ }
+ printf(" * packet offset: %d", pkt_offset);
+ printf(" pattern: ");
+ pat = nla_data(patattr[NL80211_PKTPAT_PATTERN]);
+ mask = nla_data(patattr[NL80211_PKTPAT_MASK]);
+ for (i = 0; i < patlen; i++) {
+ if (mask[i / 8] & (1 << (i % 8)))
+ printf("%.2x", pat[i]);
+ else
+ printf("--");
+ if (i != patlen - 1)
+ printf(":");
+ }
+ printf("\n");
+ }
+ }
+ }
+
+ return NL_SKIP;
+}
+
+static int handle_coalesce_show(struct nl80211_state *state, struct nl_cb *cb,
+ struct nl_msg *msg, int argc, char **argv,
+ enum id_input id)
+{
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
+ print_coalesce_handler, NULL);
+
+ return 0;
+}
+COMMAND(coalesce, show, "", NL80211_CMD_GET_COALESCE, 0, CIB_PHY, handle_coalesce_show,
+ "Show coalesce status.");
diff --git a/info.c b/info.c
index d893ffc..7e61e88 100644
--- a/info.c
+++ b/info.c
@@ -528,6 +528,21 @@ broken_combination:
printf("\tDevice supports AP scan.\n");
}
+ if (tb_msg[NL80211_ATTR_COALESCE_RULE]) {
+ struct nl80211_coalesce_rule_support *rule;
+ struct nl80211_pattern_support *pat;
+
+ printf("\tCoalesce support:\n");
+ rule = nla_data(tb_msg[NL80211_ATTR_COALESCE_RULE]);
+ pat = &rule->pat;
+ printf("\t\t * Maximum %u coalesce rules supported\n"
+ "\t\t * Each rule contains upto %u patterns of %u-%u bytes,\n"
+ "\t\t maximum packet offset %u bytes\n"
+ "\t\t * Maximum supported coalescing delay %u msecs\n",
+ rule->max_rules, pat->max_patterns, pat->min_pattern_len,
+ pat->max_pattern_len, pat->max_pkt_offset, rule->max_delay);
+ }
+
return NL_SKIP;
}
--
1.8.0
^ permalink raw reply related
* Re: Fwd: Re: TP-Link 8200ND - rtl8192cu module not loading / working
From: Larry Finger @ 2013-06-28 19:15 UTC (permalink / raw)
To: shiki.biomernok; +Cc: linux-wireless
In-Reply-To: <51CDD051.6060804@gmail.com>
On 06/28/2013 01:05 PM, shiki.biomernok wrote:
> Hello Larry!
>
> I'll only reply to you as you didn't CC the list with the driver (guess because
> it's unreleased.)
>
> Sadly, it isn't working either.
>
> http://pastebin.com/Tv00kCuZ
>
> No idea what could be the problem.
> But no need to waste more time with it, I'm pretty sure you have your things to
> do. I can just stick to the Intel one and that's all.
Just like the other driver, it authenticated and associated. I guess it never
got the IP address.
I just sent it to you due to the size of the driver, and the fact that it was
not released. I put this one back on the list.
I just ordered an 8200ND through E-Bay. I'll let you know what I find when it
arrives.
Larry
^ permalink raw reply
* [PATCH 19/19] rt2x00: rt2800usb: add USB device ID for Linksys AE3000
From: Gabor Juhos @ 2013-06-28 19:12 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1372446753-11408-1-git-send-email-juhosg@openwrt.org>
The Linksys AE3000 device is based on the RT3573
chipset. The support for this chipset is available
already, and the AE3000 device works with the driver.
Only managed mode works correctly at the moment,
for AP mode additional changes are needed in the
driver.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800usb.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index c24c1fd..6136871 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -1183,6 +1183,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x04bb, 0x0944) },
/* Linksys */
{ USB_DEVICE(0x13b1, 0x002f) },
+ { USB_DEVICE(0x13b1, 0x003b) },
{ USB_DEVICE(0x1737, 0x0079) },
/* Ralink */
{ USB_DEVICE(0x148f, 0x3572) },
--
1.7.10
^ permalink raw reply related
* [PATCH 18/19] rt2x00: rt2800usb: use correct [RT]XWI size for RT3593
From: Gabor Juhos @ 2013-06-28 19:12 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1372446753-11408-1-git-send-email-juhosg@openwrt.org>
The RT3593 chipset requires different [RT]XWI size
values. Modify the driver to use the correct values.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800.h | 1 +
drivers/net/wireless/rt2x00/rt2800usb.c | 5 ++++-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index 1ba797b..a313241 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -2814,6 +2814,7 @@ enum rt2800_eeprom_word {
#define TXWI_DESC_SIZE_5WORDS (5 * sizeof(__le32))
#define RXWI_DESC_SIZE_4WORDS (4 * sizeof(__le32))
+#define RXWI_DESC_SIZE_5WORDS (5 * sizeof(__le32))
#define RXWI_DESC_SIZE_6WORDS (6 * sizeof(__le32))
/*
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 840833b..c24c1fd 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -854,7 +854,10 @@ static void rt2800usb_queue_init(struct data_queue *queue)
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
unsigned short txwi_size, rxwi_size;
- if (rt2x00_rt(rt2x00dev, RT5592)) {
+ if (rt2x00_rt(rt2x00dev, RT3593)) {
+ txwi_size = TXWI_DESC_SIZE_4WORDS;
+ rxwi_size = RXWI_DESC_SIZE_5WORDS;
+ } else if (rt2x00_rt(rt2x00dev, RT5592)) {
txwi_size = TXWI_DESC_SIZE_5WORDS;
rxwi_size = RXWI_DESC_SIZE_6WORDS;
} else {
--
1.7.10
^ permalink raw reply related
* [PATCH 16/19] rt2x00: rt2800lib: enable RF3053 support
From: Gabor Juhos @ 2013-06-28 19:12 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1372446753-11408-1-git-send-email-juhosg@openwrt.org>
Support for the RF3053 has been implemented in
the previous changes, so it is safe to mark it
supported in the driver.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 0a0f96f..b7fa8f9 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -6949,6 +6949,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
case RF3021:
case RF3022:
case RF3052:
+ case RF3053:
case RF3290:
case RF3320:
case RF3322:
--
1.7.10
^ permalink raw reply related
* [PATCH 13/19] rt2x00: rt2800lib: add rf_vals for RF3053
From: Gabor Juhos @ 2013-06-28 19:12 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1372446753-11408-1-git-send-email-juhosg@openwrt.org>
Based on the Ralink DPO_RT5572_LinuxSTA_2.6.0.1_20120629
driver.
References:
FreqItems3053 in chips/rt3593.c
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 70 +++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index bc21a57..6dcf03a 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -6962,6 +6962,72 @@ static const struct rf_channel rf_vals_5592_xtal40[] = {
{196, 83, 0, 12, 1},
};
+static const struct rf_channel rf_vals_3053[] = {
+ /* Channel, N, R, K */
+ {1, 241, 2, 2},
+ {2, 241, 2, 7},
+ {3, 242, 2, 2},
+ {4, 242, 2, 7},
+ {5, 243, 2, 2},
+ {6, 243, 2, 7},
+ {7, 244, 2, 2},
+ {8, 244, 2, 7},
+ {9, 245, 2, 2},
+ {10, 245, 2, 7},
+ {11, 246, 2, 2},
+ {12, 246, 2, 7},
+ {13, 247, 2, 2},
+ {14, 248, 2, 4},
+
+ {36, 0x56, 0, 4},
+ {38, 0x56, 0, 6},
+ {40, 0x56, 0, 8},
+ {44, 0x57, 0, 0},
+ {46, 0x57, 0, 2},
+ {48, 0x57, 0, 4},
+ {52, 0x57, 0, 8},
+ {54, 0x57, 0, 10},
+ {56, 0x58, 0, 0},
+ {60, 0x58, 0, 4},
+ {62, 0x58, 0, 6},
+ {64, 0x58, 0, 8},
+
+ {100, 0x5B, 0, 8},
+ {102, 0x5B, 0, 10},
+ {104, 0x5C, 0, 0},
+ {108, 0x5C, 0, 4},
+ {110, 0x5C, 0, 6},
+ {112, 0x5C, 0, 8},
+
+ /* NOTE: Channel 114 has been removed intentionally.
+ * The EEPROM contains no TX power values for that,
+ * and it is disabled in the vendor driver as well.
+ */
+
+ {116, 0x5D, 0, 0},
+ {118, 0x5D, 0, 2},
+ {120, 0x5D, 0, 4},
+ {124, 0x5D, 0, 8},
+ {126, 0x5D, 0, 10},
+ {128, 0x5E, 0, 0},
+ {132, 0x5E, 0, 4},
+ {134, 0x5E, 0, 6},
+ {136, 0x5E, 0, 8},
+ {140, 0x5F, 0, 0},
+
+ {149, 0x5F, 0, 9},
+ {151, 0x5F, 0, 11},
+ {153, 0x60, 0, 1},
+ {157, 0x60, 0, 5},
+ {159, 0x60, 0, 7},
+ {161, 0x60, 0, 9},
+ {165, 0x61, 0, 1},
+ {167, 0x61, 0, 3},
+ {169, 0x61, 0, 5},
+ {171, 0x61, 0, 7},
+ {173, 0x61, 0, 9},
+};
+
static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
{
struct hw_mode_spec *spec = &rt2x00dev->spec;
@@ -7053,6 +7119,10 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
spec->supported_bands |= SUPPORT_BAND_5GHZ;
spec->num_channels = ARRAY_SIZE(rf_vals_3x);
spec->channels = rf_vals_3x;
+ } else if (rt2x00_rf(rt2x00dev, RF3053)) {
+ spec->supported_bands |= SUPPORT_BAND_5GHZ;
+ spec->num_channels = ARRAY_SIZE(rf_vals_3053);
+ spec->channels = rf_vals_3053;
} else if (rt2x00_rf(rt2x00dev, RF5592)) {
spec->supported_bands |= SUPPORT_BAND_5GHZ;
--
1.7.10
^ permalink raw reply related
* [PATCH 10/19] rt2x00: rt2800lib: hardcode TX mixer gain values for RT3593
From: Gabor Juhos @ 2013-06-28 19:12 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1372446753-11408-1-git-send-email-juhosg@openwrt.org>
The reference code uses hardcoded zero TX mixer gain value
for RT3593. Do the same in the rt2x00 driver.
Based on the Ralink DPO_RT5572_LinuxSTA_2.6.0.1_20120629
driver.
Reference:
NICReadEEPROMParameters in common/rtmp_init.c
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 6f23eb0..ea9b98d 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -6366,6 +6366,9 @@ static u8 rt2800_get_txmixer_gain_24g(struct rt2x00_dev *rt2x00dev)
{
u16 word;
+ if (rt2x00_rt(rt2x00dev, RT3593))
+ return 0;
+
rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word);
if ((word & 0x00ff) != 0x00ff)
return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL);
@@ -6377,6 +6380,9 @@ static u8 rt2800_get_txmixer_gain_5g(struct rt2x00_dev *rt2x00dev)
{
u16 word;
+ if (rt2x00_rt(rt2x00dev, RT3593))
+ return 0;
+
rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word);
if ((word & 0x00ff) != 0x00ff)
return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL);
--
1.7.10
^ permalink raw reply related
* [PATCH 09/19] rt2x00: rt2800lib: introduce rt2800_get_txmixer_gain_{24,5}g helpers
From: Gabor Juhos @ 2013-06-28 19:12 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1372446753-11408-1-git-send-email-juhosg@openwrt.org>
Move the TX mixer gain reading code into separate
helper functions in preparation for RT3593 support.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 38 +++++++++++++++++++------------
1 file changed, 24 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index cbc3dc3..6f23eb0 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -6362,6 +6362,28 @@ int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
}
EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse);
+static u8 rt2800_get_txmixer_gain_24g(struct rt2x00_dev *rt2x00dev)
+{
+ u16 word;
+
+ rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word);
+ if ((word & 0x00ff) != 0x00ff)
+ return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL);
+
+ return 0;
+}
+
+static u8 rt2800_get_txmixer_gain_5g(struct rt2x00_dev *rt2x00dev)
+{
+ u16 word;
+
+ rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word);
+ if ((word & 0x00ff) != 0x00ff)
+ return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL);
+
+ return 0;
+}
+
static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
{
struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
@@ -6456,13 +6478,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0);
rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word);
- rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word);
- if ((word & 0x00ff) != 0x00ff) {
- drv_data->txmixer_gain_24g =
- rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL);
- } else {
- drv_data->txmixer_gain_24g = 0;
- }
+ drv_data->txmixer_gain_24g = rt2800_get_txmixer_gain_24g(rt2x00dev);
rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
@@ -6473,13 +6489,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
default_lna_gain);
rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word);
- rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word);
- if ((word & 0x00ff) != 0x00ff) {
- drv_data->txmixer_gain_5g =
- rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL);
- } else {
- drv_data->txmixer_gain_5g = 0;
- }
+ drv_data->txmixer_gain_5g = rt2800_get_txmixer_gain_5g(rt2x00dev);
rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10)
--
1.7.10
^ permalink raw reply related
* [PATCH 07/19] rt2x00: rt2800lib: add rt2800_txpower_to_dev helper
From: Gabor Juhos @ 2013-06-28 19:12 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1372446753-11408-1-git-send-email-juhosg@openwrt.org>
Introduce a new helper function for converting
the default TX power values from EEPROM into
mac80211 values.
The change improves the readability and it makes
it easier to add support for other chipsets.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800.h | 6 ------
drivers/net/wireless/rt2x00/rt2800lib.c | 21 ++++++++++++++-------
2 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index 7b7caeb..d3e8f6d 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -2887,15 +2887,9 @@ enum rt2800_eeprom_word {
#define TXPOWER_G_FROM_DEV(__txpower) \
((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
-#define TXPOWER_G_TO_DEV(__txpower) \
- clamp_t(char, __txpower, MIN_G_TXPOWER, MAX_G_TXPOWER)
-
#define TXPOWER_A_FROM_DEV(__txpower) \
((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
-#define TXPOWER_A_TO_DEV(__txpower) \
- clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER)
-
/*
* Board's maximun TX power limitation
*/
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index fa5bbae..9d05273 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2725,6 +2725,16 @@ static void rt2800_iq_calibrate(struct rt2x00_dev *rt2x00dev, int channel)
rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0);
}
+static char rt2800_txpower_to_dev(struct rt2x00_dev *rt2x00dev,
+ unsigned int channel,
+ char txpower)
+{
+ if (channel <= 14)
+ return clamp_t(char, txpower, MIN_G_TXPOWER, MAX_G_TXPOWER);
+ else
+ return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER);
+}
+
static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf,
struct rf_channel *rf,
@@ -2734,13 +2744,10 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
unsigned int tx_pin;
u8 bbp, rfcsr;
- if (rf->channel <= 14) {
- info->default_power1 = TXPOWER_G_TO_DEV(info->default_power1);
- info->default_power2 = TXPOWER_G_TO_DEV(info->default_power2);
- } else {
- info->default_power1 = TXPOWER_A_TO_DEV(info->default_power1);
- info->default_power2 = TXPOWER_A_TO_DEV(info->default_power2);
- }
+ info->default_power1 = rt2800_txpower_to_dev(rt2x00dev, rf->channel,
+ info->default_power1);
+ info->default_power2 = rt2800_txpower_to_dev(rt2x00dev, rf->channel,
+ info->default_power2);
switch (rt2x00dev->chip.rf) {
case RF2020:
--
1.7.10
^ permalink raw reply related
* [PATCH 05/19] rt2x00: rt2800lib: fix BBP1_TX_ANTENNA field configuration for 3T devices
From: Gabor Juhos @ 2013-06-28 19:12 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1372446753-11408-1-git-send-email-juhosg@openwrt.org>
The field must be set to 2 instead of 0 for
devices with three TX chains.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index b6f456c..6f6f48f 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1764,7 +1764,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
break;
case 3:
- rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
+ rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
break;
}
--
1.7.10
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox