* [PATCH 2/2] mac80211: Populate radiotap header with MCS info for TX frames
From: Helmut Schaa @ 2011-10-11 16:08 UTC (permalink / raw)
To: linux-wireless; +Cc: linville, johannes, Helmut Schaa
In-Reply-To: <1318349335-22514-1-git-send-email-helmut.schaa@googlemail.com>
mac80211 already filled in the MCS rate info for rx'ed frames but tx'ed
frames that are sent to a monitor interface during the status callback
lack this information.
Add the radiotap fields for MCS info to ieee80211_tx_status_rtap_hdr
and populate them when sending tx'ed frames to the monitors.
The needed headroom is only extended by one byte since we don't include
legacy rate information in the rtap header for HT frames.
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
---
include/net/mac80211.h | 2 +-
net/mac80211/status.c | 23 +++++++++++++++++++++++
2 files changed, 24 insertions(+), 1 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index cd108df..b50fc1c 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2520,7 +2520,7 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta,
* The TX headroom reserved by mac80211 for its own tx_status functions.
* This is enough for the radiotap header.
*/
-#define IEEE80211_TX_STATUS_HEADROOM 13
+#define IEEE80211_TX_STATUS_HEADROOM 14
/**
* ieee80211_sta_set_buffered - inform mac80211 about driver-buffered frames
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index a9dc7b7..4b49ca7 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -242,6 +242,11 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info)
/* IEEE80211_RADIOTAP_DATA_RETRIES */
len += 1;
+
+ /* IEEE80211_TX_RC_MCS */
+ if (info->status.rates[0].idx >= 0 &&
+ info->status.rates[0].flags & IEEE80211_TX_RC_MCS)
+ len += 3;
return len;
}
@@ -299,6 +304,24 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band
/* for now report the total retry_count */
*pos = retry_count;
pos++;
+
+ /* IEEE80211_TX_RC_MCS */
+ if (info->status.rates[0].idx >= 0 &&
+ info->status.rates[0].flags & IEEE80211_TX_RC_MCS) {
+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
+ pos[0] = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
+ IEEE80211_RADIOTAP_MCS_HAVE_GI |
+ IEEE80211_RADIOTAP_MCS_HAVE_BW;
+ if (info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
+ pos[1] |= IEEE80211_RADIOTAP_MCS_SGI;
+ if (info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ pos[1] |= IEEE80211_RADIOTAP_MCS_BW_40;
+ if (info->status.rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD)
+ pos[1] |= IEEE80211_RADIOTAP_MCS_FMT_GF;
+ pos[2] = info->status.rates[0].idx;
+ pos += 3;
+ }
+
}
/*
--
1.7.3.4
^ permalink raw reply related
* [PATCH 1/2] mac80211: Build TX radiotap header dynamically
From: Helmut Schaa @ 2011-10-11 16:08 UTC (permalink / raw)
To: linux-wireless; +Cc: linville, johannes, Helmut Schaa
Get rid of the ieee80211_tx_status_rtap_hdr struct and instead build the
rtap header dynamically. This makes it easier to extend the rtap header
generation in the future.
Add ieee80211_tx_radiotap_len to calculate the expected size of the
rtap header before generating it. Since we can't check if the rtap
header fits into the requested headroom during compile time anymore
add a WARN_ON_ONCE.
Also move the actual rtap header generation into its own function.
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
---
net/mac80211/ieee80211_i.h | 12 -----
net/mac80211/main.c | 6 +--
net/mac80211/status.c | 112 ++++++++++++++++++++++++++++++--------------
3 files changed, 78 insertions(+), 52 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9fa5f8a..6e56dc8 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1178,18 +1178,6 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
struct net_device *dev);
-/*
- * radiotap header for status frames
- */
-struct ieee80211_tx_status_rtap_hdr {
- struct ieee80211_radiotap_header hdr;
- u8 rate;
- u8 padding_for_rate;
- __le16 tx_flags;
- u8 data_retries;
-} __packed;
-
-
/* HT */
void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
struct ieee80211_ht_cap *ht_cap_ie,
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 17b038a..d4ee6d2 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -904,12 +904,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
* and we need some headroom for passing the frame to monitor
* interfaces, but never both at the same time.
*/
-#ifndef __CHECKER__
- BUILD_BUG_ON(IEEE80211_TX_STATUS_HEADROOM !=
- sizeof(struct ieee80211_tx_status_rtap_hdr));
-#endif
local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
- sizeof(struct ieee80211_tx_status_rtap_hdr));
+ IEEE80211_TX_STATUS_HEADROOM);
debugfs_hw_add(local);
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 864a9c3..a9dc7b7 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -228,6 +228,79 @@ static void ieee80211_set_bar_pending(struct sta_info *sta, u8 tid, u16 ssn)
tid_tx->bar_pending = true;
}
+static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info)
+{
+ int len = sizeof(struct ieee80211_radiotap_header);
+
+ /* IEEE80211_RADIOTAP_RATE rate */
+ if (info->status.rates[0].idx >= 0 &&
+ !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS))
+ len += 2;
+
+ /* IEEE80211_RADIOTAP_TX_FLAGS */
+ len += 2;
+
+ /* IEEE80211_RADIOTAP_DATA_RETRIES */
+ len += 1;
+
+ return len;
+}
+
+static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band
+ *sband, struct sk_buff *skb,
+ int retry_count, int rtap_len)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_radiotap_header *rthdr;
+ unsigned char *pos;
+ __le16 txflags;
+
+ rthdr = (struct ieee80211_radiotap_header *) skb_push(skb, rtap_len);
+
+ memset(rthdr, 0, rtap_len);
+ rthdr->it_len = cpu_to_le16(rtap_len);
+ rthdr->it_present =
+ cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
+ (1 << IEEE80211_RADIOTAP_DATA_RETRIES));
+ pos = (unsigned char *)(rthdr + 1);
+
+ /*
+ * XXX: Once radiotap gets the bitmap reset thing the vendor
+ * extensions proposal contains, we can actually report
+ * the whole set of tries we did.
+ */
+
+ /* IEEE80211_RADIOTAP_RATE */
+ if (info->status.rates[0].idx >= 0 &&
+ !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) {
+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
+ *pos = sband->bitrates[info->status.rates[0].idx].bitrate / 5;
+ /* padding for tx flags */
+ pos += 2;
+ }
+
+ /* IEEE80211_RADIOTAP_TX_FLAGS */
+ txflags = 0;
+ if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
+ !is_multicast_ether_addr(hdr->addr1))
+ txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL);
+
+ if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+ (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
+ txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS);
+ else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
+ txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS);
+
+ put_unaligned_le16(txflags, pos);
+ pos += 2;
+
+ /* IEEE80211_RADIOTAP_DATA_RETRIES */
+ /* for now report the total retry_count */
+ *pos = retry_count;
+ pos++;
+}
+
/*
* Use a static threshold for now, best value to be determined
* by testing ...
@@ -246,7 +319,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
u16 frag, type;
__le16 fc;
struct ieee80211_supported_band *sband;
- struct ieee80211_tx_status_rtap_hdr *rthdr;
struct ieee80211_sub_if_data *sdata;
struct net_device *prev_dev = NULL;
struct sta_info *sta, *tmp;
@@ -256,6 +328,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
bool acked;
struct ieee80211_bar *bar;
u16 tid;
+ int rtap_len;
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
if (info->status.rates[i].idx < 0) {
@@ -460,44 +533,13 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
}
/* send frame to monitor interfaces now */
-
- if (skb_headroom(skb) < sizeof(*rthdr)) {
+ rtap_len = ieee80211_tx_radiotap_len(info);
+ if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
printk(KERN_ERR "ieee80211_tx_status: headroom too small\n");
dev_kfree_skb(skb);
return;
}
-
- rthdr = (struct ieee80211_tx_status_rtap_hdr *)
- skb_push(skb, sizeof(*rthdr));
-
- memset(rthdr, 0, sizeof(*rthdr));
- rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
- rthdr->hdr.it_present =
- cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
- (1 << IEEE80211_RADIOTAP_DATA_RETRIES) |
- (1 << IEEE80211_RADIOTAP_RATE));
-
- if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
- !is_multicast_ether_addr(hdr->addr1))
- rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL);
-
- /*
- * XXX: Once radiotap gets the bitmap reset thing the vendor
- * extensions proposal contains, we can actually report
- * the whole set of tries we did.
- */
- if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
- (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
- rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS);
- else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
- rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS);
- if (info->status.rates[0].idx >= 0 &&
- !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS))
- rthdr->rate = sband->bitrates[
- info->status.rates[0].idx].bitrate / 5;
-
- /* for now report the total retry_count */
- rthdr->data_retries = retry_count;
+ ieee80211_add_tx_radiotap_header(sband, skb, retry_count, rtap_len);
/* XXX: is this sufficient for BPF? */
skb_set_mac_header(skb, 0);
--
1.7.3.4
^ permalink raw reply related
* RE: [PATCH 17/34] iwlagn: fix a race in the unmapping of the TFDs
From: Grumbach, Emmanuel @ 2011-10-11 14:43 UTC (permalink / raw)
To: Stanislaw Gruszka
Cc: Guy, Wey-Yi W, linville@tuxdriver.com,
linux-wireless@vger.kernel.org
In-Reply-To: <20111011125810.GC2218@redhat.com>
>
> On Tue, Oct 11, 2011 at 02:38:52PM +0200, Grumbach, Emmanuel wrote:
> > > Why not simply take hcmd_lock?
> >
> > Hcmd_lock is related to the host command queue only, it won't work for Tx
> queues.
>
> So you only fix reces between
> iwl_trans_pcie_tx()/iwl_tx_queue_reclaim() and iwl_tx_queue_unmap().
> Races between
> iwl_enqueue_hcmd()/iwl_cmd_queue_reclaim() and iwl_tx_queue_unmap()
> are unresolved.
>
Thanks. Patch is on the way (has been submitted internally).
---------------------------------------------------------------------
Intel Israel (74) Limited
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply
* Re: [PATCH] wl12xx: remove warning message during IBSS Tx
From: Luciano Coelho @ 2011-10-11 14:43 UTC (permalink / raw)
To: Shahar Lev; +Cc: linux-wireless
In-Reply-To: <1318004245-18347-1-git-send-email-shahar@wizery.com>
On Fri, 2011-10-07 at 18:17 +0200, Shahar Lev wrote:
> mac80211 sets the carrier on an IBSS interface even when no network is
> joined. Ignore garbage frames transmitted on a disconnected IBSS
> interface without printing warnings.
>
> Signed-off-by: Shahar Lev <shahar@wizery.com>
> ---
Applied, thanks!
--
Cheers,
Luca.
^ permalink raw reply
* [PATCH v2 5/5] ath6kl: Allow CCKM AKM and KRK to be configured
From: Jouni Malinen @ 2011-10-11 14:31 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Jouni Malinen
In-Reply-To: <1318343517-15292-1-git-send-email-jouni@qca.qualcomm.com>
Use vendor-specific suite selectors to allow CCKM to be configured.
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath6kl/cfg80211.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index b7b2c57..6b30b75 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -121,6 +121,8 @@ static struct ieee80211_supported_band ath6kl_band_5ghz = {
.bitrates = ath6kl_a_rates,
};
+#define CCKM_KRK_CIPHER_SUITE 0x004096ff /* use for KRK */
+
static int ath6kl_set_wpa_version(struct ath6kl *ar,
enum nl80211_wpa_versions wpa_version)
{
@@ -217,6 +219,11 @@ static void ath6kl_set_key_mgmt(struct ath6kl *ar, u32 key_mgmt)
ar->auth_mode = WPA_PSK_AUTH;
else if (ar->auth_mode == WPA2_AUTH)
ar->auth_mode = WPA2_PSK_AUTH;
+ } else if (key_mgmt == 0x00409600) {
+ if (ar->auth_mode == WPA_AUTH)
+ ar->auth_mode = WPA_AUTH_CCKM;
+ else if (ar->auth_mode == WPA2_AUTH)
+ ar->auth_mode = WPA2_AUTH_CCKM;
} else if (key_mgmt != WLAN_AKM_SUITE_8021X) {
ar->auth_mode = NONE_AUTH;
}
@@ -758,6 +765,12 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
if (!ath6kl_cfg80211_ready(ar))
return -EIO;
+ if (params->cipher == CCKM_KRK_CIPHER_SUITE) {
+ if (params->key_len != WMI_KRK_LEN)
+ return -EINVAL;
+ return ath6kl_wmi_add_krk_cmd(ar->wmi, params->key);
+ }
+
if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
"%s: key index %d out of bounds\n", __func__,
@@ -1228,6 +1241,7 @@ static const u32 cipher_suites[] = {
WLAN_CIPHER_SUITE_WEP104,
WLAN_CIPHER_SUITE_TKIP,
WLAN_CIPHER_SUITE_CCMP,
+ CCKM_KRK_CIPHER_SUITE,
};
static bool is_rate_legacy(s32 rate)
--
1.7.4.1
^ permalink raw reply related
* [PATCH v2 4/5] ath6kl: Add debugfs control for keepalive and disconnection timeout
From: Jouni Malinen @ 2011-10-11 14:31 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Jouni Malinen
In-Reply-To: <1318343517-15292-1-git-send-email-jouni@qca.qualcomm.com>
The new debugfs files keepalive and disconnect_timeout can be used to
fetch the current values and to change the values for keepalive and
disconnect event timeout (both in seconds).
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath6kl/core.h | 3 +
drivers/net/wireless/ath/ath6kl/debug.c | 95 +++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath6kl/debug.h | 11 ++++
drivers/net/wireless/ath/ath6kl/wmi.c | 4 +
4 files changed, 113 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index c58cfad..31e5c7e 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -533,6 +533,9 @@ struct ath6kl {
u8 *roam_tbl;
unsigned int roam_tbl_len;
+
+ u8 keepalive;
+ u8 disc_timeout;
} debug;
#endif /* CONFIG_ATH6KL_DEBUG */
};
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index 41161ca..7b1c9ae 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -1149,6 +1149,95 @@ static const struct file_operations fops_roam_mode = {
.llseek = default_llseek,
};
+void ath6kl_debug_set_keepalive(struct ath6kl *ar, u8 keepalive)
+{
+ ar->debug.keepalive = keepalive;
+}
+
+static ssize_t ath6kl_keepalive_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ char buf[16];
+ int len;
+
+ len = snprintf(buf, sizeof(buf), "%u\n", ar->debug.keepalive);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ath6kl_keepalive_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ int ret;
+ u8 val;
+
+ ret = kstrtou8_from_user(user_buf, count, 0, &val);
+ if (ret)
+ return ret;
+
+ ret = ath6kl_wmi_set_keepalive_cmd(ar->wmi, val);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static const struct file_operations fops_keepalive = {
+ .open = ath6kl_debugfs_open,
+ .read = ath6kl_keepalive_read,
+ .write = ath6kl_keepalive_write,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+void ath6kl_debug_set_disconnect_timeout(struct ath6kl *ar, u8 timeout)
+{
+ ar->debug.disc_timeout = timeout;
+}
+
+static ssize_t ath6kl_disconnect_timeout_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ char buf[16];
+ int len;
+
+ len = snprintf(buf, sizeof(buf), "%u\n", ar->debug.disc_timeout);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ath6kl_disconnect_timeout_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ int ret;
+ u8 val;
+
+ ret = kstrtou8_from_user(user_buf, count, 0, &val);
+ if (ret)
+ return ret;
+
+ ret = ath6kl_wmi_disctimeout_cmd(ar->wmi, val);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static const struct file_operations fops_disconnect_timeout = {
+ .open = ath6kl_debugfs_open,
+ .read = ath6kl_disconnect_timeout_read,
+ .write = ath6kl_disconnect_timeout_write,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
int ath6kl_debug_init(struct ath6kl *ar)
{
ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE);
@@ -1216,6 +1305,12 @@ int ath6kl_debug_init(struct ath6kl *ar)
debugfs_create_file("roam_mode", S_IWUSR, ar->debugfs_phy, ar,
&fops_roam_mode);
+ debugfs_create_file("keepalive", S_IRUSR | S_IWUSR, ar->debugfs_phy, ar,
+ &fops_keepalive);
+
+ debugfs_create_file("disconnect_timeout", S_IRUSR | S_IWUSR,
+ ar->debugfs_phy, ar, &fops_disconnect_timeout);
+
return 0;
}
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
index f73bf15..7d5323d 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.h
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -92,6 +92,8 @@ void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len);
void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war);
int ath6kl_debug_roam_tbl_event(struct ath6kl *ar, const void *buf,
size_t len);
+void ath6kl_debug_set_keepalive(struct ath6kl *ar, u8 keepalive);
+void ath6kl_debug_set_disconnect_timeout(struct ath6kl *ar, u8 timeout);
int ath6kl_debug_init(struct ath6kl *ar);
void ath6kl_debug_cleanup(struct ath6kl *ar);
@@ -133,6 +135,15 @@ static inline int ath6kl_debug_roam_tbl_event(struct ath6kl *ar,
return 0;
}
+static inline void ath6kl_debug_set_keepalive(struct ath6kl *ar, u8 keepalive)
+{
+}
+
+static inline void ath6kl_debug_set_disconnect_timeout(struct ath6kl *ar,
+ u8 timeout)
+{
+}
+
static inline int ath6kl_debug_init(struct ath6kl *ar)
{
return 0;
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 3fb2702..7b6bfdd 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -1940,6 +1940,8 @@ int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 timeout)
ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_DISC_TIMEOUT_CMDID,
NO_SYNC_WMIFLAG);
+ if (ret == 0)
+ ath6kl_debug_set_disconnect_timeout(wmi->parent_dev, timeout);
return ret;
}
@@ -2524,6 +2526,8 @@ int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl)
ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_KEEPALIVE_CMDID,
NO_SYNC_WMIFLAG);
+ if (ret == 0)
+ ath6kl_debug_set_keepalive(wmi->parent_dev, keep_alive_intvl);
return ret;
}
--
1.7.4.1
^ permalink raw reply related
* [PATCH v2 3/5] ath6kl: Add debugfs files for roaming control
From: Jouni Malinen @ 2011-10-11 14:31 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Jouni Malinen
In-Reply-To: <1318343517-15292-1-git-send-email-jouni@qca.qualcomm.com>
Roaming mode can be changed by writing roam mode (default, bssbias, or
lock) to roam_mode. Forced roam can be requested by writing the BSSID
into force_roam.
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath6kl/debug.c | 84 +++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath6kl/wmi.c | 40 +++++++++++++++
drivers/net/wireless/ath/ath6kl/wmi.h | 21 ++++++--
3 files changed, 139 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index cec958a..41161ca 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -1071,6 +1071,84 @@ static const struct file_operations fops_roam_table = {
.llseek = default_llseek,
};
+static ssize_t ath6kl_force_roam_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ int ret;
+ char buf[20];
+ size_t len;
+ u8 bssid[ETH_ALEN];
+ int i;
+ int addr[ETH_ALEN];
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+ buf[len] = '\0';
+
+ if (sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
+ &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5])
+ != ETH_ALEN)
+ return -EINVAL;
+ for (i = 0; i < ETH_ALEN; i++)
+ bssid[i] = addr[i];
+
+ ret = ath6kl_wmi_force_roam_cmd(ar->wmi, bssid);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static const struct file_operations fops_force_roam = {
+ .write = ath6kl_force_roam_write,
+ .open = ath6kl_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t ath6kl_roam_mode_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ int ret;
+ char buf[20];
+ size_t len;
+ enum wmi_roam_mode mode;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+ buf[len] = '\0';
+ if (len > 0 && buf[len - 1] == '\n')
+ buf[len - 1] = '\0';
+
+ if (strcasecmp(buf, "default") == 0)
+ mode = WMI_DEFAULT_ROAM_MODE;
+ else if (strcasecmp(buf, "bssbias") == 0)
+ mode = WMI_HOST_BIAS_ROAM_MODE;
+ else if (strcasecmp(buf, "lock") == 0)
+ mode = WMI_LOCK_BSS_MODE;
+ else
+ return -EINVAL;
+
+ ret = ath6kl_wmi_set_roam_mode_cmd(ar->wmi, mode);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static const struct file_operations fops_roam_mode = {
+ .write = ath6kl_roam_mode_write,
+ .open = ath6kl_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
int ath6kl_debug_init(struct ath6kl *ar)
{
ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE);
@@ -1132,6 +1210,12 @@ int ath6kl_debug_init(struct ath6kl *ar)
debugfs_create_file("roam_table", S_IRUSR, ar->debugfs_phy, ar,
&fops_roam_table);
+ debugfs_create_file("force_roam", S_IWUSR, ar->debugfs_phy, ar,
+ &fops_force_roam);
+
+ debugfs_create_file("roam_mode", S_IWUSR, ar->debugfs_phy, ar,
+ &fops_roam_mode);
+
return 0;
}
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 4021527..3fb2702 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -682,6 +682,46 @@ int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi)
return 0;
}
+int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid)
+{
+ struct sk_buff *skb;
+ struct roam_ctrl_cmd *cmd;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct roam_ctrl_cmd *) skb->data;
+ memset(cmd, 0, sizeof(*cmd));
+
+ memcpy(cmd->info.bssid, bssid, ETH_ALEN);
+ cmd->roam_ctrl = WMI_FORCE_ROAM;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "force roam to %pM\n", bssid);
+ return ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_ROAM_CTRL_CMDID,
+ NO_SYNC_WMIFLAG);
+}
+
+int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode)
+{
+ struct sk_buff *skb;
+ struct roam_ctrl_cmd *cmd;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct roam_ctrl_cmd *) skb->data;
+ memset(cmd, 0, sizeof(*cmd));
+
+ cmd->info.roam_mode = mode;
+ cmd->roam_ctrl = WMI_SET_ROAM_MODE;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "set roam mode %d\n", mode);
+ return ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_ROAM_CTRL_CMDID,
+ NO_SYNC_WMIFLAG);
+}
+
static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len)
{
struct wmi_connect_event *ev;
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index f986da1..f0ca899 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -1354,14 +1354,20 @@ enum wmi_roam_ctrl {
WMI_SET_LRSSI_SCAN_PARAMS,
};
+enum wmi_roam_mode {
+ WMI_DEFAULT_ROAM_MODE = 1, /* RSSI based roam */
+ WMI_HOST_BIAS_ROAM_MODE = 2, /* Host bias based roam */
+ WMI_LOCK_BSS_MODE = 3, /* Lock to the current BSS */
+};
+
struct bss_bias {
u8 bssid[ETH_ALEN];
- u8 bias;
+ s8 bias;
} __packed;
struct bss_bias_info {
u8 num_bss;
- struct bss_bias bss_bias[1];
+ struct bss_bias bss_bias[0];
} __packed;
struct low_rssi_scan_params {
@@ -1374,10 +1380,11 @@ struct low_rssi_scan_params {
struct roam_ctrl_cmd {
union {
- u8 bssid[ETH_ALEN];
- u8 roam_mode;
- struct bss_bias_info bss;
- struct low_rssi_scan_params params;
+ u8 bssid[ETH_ALEN]; /* WMI_FORCE_ROAM */
+ u8 roam_mode; /* WMI_SET_ROAM_MODE */
+ struct bss_bias_info bss; /* WMI_SET_HOST_BIAS */
+ struct low_rssi_scan_params params; /* WMI_SET_LRSSI_SCAN_PARAMS
+ */
} __packed info;
u8 roam_ctrl;
} __packed;
@@ -2237,6 +2244,8 @@ s32 ath6kl_wmi_get_rate(s8 rate_index);
int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd);
int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);
+int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid);
+int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode);
/* AP mode */
int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, struct wmi_connect_cmd *p);
--
1.7.4.1
^ permalink raw reply related
* [PATCH v2 0/5] ath6kl: Debugging and roaming
From: Jouni Malinen @ 2011-10-11 14:31 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Jouni Malinen
This set of patches adds some more ath6kl debugging information and
control to debugfs and enables additional roaming functionality.
v2 addresses the comments from Kalle to move debug functionality in
patches 2 and 4 to debug.c.
Jouni Malinen (5):
ath6kl: Add endpoint_stats debugfs file
ath6kl: Add debugfs file for target roam table
ath6kl: Add debugfs files for roaming control
ath6kl: Add debugfs control for keepalive and disconnection timeout
ath6kl: Allow CCKM AKM and KRK to be configured
drivers/net/wireless/ath/ath6kl/cfg80211.c | 14 +
drivers/net/wireless/ath/ath6kl/core.h | 7 +
drivers/net/wireless/ath/ath6kl/debug.c | 390 ++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath6kl/debug.h | 19 ++
drivers/net/wireless/ath/ath6kl/wmi.c | 55 ++++
drivers/net/wireless/ath/ath6kl/wmi.h | 28 ++-
6 files changed, 507 insertions(+), 6 deletions(-)
--
1.7.4.1
^ permalink raw reply
* [PATCH v2 2/5] ath6kl: Add debugfs file for target roam table
From: Jouni Malinen @ 2011-10-11 14:31 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Jouni Malinen
In-Reply-To: <1318343517-15292-1-git-send-email-jouni@qca.qualcomm.com>
The new roam_table debugfs file can be used to display the current
roam table from the target.
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath6kl/core.h | 4 +
drivers/net/wireless/ath/ath6kl/debug.c | 109 +++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath6kl/debug.h | 8 ++
drivers/net/wireless/ath/ath6kl/wmi.c | 11 +++
drivers/net/wireless/ath/ath6kl/wmi.h | 7 ++
5 files changed, 139 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 6d8a484..c58cfad 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -397,6 +397,7 @@ struct ath6kl_req_key {
#define TESTMODE 13
#define CLEAR_BSSFILTER_ON_BEACON 14
#define DTIM_PERIOD_AVAIL 15
+#define ROAM_TBL_PEND 16
struct ath6kl {
struct device *dev;
@@ -529,6 +530,9 @@ struct ath6kl {
struct {
unsigned int invalid_rate;
} war_stats;
+
+ u8 *roam_tbl;
+ unsigned int roam_tbl_len;
} debug;
#endif /* CONFIG_ATH6KL_DEBUG */
};
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index b9bf28d..cec958a 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -966,6 +966,111 @@ static const struct file_operations fops_diag_reg_write = {
.llseek = default_llseek,
};
+int ath6kl_debug_roam_tbl_event(struct ath6kl *ar, const void *buf,
+ size_t len)
+{
+ const struct wmi_target_roam_tbl *tbl;
+ u16 num_entries;
+
+ if (len < sizeof(*tbl))
+ return -EINVAL;
+
+ tbl = (const struct wmi_target_roam_tbl *) buf;
+ num_entries = le16_to_cpu(tbl->num_entries);
+ if (sizeof(*tbl) + num_entries * sizeof(struct wmi_bss_roam_info) >
+ len)
+ return -EINVAL;
+
+ if (ar->debug.roam_tbl == NULL ||
+ ar->debug.roam_tbl_len < (unsigned int) len) {
+ kfree(ar->debug.roam_tbl);
+ ar->debug.roam_tbl = kmalloc(len, GFP_ATOMIC);
+ if (ar->debug.roam_tbl == NULL)
+ return -ENOMEM;
+ }
+
+ memcpy(ar->debug.roam_tbl, buf, len);
+ ar->debug.roam_tbl_len = len;
+
+ if (test_bit(ROAM_TBL_PEND, &ar->flag)) {
+ clear_bit(ROAM_TBL_PEND, &ar->flag);
+ wake_up(&ar->event_wq);
+ }
+
+ return 0;
+}
+
+static ssize_t ath6kl_roam_table_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ int ret;
+ long left;
+ struct wmi_target_roam_tbl *tbl;
+ u16 num_entries, i;
+ char *buf;
+ unsigned int len, buf_len;
+ ssize_t ret_cnt;
+
+ if (down_interruptible(&ar->sem))
+ return -EBUSY;
+
+ set_bit(ROAM_TBL_PEND, &ar->flag);
+
+ ret = ath6kl_wmi_get_roam_tbl_cmd(ar->wmi);
+ if (ret) {
+ up(&ar->sem);
+ return ret;
+ }
+
+ left = wait_event_interruptible_timeout(
+ ar->event_wq, !test_bit(ROAM_TBL_PEND, &ar->flag), WMI_TIMEOUT);
+ up(&ar->sem);
+
+ if (left <= 0)
+ return -ETIMEDOUT;
+
+ if (ar->debug.roam_tbl == NULL)
+ return -ENOMEM;
+
+ tbl = (struct wmi_target_roam_tbl *) ar->debug.roam_tbl;
+ num_entries = le16_to_cpu(tbl->num_entries);
+
+ buf_len = 100 + num_entries * 100;
+ buf = kzalloc(buf_len, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+ len = 0;
+ len += scnprintf(buf + len, buf_len - len,
+ "roam_mode=%u\n\n"
+ "# roam_util bssid rssi rssidt last_rssi util bias\n",
+ le16_to_cpu(tbl->roam_mode));
+
+ for (i = 0; i < num_entries; i++) {
+ struct wmi_bss_roam_info *info = &tbl->info[i];
+ len += scnprintf(buf + len, buf_len - len,
+ "%d %pM %d %d %d %d %d\n",
+ a_sle32_to_cpu(info->roam_util), info->bssid,
+ info->rssi, info->rssidt, info->last_rssi,
+ info->util, info->bias);
+ }
+
+ if (len > buf_len)
+ len = buf_len;
+
+ ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+
+ kfree(buf);
+ return ret_cnt;
+}
+
+static const struct file_operations fops_roam_table = {
+ .read = ath6kl_roam_table_read,
+ .open = ath6kl_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
int ath6kl_debug_init(struct ath6kl *ar)
{
ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE);
@@ -1024,6 +1129,9 @@ int ath6kl_debug_init(struct ath6kl *ar)
debugfs_create_file("war_stats", S_IRUSR, ar->debugfs_phy, ar,
&fops_war_stats);
+ debugfs_create_file("roam_table", S_IRUSR, ar->debugfs_phy, ar,
+ &fops_roam_table);
+
return 0;
}
@@ -1031,6 +1139,7 @@ void ath6kl_debug_cleanup(struct ath6kl *ar)
{
vfree(ar->debug.fwlog_buf.buf);
kfree(ar->debug.fwlog_tmp);
+ kfree(ar->debug.roam_tbl);
}
#endif
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
index e3740b0..f73bf15 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.h
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -90,6 +90,8 @@ void ath6kl_dump_registers(struct ath6kl_device *dev,
void dump_cred_dist_stats(struct htc_target *target);
void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len);
void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war);
+int ath6kl_debug_roam_tbl_event(struct ath6kl *ar, const void *buf,
+ size_t len);
int ath6kl_debug_init(struct ath6kl *ar);
void ath6kl_debug_cleanup(struct ath6kl *ar);
@@ -125,6 +127,12 @@ static inline void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war)
{
}
+static inline int ath6kl_debug_roam_tbl_event(struct ath6kl *ar,
+ const void *buf, size_t len)
+{
+ return 0;
+}
+
static inline int ath6kl_debug_init(struct ath6kl *ar)
{
return 0;
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index ab782d7..4021527 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -2407,6 +2407,11 @@ int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi)
return ath6kl_wmi_simple_cmd(wmi, WMI_GET_TX_PWR_CMDID);
}
+int ath6kl_wmi_get_roam_tbl_cmd(struct wmi *wmi)
+{
+ return ath6kl_wmi_simple_cmd(wmi, WMI_GET_ROAM_TBL_CMDID);
+}
+
int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status, u8 preamble_policy)
{
struct sk_buff *skb;
@@ -2844,6 +2849,11 @@ static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
return ret;
}
+static int ath6kl_wmi_roam_tbl_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ return ath6kl_debug_roam_tbl_event(wmi->parent_dev, datap, len);
+}
+
/* Control Path */
int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
{
@@ -2948,6 +2958,7 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
break;
case WMI_REPORT_ROAM_TBL_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_TBL_EVENTID\n");
+ ret = ath6kl_wmi_roam_tbl_event_rx(wmi, datap, len);
break;
case WMI_EXTENSION_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_EXTENSION_EVENTID\n");
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index 96102c6..f986da1 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -1624,6 +1624,12 @@ struct wmi_bss_roam_info {
u8 reserved;
} __packed;
+struct wmi_target_roam_tbl {
+ __le16 roam_mode;
+ __le16 num_entries;
+ struct wmi_bss_roam_info info[];
+} __packed;
+
/* WMI_CAC_EVENTID */
enum cac_indication {
CAC_INDICATION_ADMISSION = 0x00,
@@ -2221,6 +2227,7 @@ int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, const u8 *bssid,
const u8 *pmkid, bool set);
int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 dbM);
int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi);
+int ath6kl_wmi_get_roam_tbl_cmd(struct wmi *wmi);
int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg);
int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl);
--
1.7.4.1
^ permalink raw reply related
* [PATCH v2 1/5] ath6kl: Add endpoint_stats debugfs file
From: Jouni Malinen @ 2011-10-11 14:31 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Jouni Malinen
In-Reply-To: <1318343517-15292-1-git-send-email-jouni@qca.qualcomm.com>
This file can be used to fetch endpoint statistics counters and
to clear them by writing 0 to it.
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath6kl/debug.c | 102 +++++++++++++++++++++++++++++++
1 files changed, 102 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index ba3f23d..b9bf28d 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -595,6 +595,105 @@ static const struct file_operations fops_credit_dist_stats = {
.llseek = default_llseek,
};
+static unsigned int print_endpoint_stat(struct htc_target *target, char *buf,
+ unsigned int buf_len, unsigned int len,
+ int offset, const char *name)
+{
+ int i;
+ struct htc_endpoint_stats *ep_st;
+ u32 *counter;
+
+ len += scnprintf(buf + len, buf_len - len, "%s:", name);
+ for (i = 0; i < ENDPOINT_MAX; i++) {
+ ep_st = &target->endpoint[i].ep_st;
+ counter = ((u32 *) ep_st) + (offset / 4);
+ len += scnprintf(buf + len, buf_len - len, " %u", *counter);
+ }
+ len += scnprintf(buf + len, buf_len - len, "\n");
+
+ return len;
+}
+
+static ssize_t ath6kl_endpoint_stats_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ struct htc_target *target = ar->htc_target;
+ char *buf;
+ unsigned int buf_len, len = 0;
+ ssize_t ret_cnt;
+
+ buf_len = 1000 + ENDPOINT_MAX * 100;
+ buf = kzalloc(buf_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+#define EPSTAT(name) \
+ len = print_endpoint_stat(target, buf, buf_len, len, \
+ offsetof(struct htc_endpoint_stats, name), \
+ #name)
+ EPSTAT(cred_low_indicate);
+ EPSTAT(tx_issued);
+ EPSTAT(tx_pkt_bundled);
+ EPSTAT(tx_bundles);
+ EPSTAT(tx_dropped);
+ EPSTAT(tx_cred_rpt);
+ EPSTAT(cred_rpt_from_rx);
+ EPSTAT(cred_rpt_ep0);
+ EPSTAT(cred_from_rx);
+ EPSTAT(cred_from_other);
+ EPSTAT(cred_from_ep0);
+ EPSTAT(cred_cosumd);
+ EPSTAT(cred_retnd);
+ EPSTAT(rx_pkts);
+ EPSTAT(rx_lkahds);
+ EPSTAT(rx_bundl);
+ EPSTAT(rx_bundle_lkahd);
+ EPSTAT(rx_bundle_from_hdr);
+ EPSTAT(rx_alloc_thresh_hit);
+ EPSTAT(rxalloc_thresh_byte);
+#undef EPSTAT
+
+ if (len > buf_len)
+ len = buf_len;
+
+ ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+ return ret_cnt;
+}
+
+static ssize_t ath6kl_endpoint_stats_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ struct htc_target *target = ar->htc_target;
+ int ret, i;
+ u32 val;
+ struct htc_endpoint_stats *ep_st;
+
+ ret = kstrtou32_from_user(user_buf, count, 0, &val);
+ if (ret)
+ return ret;
+ if (val == 0) {
+ for (i = 0; i < ENDPOINT_MAX; i++) {
+ ep_st = &target->endpoint[i].ep_st;
+ memset(ep_st, 0, sizeof(*ep_st));
+ }
+ }
+
+ return count;
+}
+
+static const struct file_operations fops_endpoint_stats = {
+ .open = ath6kl_debugfs_open,
+ .read = ath6kl_endpoint_stats_read,
+ .write = ath6kl_endpoint_stats_write,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
static unsigned long ath6kl_get_num_reg(void)
{
int i;
@@ -901,6 +1000,9 @@ int ath6kl_debug_init(struct ath6kl *ar)
debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar,
&fops_credit_dist_stats);
+ debugfs_create_file("endpoint_stats", S_IRUSR | S_IWUSR,
+ ar->debugfs_phy, ar, &fops_endpoint_stats);
+
debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar,
&fops_fwlog);
--
1.7.4.1
^ permalink raw reply related
* Re: [PATCH 1/2] wl12xx: sdio: use dev_dbg instead of wl1271_debug
From: Luciano Coelho @ 2011-10-11 13:22 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <1317987297-18172-1-git-send-email-coelho@ti.com>
On Fri, 2011-10-07 at 14:34 +0300, Luciano Coelho wrote:
> To prevent a useless dependency between the sdio module and the wl12xx
> module, we need to replace the wl1271_debug macros (and friends) for
> dev_dbg and other equivalents.
>
> At the same time, remove the SDIO data hexdump, since this produces
> way too much data and is not particularly useful. There's not
> print_hex_dump() equivalent for dynamic debug, so it's hard to control
> when the dumps are printed out.
>
> Signed-off-by: Luciano Coelho <coelho@ti.com>
> ---
Applied both.
--
Cheers,
Luca.
^ permalink raw reply
* Re: [PATCH] wl12xx: move debugging definitions to a separate file
From: Luciano Coelho @ 2011-10-11 13:20 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <1318085047.9690.32.camel@cumari>
On Sat, 2011-10-08 at 17:44 +0300, Luciano Coelho wrote:
> On Fri, 2011-10-07 at 11:13 +0300, Luciano Coelho wrote:
> > Separate the debugging macros and other definitions to a new debug.h
> > file. This is be needed because the sdio and spi modules don't need
> > to depend on the wl12xx module anymore, but still need to include
> > wl12xx.h. Currently they do depend on it, because of the debugging
> > global that wl12xx exports. A future patch will remove this
> > dependency.
> >
> > Signed-off-by: Luciano Coelho <coelho@ti.com>
> > ---
>
> These defines should be in debug.h as well:
>
> #define DRIVER_NAME "wl1271"
> #define DRIVER_PREFIX DRIVER_NAME ": "
>
> I'll move them too and rename wl1271 to wl12xx when I apply.
Applied.
--
Cheers,
Luca.
^ permalink raw reply
* Re: [PATCH 0/8] wl12xx: forward ported Balbi's bus driver refactor
From: Luciano Coelho @ 2011-10-11 13:05 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <1317928259-26437-1-git-send-email-coelho@ti.com>
On Thu, 2011-10-06 at 22:10 +0300, Luciano Coelho wrote:
> Hi,
>
> Felipe sent this series of patches a long time ago with very good
> suggestion on how to avoid the duplicate code we have in the sdio and
> spi drivers.
>
> With this, we create a platform device that is handled by a platform
> driver. The bus-specific module, creates a platform device and the
> core module implements the driver that supports both platform devices
> (namely "wl12xx-sdio" and "wl12xx-spi").
>
> I didn't apply this earlier because I had concerns about the change in
> the platform data, but now I'm convinced it's not a real problem. It
> may affect compat-wireless, but it's easy to solve.
>
> I have now forward-ported the patches, fixed some bugs, removed some
> style changes and moved some other things around. For the changes I
> made, see the commit message of each patch. Some changes are not in
> the commit message, but are explained in the patch emails, after the
> Signed-off-by area.
>
> I'm keeping Felipe as the author, since most of the work is his. I
> have just tested and fixed it up.
>
> Cheers,
> Luca.
>
> Felipe Balbi (8):
> wl12xx: add an sdio glue struct to keep wl and device side-by-side
> wl12xx: add an spi glue struct to keep wl and device side-by-side
> wl12xx: add a platform device to the sdio module
> wl12xx: add a platform device to the spi module
> wl12xx: add platform driver to the core module
> wl12xx: move common init code from bus modules to main
> wl12xx: mark some symbols static
> wl12xx: drop unneeded plat_dev
Applied the whole series.
--
Cheers,
Luca.
^ permalink raw reply
* Re: [PATCH 17/34] iwlagn: fix a race in the unmapping of the TFDs
From: Stanislaw Gruszka @ 2011-10-11 12:58 UTC (permalink / raw)
To: Grumbach, Emmanuel
Cc: Guy, Wey-Yi W, linville@tuxdriver.com,
linux-wireless@vger.kernel.org
In-Reply-To: <4825B8A2C4E264489E57869F0DCFB2234457A944F2@hasmsx502.ger.corp.intel.com>
On Tue, Oct 11, 2011 at 02:38:52PM +0200, Grumbach, Emmanuel wrote:
> > Why not simply take hcmd_lock?
>
> Hcmd_lock is related to the host command queue only, it won't work for Tx queues.
So you only fix reces between
iwl_trans_pcie_tx()/iwl_tx_queue_reclaim() and iwl_tx_queue_unmap().
Races between
iwl_enqueue_hcmd()/iwl_cmd_queue_reclaim() and iwl_tx_queue_unmap()
are unresolved.
Stanislaw
^ permalink raw reply
* Re: [PATCH 00/29] make the driver ready for multi-vif support
From: Luciano Coelho @ 2011-10-11 12:52 UTC (permalink / raw)
To: Eliad Peller; +Cc: linux-wireless
In-Reply-To: <1318234397-21081-1-git-send-email-eliad@wizery.com>
On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
> This patchset finishes adding multiple vif support to the
> wl12xx driver.
>
> The driver still allows only a single vif, as the current
> fw only supports a single vif.
>
> This patchset doesn't break compatibility with the current fw.
Applied, thanks! With the following small changes:
* used v2 of 08/29;
* used '(foo - bar) & 0xff' instead of '(foo - bar + 256) % 256'.
--
Cheers,
Luca.
^ permalink raw reply
* RE: [PATCH 17/34] iwlagn: fix a race in the unmapping of the TFDs
From: Grumbach, Emmanuel @ 2011-10-11 12:38 UTC (permalink / raw)
To: Stanislaw Gruszka
Cc: Guy, Wey-Yi W, linville@tuxdriver.com,
linux-wireless@vger.kernel.org
In-Reply-To: <20111011123630.GB2218@redhat.com>
> > > > While inspecting the code, I saw that iwl_tx_queue_unmap modifies
> > > > the read pointer of the Tx queue without taking any locks. This means
> > > > that it can race with the reclaim flow. This can possibly lead to
> > > > a DMA warning complaining that we unmap the same buffer twice.
> > > >
> > > > This is more a W/A than a fix since it is really weird to take
> > > > sta_lock inside iwl_tx_queue_unmap, but it can help until we revamp
> > > > the locking model in the transport layer.
> > > >
> > > > Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
> > > > Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
> > > > ---
> > > > drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 3 +++
> > > > 1 files changed, 3 insertions(+), 0 deletions(-)
> > > >
> > > > diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
> > > b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
> > > > index 60067c7..f69aecb 100644
> > > > --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
> > > > +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
> > > > @@ -406,6 +406,7 @@ static void iwl_tx_queue_unmap(struct iwl_trans
> > > *trans, int txq_id)
> > > > struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
> > > > struct iwl_queue *q = &txq->q;
> > > > enum dma_data_direction dma_dir;
> > > > + unsigned long flags;
> > > >
> > > > if (!q->n_bd)
> > > > return;
> > > > @@ -418,12 +419,14 @@ static void iwl_tx_queue_unmap(struct iwl_trans
> > > *trans, int txq_id)
> > > > else
> > > > dma_dir = DMA_TO_DEVICE;
> > > >
> > > > + spin_lock_irqsave(&trans->shrd->sta_lock, flags);
> > > sta_lock does not look like right lock to use.
> > >
> > True. And I wrote in the commit message that this is a W/A until we
> revamp the locking model.
>
> Why not simply take hcmd_lock?
Hcmd_lock is related to the host command queue only, it won't work for Tx queues.
---------------------------------------------------------------------
Intel Israel (74) Limited
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply
* Re: [PATCH 17/34] iwlagn: fix a race in the unmapping of the TFDs
From: Stanislaw Gruszka @ 2011-10-11 12:36 UTC (permalink / raw)
To: Grumbach, Emmanuel
Cc: Guy, Wey-Yi W, linville@tuxdriver.com,
linux-wireless@vger.kernel.org
In-Reply-To: <4825B8A2C4E264489E57869F0DCFB2234457A944D0@hasmsx502.ger.corp.intel.com>
On Tue, Oct 11, 2011 at 02:26:30PM +0200, Grumbach, Emmanuel wrote:
> >
> > On Mon, Oct 10, 2011 at 07:27:02AM -0700, Wey-Yi Guy wrote:
> > > While inspecting the code, I saw that iwl_tx_queue_unmap modifies
> > > the read pointer of the Tx queue without taking any locks. This means
> > > that it can race with the reclaim flow. This can possibly lead to
> > > a DMA warning complaining that we unmap the same buffer twice.
> > >
> > > This is more a W/A than a fix since it is really weird to take
> > > sta_lock inside iwl_tx_queue_unmap, but it can help until we revamp
> > > the locking model in the transport layer.
> > >
> > > Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
> > > Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
> > > ---
> > > drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 3 +++
> > > 1 files changed, 3 insertions(+), 0 deletions(-)
> > >
> > > diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
> > b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
> > > index 60067c7..f69aecb 100644
> > > --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
> > > +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
> > > @@ -406,6 +406,7 @@ static void iwl_tx_queue_unmap(struct iwl_trans
> > *trans, int txq_id)
> > > struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
> > > struct iwl_queue *q = &txq->q;
> > > enum dma_data_direction dma_dir;
> > > + unsigned long flags;
> > >
> > > if (!q->n_bd)
> > > return;
> > > @@ -418,12 +419,14 @@ static void iwl_tx_queue_unmap(struct iwl_trans
> > *trans, int txq_id)
> > > else
> > > dma_dir = DMA_TO_DEVICE;
> > >
> > > + spin_lock_irqsave(&trans->shrd->sta_lock, flags);
> > sta_lock does not look like right lock to use.
> >
> True. And I wrote in the commit message that this is a W/A until we revamp the locking model.
Why not simply take hcmd_lock?
^ permalink raw reply
* RE: [PATCH 17/34] iwlagn: fix a race in the unmapping of the TFDs
From: Grumbach, Emmanuel @ 2011-10-11 12:26 UTC (permalink / raw)
To: Stanislaw Gruszka, Guy, Wey-Yi W
Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org
In-Reply-To: <20111011122216.GA2218@redhat.com>
>
> On Mon, Oct 10, 2011 at 07:27:02AM -0700, Wey-Yi Guy wrote:
> > While inspecting the code, I saw that iwl_tx_queue_unmap modifies
> > the read pointer of the Tx queue without taking any locks. This means
> > that it can race with the reclaim flow. This can possibly lead to
> > a DMA warning complaining that we unmap the same buffer twice.
> >
> > This is more a W/A than a fix since it is really weird to take
> > sta_lock inside iwl_tx_queue_unmap, but it can help until we revamp
> > the locking model in the transport layer.
> >
> > Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
> > Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
> > ---
> > drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 3 +++
> > 1 files changed, 3 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
> b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
> > index 60067c7..f69aecb 100644
> > --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
> > +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
> > @@ -406,6 +406,7 @@ static void iwl_tx_queue_unmap(struct iwl_trans
> *trans, int txq_id)
> > struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
> > struct iwl_queue *q = &txq->q;
> > enum dma_data_direction dma_dir;
> > + unsigned long flags;
> >
> > if (!q->n_bd)
> > return;
> > @@ -418,12 +419,14 @@ static void iwl_tx_queue_unmap(struct iwl_trans
> *trans, int txq_id)
> > else
> > dma_dir = DMA_TO_DEVICE;
> >
> > + spin_lock_irqsave(&trans->shrd->sta_lock, flags);
> sta_lock does not look like right lock to use.
>
True. And I wrote in the commit message that this is a W/A until we revamp the locking model.
---------------------------------------------------------------------
Intel Israel (74) Limited
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply
* Re: [PATCH 17/34] iwlagn: fix a race in the unmapping of the TFDs
From: Stanislaw Gruszka @ 2011-10-11 12:22 UTC (permalink / raw)
To: Wey-Yi Guy; +Cc: linville, linux-wireless, Emmanuel Grumbach
In-Reply-To: <1318256839-31837-18-git-send-email-wey-yi.w.guy@intel.com>
On Mon, Oct 10, 2011 at 07:27:02AM -0700, Wey-Yi Guy wrote:
> While inspecting the code, I saw that iwl_tx_queue_unmap modifies
> the read pointer of the Tx queue without taking any locks. This means
> that it can race with the reclaim flow. This can possibly lead to
> a DMA warning complaining that we unmap the same buffer twice.
>
> This is more a W/A than a fix since it is really weird to take
> sta_lock inside iwl_tx_queue_unmap, but it can help until we revamp
> the locking model in the transport layer.
>
> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
> ---
> drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 3 +++
> 1 files changed, 3 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
> index 60067c7..f69aecb 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
> @@ -406,6 +406,7 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id)
> struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
> struct iwl_queue *q = &txq->q;
> enum dma_data_direction dma_dir;
> + unsigned long flags;
>
> if (!q->n_bd)
> return;
> @@ -418,12 +419,14 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id)
> else
> dma_dir = DMA_TO_DEVICE;
>
> + spin_lock_irqsave(&trans->shrd->sta_lock, flags);
sta_lock does not look like right lock to use.
Stanislaw
^ permalink raw reply
* Re: [PATCH 4/5] ath6kl: Add debugfs control for keepalive and disconnection timeout
From: Kalle Valo @ 2011-10-11 11:55 UTC (permalink / raw)
To: Jouni Malinen; +Cc: linux-wireless
In-Reply-To: <1318243411-16110-5-git-send-email-jouni@qca.qualcomm.com>
On 10/10/2011 01:43 PM, Jouni Malinen wrote:
> The new debugfs files keepalive and disconnect_timeout can be used to
> fetch the current values and to change the values for keepalive and
> disconnect event timeout (both in seconds).
[...]
> --- a/drivers/net/wireless/ath/ath6kl/wmi.c
> +++ b/drivers/net/wireless/ath/ath6kl/wmi.c
> @@ -1940,6 +1940,10 @@ int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 timeout)
>
> ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_DISC_TIMEOUT_CMDID,
> NO_SYNC_WMIFLAG);
> +#ifdef CONFIG_ATH6KL_DEBUG
> + if (ret == 0)
> + wmi->parent_dev->debug.disc_timeout = timeout;
> +#endif /* CONFIG_ATH6KL_DEBUG */
> return ret;
> }
>
> @@ -2524,6 +2528,10 @@ int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl)
>
> ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_KEEPALIVE_CMDID,
> NO_SYNC_WMIFLAG);
> +#ifdef CONFIG_ATH6KL_DEBUG
> + if (ret == 0)
> + wmi->parent_dev->debug.keepalive = keep_alive_intvl;
> +#endif /* CONFIG_ATH6KL_DEBUG */
Similar comment for these two as well. It would better to have the code
in debug.c (or .h) and add functions for providing this information.
Kalle
^ permalink raw reply
* Re: [PATCH] mac80211: Populate radiotap header with MCS info for tx'ed frames
From: Helmut Schaa @ 2011-10-11 11:52 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, linville
In-Reply-To: <1318333875.3965.10.camel@jlt3.sipsolutions.net>
On Tue, Oct 11, 2011 at 1:51 PM, Johannes Berg
<johannes@sipsolutions.net> wrote:
>> Or should we just get rid of the whole struct and fill in the
>> rtap header dynamically like it is done in the rx path and
>> drop the build-bug-on thing?
>
> I wouldn't mind that either, but we'll want to have a WARN_ON_ONCE()
> somewhere if we run out of space.
Ok, let's try it that way. John please drop this one, I'll do a v2.
Helmut
^ permalink raw reply
* [PATCH] wl12xx: handle injected packets
From: Eliad Peller @ 2011-10-11 11:52 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
Injected packets are sent with no vif, causing the wl12xx
to NULL-dereference in multiple places.
Furthermore, injected packets are currently not sent at all,
as system_hlid doesn't belong to any specific role, so
wl1271_skb_dequeue() never return its packets.
Handle both these problems.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
thanks Johannes for providing a testing app
drivers/net/wireless/wl12xx/main.c | 7 +++++--
drivers/net/wireless/wl12xx/tx.c | 27 +++++++++++++--------------
2 files changed, 18 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 692a275..fc652c4 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1517,11 +1517,14 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
struct wl1271 *wl = hw->priv;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif;
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ struct wl12xx_vif *wlvif = NULL;
unsigned long flags;
int q, mapping;
u8 hlid;
+ if (vif)
+ wlvif = wl12xx_vif_to_data(vif);
+
mapping = skb_get_queue_mapping(skb);
q = wl1271_tx_get_queue(mapping);
@@ -1531,7 +1534,7 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
/* queue the packet */
if (hlid == WL12XX_INVALID_LINK_ID ||
- !test_bit(hlid, wlvif->links_map)) {
+ (wlvif && !test_bit(hlid, wlvif->links_map))) {
wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", hlid, q);
dev_kfree_skb(skb);
goto out;
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 02d606f..33b800d 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -180,7 +180,7 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif,
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- if (wl12xx_is_dummy_packet(wl, skb))
+ if (!wlvif || wl12xx_is_dummy_packet(wl, skb))
return wl->system_hlid;
if (wlvif->bss_type == BSS_TYPE_AP_BSS)
@@ -259,7 +259,8 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
wl->tx_allocated_pkts[ac]++;
- if (!is_dummy && wlvif->bss_type == BSS_TYPE_AP_BSS &&
+ if (!is_dummy && wlvif &&
+ wlvif->bss_type == BSS_TYPE_AP_BSS &&
test_bit(hlid, wlvif->ap.sta_hlid_map))
wl->links[hlid].allocated_pkts++;
@@ -302,7 +303,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
desc->start_time = cpu_to_le32(hosttime - wl->time_offset);
is_dummy = wl12xx_is_dummy_packet(wl, skb);
- if (is_dummy || wlvif->bss_type != BSS_TYPE_AP_BSS)
+ if (is_dummy || !wlvif || wlvif->bss_type != BSS_TYPE_AP_BSS)
desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU);
else
desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU);
@@ -321,14 +322,14 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
TX_HW_ATTR_SESSION_COUNTER;
tx_attr |= TX_HW_ATTR_TX_DUMMY_REQ;
- } else {
+ } else if (wlvif) {
/* configure the tx attributes */
tx_attr = wlvif->session_counter <<
TX_HW_ATTR_OFST_SESSION_COUNTER;
}
desc->hlid = hlid;
- if (is_dummy)
+ if (is_dummy || !wlvif)
rate_idx = 0;
else if (wlvif->bss_type != BSS_TYPE_AP_BSS) {
/* if the packets are destined for AP (have a STA entry)
@@ -433,7 +434,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
wl1271_tx_fill_hdr(wl, wlvif, skb, extra, info, hlid);
- if (!is_dummy && wlvif->bss_type == BSS_TYPE_AP_BSS) {
+ if (!is_dummy && wlvif && wlvif->bss_type == BSS_TYPE_AP_BSS) {
wl1271_tx_ap_update_inconnection_sta(wl, skb);
wl1271_tx_regulate_link(wl, wlvif, hlid);
}
@@ -610,6 +611,9 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
}
}
+ if (!skb)
+ skb = wl12xx_lnk_skb_dequeue(wl, &wl->links[wl->system_hlid]);
+
if (!skb &&
test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) {
int q;
@@ -703,19 +707,14 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
return;
while ((skb = wl1271_skb_dequeue(wl))) {
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
bool has_data = false;
wlvif = NULL;
- if (!wl12xx_is_dummy_packet(wl, skb)) {
- struct ieee80211_tx_info *info;
- struct ieee80211_vif *vif;
+ if (!wl12xx_is_dummy_packet(wl, skb) && info->control.vif)
+ wlvif = wl12xx_vif_to_data(info->control.vif);
- info = IEEE80211_SKB_CB(skb);
- vif = info->control.vif;
- wlvif = wl12xx_vif_to_data(vif);
- }
has_data = wlvif && wl1271_tx_is_data_present(skb);
-
ret = wl1271_prepare_tx_frame(wl, wlvif, skb, buf_offset);
if (ret == -EAGAIN) {
/*
--
1.7.6.401.g6a319
^ permalink raw reply related
* Re: [PATCH] mac80211: Populate radiotap header with MCS info for tx'ed frames
From: Johannes Berg @ 2011-10-11 11:51 UTC (permalink / raw)
To: Helmut Schaa; +Cc: linux-wireless, linville
In-Reply-To: <CAGXE3d8cuBg28PfMYQcAJ96oTEqUg6rG8ExUr+Sezq51eM2J_Q@mail.gmail.com>
On Tue, 2011-10-11 at 13:48 +0200, Helmut Schaa wrote:
> On Tue, Oct 11, 2011 at 1:35 PM, Johannes Berg
> <johannes@sipsolutions.net> wrote:
> > So using something like
> > this would allow us to save some space as well:
> >
> > struct ieee80211_tx_status_rtap_hdr {
> > struct ieee80211_radiotap_header hdr;
> > union {
> > struct {
> > u8 rate;
> > u8 padding_for_rate;
> > __le16 tx_flags;
> > u8 data_retries;
> > } non_mcs;
> > struct {
> > __le16 tx_flags;
> > u8 data_retries;
> > u8 mcs_known, mcs_flags, mcs;
> > } mcs;
> > }
> > } __packed;
>
> I thought about the same but this means we have to fill in
> different fields (non_mcs.tx_flags vs mcs.tx_flags) for the MCS
> vs legacy path and set the radiotap header len differently in
> both cases.
Good point.
> Or should we just get rid of the whole struct and fill in the
> rtap header dynamically like it is done in the rx path and
> drop the build-bug-on thing?
I wouldn't mind that either, but we'll want to have a WARN_ON_ONCE()
somewhere if we run out of space.
johannes
^ permalink raw reply
* Re: [PATCH] mac80211: Populate radiotap header with MCS info for tx'ed frames
From: Helmut Schaa @ 2011-10-11 11:48 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, linville
In-Reply-To: <1318332927.3965.9.camel@jlt3.sipsolutions.net>
On Tue, Oct 11, 2011 at 1:35 PM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> So using something like
> this would allow us to save some space as well:
>
> struct ieee80211_tx_status_rtap_hdr {
> struct ieee80211_radiotap_header hdr;
> union {
> struct {
> u8 rate;
> u8 padding_for_rate;
> __le16 tx_flags;
> u8 data_retries;
> } non_mcs;
> struct {
> __le16 tx_flags;
> u8 data_retries;
> u8 mcs_known, mcs_flags, mcs;
> } mcs;
> }
> } __packed;
I thought about the same but this means we have to fill in
different fields (non_mcs.tx_flags vs mcs.tx_flags) for the MCS
vs legacy path and set the radiotap header len differently in
both cases.
Or should we just get rid of the whole struct and fill in the
rtap header dynamically like it is done in the rx path and
drop the build-bug-on thing?
Helmut
^ permalink raw reply
* Re: [PATCH 2/5] ath6kl: Add debugfs file for target roam table
From: Kalle Valo @ 2011-10-11 11:39 UTC (permalink / raw)
To: Jouni Malinen; +Cc: linux-wireless
In-Reply-To: <1318243411-16110-3-git-send-email-jouni@qca.qualcomm.com>
On 10/10/2011 01:43 PM, Jouni Malinen wrote:
> The new roam_table debugfs file can be used to display the current
> roam table from the target.
One comment:
> +static int ath6kl_wmi_roam_tbl_event_rx(struct wmi *wmi, u8 *datap, int len)
> +{
> +#ifdef CONFIG_ATH6KL_DEBUG
> + struct ath6kl *ar = wmi->parent_dev;
> + struct wmi_target_roam_tbl *tbl;
> + u16 num_entries;
> +
> + if (len < sizeof(*tbl))
> + return -EINVAL;
> +
> + tbl = (struct wmi_target_roam_tbl *) datap;
> + num_entries = le16_to_cpu(tbl->num_entries);
> + if (sizeof(*tbl) + num_entries * sizeof(struct wmi_bss_roam_info) > len)
> + return -EINVAL;
> +
> + if (ar->debug.roam_tbl == NULL ||
> + ar->debug.roam_tbl_len < (unsigned int) len) {
> + kfree(ar->debug.roam_tbl);
> + ar->debug.roam_tbl = kmalloc(len, GFP_ATOMIC);
> + if (ar->debug.roam_tbl == NULL)
> + return -ENOMEM;
> + }
> +
> + memcpy(ar->debug.roam_tbl, datap, len);
> + ar->debug.roam_tbl_len = len;
> +
> + if (test_bit(ROAM_TBL_PEND, &ar->flag)) {
> + clear_bit(ROAM_TBL_PEND, &ar->flag);
> + wake_up(&ar->event_wq);
> + }
> +#endif /* CONFIG_ATH6KL_DEBUG */
> +
> + return 0;
> +}
I would prefer to have the part inside ifdef in debug.c, for example
like ath6kl_debug_fwlog_event() is implemented. That way we can get rid
of the ifdef inside code and related functinality would be in the same file.
Kalle
^ permalink raw reply
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