Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH v2 1/5] ath6kl: Add endpoint_stats debugfs file
From: Jouni Malinen @ 2011-10-11 18:52 UTC (permalink / raw)
  To: Joe Perches; +Cc: kvalo, linux-wireless
In-Reply-To: <1318351171.1839.43.camel@Joe-Laptop>

On Tue, Oct 11, 2011 at 09:39:31AM -0700, Joe Perches wrote:
> > +static unsigned int print_endpoint_stat(struct htc_target *target, char *buf,
> > +					unsigned int buf_len, unsigned int len,
> > +					int offset, const char *name)
> 
> Perhaps the function name is wrong.
> This doesn't print, it fills a buffer.

Well, it prints the stuff into a buffer just like scnprintf prints
things.. Feel free to send a patch if you want to try to rename
*print* functions ;-).

> len and offset are to me oddly used variable names.

I guess len could be renamed to pos, but the use of len here matches
with the function used in the main function, i.e., this
print_endpoint_stat is more of a replacement for a macro. offset sounds
correct to me, i.e., it is the offset within the statistics structure.

> > +		counter = ((u32 *) ep_st) + (offset / 4);

> perhaps:
> 
> static int endpoint_stats(struct htc_target *target,
> 			  char *buf, size_t len,
> 			  size_t pos, int index, const char *name)

I would have nothing against pos, but index would be a bit confusing
here since that parameter is really the byte offset and not the index.

> 	pos += scnprintf(buf + pos, len - pos, "%s:", name);
> 	for (i = 0; i < ENDPOINT_MAX; i++) {
> 		u32 *stats = (u32 *)&target->endpoint[i].ep_st;
> 		offset += scnprintf(buf + pos, len - pos, " %u", stats[index]);

Well, okay, index to a u32 array.. If you feel strongly enough, please
send a separate cleanup patch since Kalle applied this already.


> > +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;
> 
> size_t len = 0;
> (or maybe pos instead)

This follows the style used throughout this file. Feel free to propose
cleanup to all the functions.

> 
> > +	ssize_t ret_cnt;
> > +
> > +	buf_len = 1000 + ENDPOINT_MAX * 100;
> 
> It seems odd to start with size using 1000

Yeah.. I think I had something as a prefix first and then just forgot to
remove that extra addition.

> There's ENDPOINT_MAX rows (9)
> Each row contains:
> 	up to 20 byte row name
> 	20 counters * up to 10 bytes per counter
> up to 220 bytes per row

It's actually the other way around, i.e., 20 rows with 9 counters.

> Perhaps this?
> 	const size_t buf_len = ENDPOINT_MAX * (20 + sizeof(struct htc_endpoint_stats) / sizeof(u32) * 10);

I was too lazy to count the exact maximum. If there is any chance of
overflowing the buf_len, this would obviously need to be fixed. The
theoretical maximum would likely be something like 20 * (22 + 9 * 11),
so yes, while I don't think this happens in practice, this buffer length
should be incremented to cover the theoretical case (and to make some
more sense).

> > +	buf = kzalloc(buf_len, GFP_KERNEL);
> 
> kzalloc doesn't seem necessary,
> everything is overwritten.  just kmalloc?

Yeah, I probably copied that from an existing function, but I would
agree that that is not really any need for clearing the buffer.

> As is, it's (barely) possible to overflow
> the buffer length and end up non-null terminated.
> Perhaps that doesn't matter.

I don't think there is any need for null-terminating the buffer since
this is really binary data with length returned. As I noted, this is
unlikely to end up having large enough counter values to overflow in
practice, but changing the buf_len calculation to make more sense is
useful cleanup anyway.

> > +	len = print_endpoint_stat(target, buf, buf_len, len,		\
> > +				  offsetof(struct htc_endpoint_stats, name), \
> > +				  #name)
> 
> perhaps
> 
> #define EPSTAT(name)							\
> 	len = endpoint_stat(target, buf, buf_len, len,			\
> 			    offsetof(struct htc_endpoint_stats, name) / sizeof(u32), \
> 			    #name)

I'm fine with this, too, as a separate cleanup patch.

> > +	if (len > buf_len)
> > +		len = buf_len;
> 
> Maybe it's better to ensure 0 termination?
> 	if (len > buf_len) {
> 		len = buf_len;
> 		buf[buf_len - 1] = 0;
> 	}

Why? This is a read file op.. It is not like the caller is expecting a
null-terminated string to come back from here.

-- 
Jouni Malinen                                            PGP id EFC895FA

^ permalink raw reply

* Re: [RFC] wl12xx: use the same plat dev name for both SPI and SDIO
From: Luciano Coelho @ 2011-10-11 18:02 UTC (permalink / raw)
  To: linux-wireless; +Cc: balbi
In-Reply-To: <1317992414-30197-1-git-send-email-coelho@ti.com>

On Fri, 2011-10-07 at 16:00 +0300, Luciano Coelho wrote: 
> There's no need to have the bus name included in the platform device
> name that we create.  The core driver doesn't need to know about the
> type of bus it uses.  Any differences between the buses that need to
> be handled differently in the core, can be passed in the platform data
> (as the pwr_in_suspend boolean does).
> 
> Use "wl12xx" for the device name in both bus drivers.  Rename the
> platform driver name to "wl12xx_driver", just to differentiate from
> the platform device names.
> 
> Signed-off-by: Luciano Coelho <coelho@ti.com>
> ---

Nobody complained about this (except Arik, but I answered his question),
so I decided to apply this.  I won't re-send it as PATCH, because that
would be useless. ;)

-- 
Cheers,
Luca.


^ permalink raw reply

* [PATCH] iw: add DFS region parsing support
From: Luis R. Rodriguez @ 2011-10-11 17:59 UTC (permalink / raw)
  To: linville, johannes; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1318355944-24708-1-git-send-email-mcgrof@qca.qualcomm.com>

This lets iw parse the DFS region passed on by the kernel
when one is found for the currently used regulatory domain.

Signed-off-by: Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
---
 nl80211.h |   65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 reg.c     |   31 +++++++++++++++++++++++++++++
 2 files changed, 96 insertions(+), 0 deletions(-)

diff --git a/nl80211.h b/nl80211.h
index c73582f..2dbb799 100644
--- a/nl80211.h
+++ b/nl80211.h
@@ -506,6 +506,9 @@
  * @NL80211_CMD_PMKSA_CANDIDATE: This is used as an event to inform userspace
  *	of PMKSA caching dandidates.
  *
+ * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup).
+ * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -632,6 +635,9 @@ enum nl80211_commands {
 
 	NL80211_CMD_PMKSA_CANDIDATE,
 
+	NL80211_CMD_TDLS_OPER,
+	NL80211_CMD_TDLS_MGMT,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -1089,6 +1095,24 @@ enum nl80211_commands {
  *	This attribute is used with %NL80211_CMD_TRIGGER_SCAN and
  *	%NL80211_CMD_FRAME commands.
  *
+ * @NL80211_ATTR_TDLS_ACTION: Low level TDLS action code (e.g. link setup
+ *	request, link setup confirm, link teardown, etc.). Values are
+ *	described in the TDLS (802.11z) specification.
+ * @NL80211_ATTR_TDLS_DIALOG_TOKEN: Non-zero token for uniquely identifying a
+ *	TDLS conversation between two devices.
+ * @NL80211_ATTR_TDLS_OPERATION: High level TDLS operation; see
+ *	&enum nl80211_tdls_operation, represented as a u8.
+ * @NL80211_ATTR_TDLS_SUPPORT: A flag indicating the device can operate
+ *	as a TDLS peer sta.
+ * @NL80211_ATTR_TDLS_EXTERNAL_SETUP: The TDLS discovery/setup and teardown
+ *	procedures should be performed by sending TDLS packets via
+ *	%NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
+ *	used for asking the driver to perform a TDLS operation.
+ *
+ * @NL80211_ATTR_DFS_REGION: region for regulatory rules which this country
+ *    abides to when initiating radiation on DFS channels. A country maps
+ *    to one DFS region.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1311,6 +1335,14 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_TX_NO_CCK_RATE,
 
+	NL80211_ATTR_TDLS_ACTION,
+	NL80211_ATTR_TDLS_DIALOG_TOKEN,
+	NL80211_ATTR_TDLS_OPERATION,
+	NL80211_ATTR_TDLS_SUPPORT,
+	NL80211_ATTR_TDLS_EXTERNAL_SETUP,
+
+	NL80211_ATTR_DFS_REGION,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -1408,6 +1440,7 @@ enum nl80211_iftype {
  * @NL80211_STA_FLAG_WME: station is WME/QoS capable
  * @NL80211_STA_FLAG_MFP: station uses management frame protection
  * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated
+ * @NL80211_STA_FLAG_TDLS_PEER: station is a TDLS peer
  * @NL80211_STA_FLAG_MAX: highest station flag number currently defined
  * @__NL80211_STA_FLAG_AFTER_LAST: internal use
  */
@@ -1418,6 +1451,7 @@ enum nl80211_sta_flags {
 	NL80211_STA_FLAG_WME,
 	NL80211_STA_FLAG_MFP,
 	NL80211_STA_FLAG_AUTHENTICATED,
+	NL80211_STA_FLAG_TDLS_PEER,
 
 	/* keep last */
 	__NL80211_STA_FLAG_AFTER_LAST,
@@ -1815,6 +1849,21 @@ enum nl80211_reg_rule_flags {
 };
 
 /**
+ * enum nl80211_dfs_regions - regulatory DFS regions
+ *
+ * @NL80211_DFS_UNSET: Country has no DFS master region specified
+ * @NL80211_DFS_FCC_: Country follows DFS master rules from FCC
+ * @NL80211_DFS_FCC_: Country follows DFS master rules from ETSI
+ * @NL80211_DFS_JP_: Country follows DFS master rules from JP/MKK/Telec
+ */
+enum nl80211_dfs_regions {
+	NL80211_DFS_UNSET	= 0,
+	NL80211_DFS_FCC		= 1,
+	NL80211_DFS_ETSI	= 2,
+	NL80211_DFS_JP		= 3,
+};
+
+/**
  * enum nl80211_survey_info - survey information
  *
  * These attribute types are used with %NL80211_ATTR_SURVEY_INFO
@@ -2604,4 +2653,20 @@ enum nl80211_pmksa_candidate_attr {
 	MAX_NL80211_PMKSA_CANDIDATE = NUM_NL80211_PMKSA_CANDIDATE - 1
 };
 
+/**
+ * enum nl80211_tdls_operation - values for %NL80211_ATTR_TDLS_OPERATION
+ * @NL80211_TDLS_DISCOVERY_REQ: Send a TDLS discovery request
+ * @NL80211_TDLS_SETUP: Setup TDLS link
+ * @NL80211_TDLS_TEARDOWN: Teardown a TDLS link which is already established
+ * @NL80211_TDLS_ENABLE_LINK: Enable TDLS link
+ * @NL80211_TDLS_DISABLE_LINK: Disable TDLS link
+ */
+enum nl80211_tdls_operation {
+	NL80211_TDLS_DISCOVERY_REQ,
+	NL80211_TDLS_SETUP,
+	NL80211_TDLS_TEARDOWN,
+	NL80211_TDLS_ENABLE_LINK,
+	NL80211_TDLS_DISABLE_LINK,
+};
+
 #endif /* __LINUX_NL80211_H */
diff --git a/reg.c b/reg.c
index c4ee1c4..4fa5bec 100644
--- a/reg.c
+++ b/reg.c
@@ -96,6 +96,31 @@ COMMAND(reg, set, "<ISO/IEC 3166-1 alpha2>",
 	NL80211_CMD_REQ_SET_REG, 0, CIB_NONE, handle_reg_set,
 	"Notify the kernel about the current regulatory domain.");
 
+static void print_dfs_region(__u8 dfs_region)
+{
+	if (!dfs_region)
+		return;
+
+	printf("DFS Master region: ");
+
+	switch (dfs_region) {
+	case NL80211_DFS_FCC:
+		printf("FCC");
+		break;
+	case NL80211_DFS_ETSI:
+		printf("ETSI");
+		break;
+	case NL80211_DFS_JP:
+		printf("JP");
+		break;
+	default:
+		printf("Uknown");
+		break;
+	}
+
+	printf("\n");
+}
+
 static int print_reg_handler(struct nl_msg *msg, void *arg)
 
 {
@@ -107,6 +132,7 @@ static int print_reg_handler(struct nl_msg *msg, void *arg)
 	struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
 	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
 	char *alpha2;
+	__u8 dfs_region = 0;
 	struct nlattr *nl_rule;
 	int rem_rule;
 	static struct nla_policy reg_rule_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
@@ -132,7 +158,12 @@ static int print_reg_handler(struct nl_msg *msg, void *arg)
 	}
 
 	alpha2 = nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]);
+
+	if (tb_msg[NL80211_ATTR_DFS_REGION])
+		dfs_region = nla_get_u8(tb_msg[NL80211_ATTR_DFS_REGION]);
+
 	printf("country %c%c:\n", alpha2[0], alpha2[1]);
+	print_dfs_region(dfs_region);
 
 	nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule) {
 		struct nlattr *tb_rule[NL80211_FREQUENCY_ATTR_MAX + 1];
-- 
1.7.4.15.g7811d


^ permalink raw reply related

* [PATCH 6/6] cfg80211: pass DFS region to drivers through reg_notifier()
From: Luis R. Rodriguez @ 2011-10-11 17:59 UTC (permalink / raw)
  To: linville, johannes; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1318355944-24708-1-git-send-email-mcgrof@qca.qualcomm.com>

This grants drivers access to the DFS region that a
regulatory domain belongs to.

Signed-off-by: Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
---
 include/net/regulatory.h |    5 +++++
 net/wireless/reg.c       |    2 ++
 2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/include/net/regulatory.h b/include/net/regulatory.h
index 7399c93..a5f7993 100644
--- a/include/net/regulatory.h
+++ b/include/net/regulatory.h
@@ -48,6 +48,10 @@ enum environment_cap {
  * 	99 - built by driver but a specific alpha2 cannot be determined
  * 	98 - result of an intersection between two regulatory domains
  *	97 - regulatory domain has not yet been configured
+ * @dfs_region: If CRDA responded with a regulatory domain that requires
+ *	DFS master operation on a known DFS region (NL80211_DFS_*),
+ *	dfs_region represents that region. Drivers can use this and the
+ *	@alpha2 to adjust their device's DFS parameters as required.
  * @intersect: indicates whether the wireless core should intersect
  * 	the requested regulatory domain with the presently set regulatory
  * 	domain.
@@ -67,6 +71,7 @@ struct regulatory_request {
 	int wiphy_idx;
 	enum nl80211_reg_initiator initiator;
 	char alpha2[2];
+	u8 dfs_region;
 	bool intersect;
 	bool processed;
 	enum environment_cap country_ie_env;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 69141ed..b66444d 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1121,6 +1121,8 @@ static void wiphy_update_regulatory(struct wiphy *wiphy,
 	if (ignore_reg_update(wiphy, initiator))
 		return;
 
+	last_request->dfs_region = cfg80211_regdomain->dfs_region;
+
 	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
 		if (wiphy->bands[band])
 			handle_band(wiphy, band, initiator);
-- 
1.7.4.15.g7811d


^ permalink raw reply related

* [PATCH 5/6] cfg80211: process regulatory DFS region for countries
From: Luis R. Rodriguez @ 2011-10-11 17:59 UTC (permalink / raw)
  To: linville, johannes; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1318355944-24708-1-git-send-email-mcgrof@qca.qualcomm.com>

The wireless-regdb now has support for mapping a country to
one DFS region. CRDA sends this to us now so process it
so we can provide that hint to drivers. This will later be
used by code for processing DFS in a way that meets the
criteria for the DFS region the country belongs to.

Signed-off-by: Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
---
 include/linux/nl80211.h  |   21 +++++++++++++++++++++
 include/net/regulatory.h |    1 +
 net/wireless/nl80211.c   |   15 +++++++++++++++
 net/wireless/reg.c       |   37 +++++++++++++++++++++++++++++++++++++
 net/wireless/reg.h       |    1 +
 5 files changed, 75 insertions(+), 0 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 9d797f2..2dbb799 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1109,6 +1109,10 @@ enum nl80211_commands {
  *	%NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
  *	used for asking the driver to perform a TDLS operation.
  *
+ * @NL80211_ATTR_DFS_REGION: region for regulatory rules which this country
+ *    abides to when initiating radiation on DFS channels. A country maps
+ *    to one DFS region.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1337,6 +1341,8 @@ enum nl80211_attrs {
 	NL80211_ATTR_TDLS_SUPPORT,
 	NL80211_ATTR_TDLS_EXTERNAL_SETUP,
 
+	NL80211_ATTR_DFS_REGION,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -1843,6 +1849,21 @@ enum nl80211_reg_rule_flags {
 };
 
 /**
+ * enum nl80211_dfs_regions - regulatory DFS regions
+ *
+ * @NL80211_DFS_UNSET: Country has no DFS master region specified
+ * @NL80211_DFS_FCC_: Country follows DFS master rules from FCC
+ * @NL80211_DFS_FCC_: Country follows DFS master rules from ETSI
+ * @NL80211_DFS_JP_: Country follows DFS master rules from JP/MKK/Telec
+ */
+enum nl80211_dfs_regions {
+	NL80211_DFS_UNSET	= 0,
+	NL80211_DFS_FCC		= 1,
+	NL80211_DFS_ETSI	= 2,
+	NL80211_DFS_JP		= 3,
+};
+
+/**
  * enum nl80211_survey_info - survey information
  *
  * These attribute types are used with %NL80211_ATTR_SURVEY_INFO
diff --git a/include/net/regulatory.h b/include/net/regulatory.h
index eb7d3c2..7399c93 100644
--- a/include/net/regulatory.h
+++ b/include/net/regulatory.h
@@ -93,6 +93,7 @@ struct ieee80211_reg_rule {
 struct ieee80211_regdomain {
 	u32 n_reg_rules;
 	char alpha2[2];
+	u8 dfs_region;
 	struct ieee80211_reg_rule reg_rules[];
 };
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index edf655a..8d3012a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -197,6 +197,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
 	[NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
 	[NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
 	[NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
+	[NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 },
 };
 
 /* policy for the key attributes */
@@ -3348,6 +3349,9 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
 
 	NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2,
 		cfg80211_regdomain->alpha2);
+	if (cfg80211_regdomain->dfs_region)
+		NLA_PUT_U8(msg, NL80211_ATTR_DFS_REGION,
+			   cfg80211_regdomain->dfs_region);
 
 	nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES);
 	if (!nl_reg_rules)
@@ -3406,6 +3410,7 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
 	char *alpha2 = NULL;
 	int rem_reg_rules = 0, r = 0;
 	u32 num_rules = 0, rule_idx = 0, size_of_regd;
+	u8 dfs_region = 0;
 	struct ieee80211_regdomain *rd = NULL;
 
 	if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
@@ -3416,6 +3421,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
 
 	alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
 
+	if (info->attrs[NL80211_ATTR_DFS_REGION])
+		dfs_region = nla_get_u8(info->attrs[NL80211_ATTR_DFS_REGION]);
+
 	nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
 			rem_reg_rules) {
 		num_rules++;
@@ -3443,6 +3451,13 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
 	rd->alpha2[0] = alpha2[0];
 	rd->alpha2[1] = alpha2[1];
 
+	/*
+	 * Disable DFS master mode if the DFS region was
+	 * not supported or known on this kernel.
+	 */
+	if (reg_supported_dfs_region(dfs_region))
+		rd->dfs_region = dfs_region;
+
 	nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
 			rem_reg_rules) {
 		nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 2520a1b..69141ed 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1946,6 +1946,42 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
 	}
 }
 
+bool reg_supported_dfs_region(u8 dfs_region)
+{
+	switch (dfs_region) {
+	case NL80211_DFS_UNSET:
+	case NL80211_DFS_FCC:
+	case NL80211_DFS_ETSI:
+	case NL80211_DFS_JP:
+		return true;
+	default:
+		REG_DBG_PRINT("Ignoring uknown DFS master region: %d\n",
+			      dfs_region);
+		return false;
+	}
+}
+
+static void print_dfs_region(u8 dfs_region)
+{
+	if (!dfs_region)
+		return;
+
+	switch (dfs_region) {
+	case NL80211_DFS_FCC:
+		pr_info(" DFS Master region FCC");
+		break;
+	case NL80211_DFS_ETSI:
+		pr_info(" DFS Master region ETSI");
+		break;
+	case NL80211_DFS_JP:
+		pr_info(" DFS Master region JP");
+		break;
+	default:
+		pr_info(" DFS Master region Uknown");
+		break;
+	}
+}
+
 static void print_regdomain(const struct ieee80211_regdomain *rd)
 {
 
@@ -1973,6 +2009,7 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
 			pr_info("Regulatory domain changed to country: %c%c\n",
 				rd->alpha2[0], rd->alpha2[1]);
 	}
+	print_dfs_region(rd->dfs_region);
 	print_rd_rules(rd);
 }
 
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 4a56799..786e414 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -5,6 +5,7 @@ extern const struct ieee80211_regdomain *cfg80211_regdomain;
 
 bool is_world_regdom(const char *alpha2);
 bool reg_is_valid_request(const char *alpha2);
+bool reg_supported_dfs_region(u8 dfs_region);
 
 int regulatory_hint_user(const char *alpha2);
 
-- 
1.7.4.15.g7811d


^ permalink raw reply related

* [PATCH 4/4] crda: add support to send DFS master region
From: Luis R. Rodriguez @ 2011-10-11 17:59 UTC (permalink / raw)
  To: linville, johannes; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1318355944-24708-1-git-send-email-mcgrof@qca.qualcomm.com>

wireless-regdb now has support for a DFS master region
for each country. We must read this from the file and
send it as an NL80211_ATTR_DFS_REGION attribute.

We add a "creqs" value for the country structure but only
use the first two bits as that is all we need right now.

Signed-off-by: Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
---
 crda.c    |    1 +
 nl80211.h |   21 +++++++++++++++++++++
 regdb.h   |    3 ++-
 3 files changed, 24 insertions(+), 1 deletions(-)

diff --git a/crda.c b/crda.c
index fcb0c11..1e2ff22 100644
--- a/crda.c
+++ b/crda.c
@@ -280,6 +280,7 @@ int main(int argc, char **argv)
 				country->reg_collection_ptr);
 
 	NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2);
+	NLA_PUT_U8(msg, NL80211_ATTR_DFS_REGION, country->creqs & 0x3);
 
 	nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES);
 	if (!nl_reg_rules) {
diff --git a/nl80211.h b/nl80211.h
index 9d797f2..2dbb799 100644
--- a/nl80211.h
+++ b/nl80211.h
@@ -1109,6 +1109,10 @@ enum nl80211_commands {
  *	%NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
  *	used for asking the driver to perform a TDLS operation.
  *
+ * @NL80211_ATTR_DFS_REGION: region for regulatory rules which this country
+ *    abides to when initiating radiation on DFS channels. A country maps
+ *    to one DFS region.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1337,6 +1341,8 @@ enum nl80211_attrs {
 	NL80211_ATTR_TDLS_SUPPORT,
 	NL80211_ATTR_TDLS_EXTERNAL_SETUP,
 
+	NL80211_ATTR_DFS_REGION,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -1843,6 +1849,21 @@ enum nl80211_reg_rule_flags {
 };
 
 /**
+ * enum nl80211_dfs_regions - regulatory DFS regions
+ *
+ * @NL80211_DFS_UNSET: Country has no DFS master region specified
+ * @NL80211_DFS_FCC_: Country follows DFS master rules from FCC
+ * @NL80211_DFS_FCC_: Country follows DFS master rules from ETSI
+ * @NL80211_DFS_JP_: Country follows DFS master rules from JP/MKK/Telec
+ */
+enum nl80211_dfs_regions {
+	NL80211_DFS_UNSET	= 0,
+	NL80211_DFS_FCC		= 1,
+	NL80211_DFS_ETSI	= 2,
+	NL80211_DFS_JP		= 3,
+};
+
+/**
  * enum nl80211_survey_info - survey information
  *
  * These attribute types are used with %NL80211_ATTR_SURVEY_INFO
diff --git a/regdb.h b/regdb.h
index 045a0e3..f040aa1 100644
--- a/regdb.h
+++ b/regdb.h
@@ -96,7 +96,8 @@ struct regdb_file_reg_rules_collection {
 
 struct regdb_file_reg_country {
 	__u8	alpha2[2];
-	__u8	PAD[2];
+	__u8	PAD;
+	__u8	creqs; /* first two bits define DFS region */
 	/* pointer (offset) into the file to a struct
 	 * regdb_file_reg_rules_collection */
 	__be32	reg_collection_ptr;
-- 
1.7.4.15.g7811d


^ permalink raw reply related

* [PATCH 3/4] crda: fix null string assumption for alpha2
From: Luis R. Rodriguez @ 2011-10-11 17:59 UTC (permalink / raw)
  To: linville, johannes; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1318355944-24708-1-git-send-email-mcgrof@qca.qualcomm.com>

The wireless-regdb only accounts for two bytes for
the country code but CRDA defined the alpha2 to be
as a string of length 2, and so does the nl80211 attribute
policy:

        [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 },

The meaning of a string is it'll be null terminated, so if you
do not add the null termination a country without the null termination
will not match up with the nl80211 attribute policy.

This has no impact for us unless we want to use the next available
pad byte on the wireless-regdb. This fixes CRDA by using a local copy
of the regdb's alpha2 that is properly null terminated and sending it.

The implications of this change is that new wirelesss-regdb's that
make use of the next pad byte for a country will get that country
ignored for regulatory hints sent to the kernel. At this point we
don't yet know what the next byte will be used for though so this
has no impact. The second pad byte is being used for DFS and that
is not impacted by this nor is this change required for it.

Distributions should upgrade though in case we ever do decide to use
this last precious country byte. I've tested that this indeed fixes
the bogus issue I saw when instead of using the second pad byte we
use the first pad byte. Thanks to Johannes for spotting the issue.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
---
 crda.c   |    4 ++--
 reglib.h |   13 -------------
 2 files changed, 2 insertions(+), 15 deletions(-)

diff --git a/crda.c b/crda.c
index 6857e3f..fcb0c11 100644
--- a/crda.c
+++ b/crda.c
@@ -149,7 +149,7 @@ int main(int argc, char **argv)
 	struct regdb_file_header *header;
 	struct regdb_file_reg_country *countries;
 	int dblen, siglen, num_countries, i, j, r;
-	char alpha2[2];
+	char alpha2[3] = {}; /* NUL-terminate */
 	char *env_country;
 	struct nl80211_state nlstate;
 	struct nl_cb *cb = NULL;
@@ -279,7 +279,7 @@ int main(int argc, char **argv)
 				sizeof(*rcoll) + num_rules * sizeof(__be32),
 				country->reg_collection_ptr);
 
-	NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, (char *) country->alpha2);
+	NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2);
 
 	nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES);
 	if (!nl_reg_rules) {
diff --git a/reglib.h b/reglib.h
index f3a76ef..9fe5d8b 100644
--- a/reglib.h
+++ b/reglib.h
@@ -53,21 +53,8 @@ static inline int is_alpha2(const char *alpha2)
 	return 0;
 }
 
-/* Avoid stdlib */
-static inline int is_len_2(const char *alpha2)
-{
-        if (alpha2[0] == '\0' || (alpha2[1] == '\0'))
-                return 0;
-        if (alpha2[2] == '\0')
-                return 1;
-        return 0;
-}
-
 static inline int is_valid_regdom(const char *alpha2)
 {
-	if (!is_len_2(alpha2))
-		return 0;
-
 	if (!is_alpha2(alpha2) && !is_world_regdom(alpha2))
 		return 0;
 
-- 
1.7.4.15.g7811d


^ permalink raw reply related

* [PATCH 2/2] wireless-regdb: add FCC as the DFS region for US
From: Luis R. Rodriguez @ 2011-10-11 17:58 UTC (permalink / raw)
  To: linville, johannes; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1318355944-24708-1-git-send-email-mcgrof@qca.qualcomm.com>

DFS master support in the US requires consideration for DFS
requirements as defined by the FCC rules.

Signed-off-by: Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
---
 db.txt |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/db.txt b/db.txt
index f0b46d8..4b7e879 100644
--- a/db.txt
+++ b/db.txt
@@ -651,7 +651,7 @@ country TR:
 country UA:
 	(2402 - 2482 @ 40), (N/A, 20)
 
-country US:
+country US: DFS-FCC
 	(2402 - 2472 @ 40), (3, 27)
 	(5170 - 5250 @ 40), (3, 17)
 	(5250 - 5330 @ 40), (3, 20), DFS
-- 
1.7.4.15.g7811d


^ permalink raw reply related

* [PATCH 1/2] wireless-regdb: Add master DFS region support
From: Luis R. Rodriguez @ 2011-10-11 17:58 UTC (permalink / raw)
  To: linville, johannes; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1318355944-24708-1-git-send-email-mcgrof@qca.qualcomm.com>

To support master DFS we add the three known DFS regions which
countries are known to support. In order to modify the regulatory
database schema in a backward compatible way we use one of
the two pad bytes which were unused. By using one of the two pad
bytes we end up keeping new regulatory databases with DFS region
support compatible with older verions of CRDA, the DFS region would
just not be sent to the kernel.

DFS master is only required for modes of operation which iniate
radiation on DFS channels, we will start supporting DFS with AP
mode of operation. Without DFS master support you cannot intiate
radiation on those channels (AP, Mesh, IBSS, P2P). Apart from support
from wireless-regd, crda and the 802.11 stack you'll also need proper
DFS support on your device driver.

A country can only map to one DFS region at a time for all frequency
regions. After this patch countries can start being mapped to their
own DFS region.

Signed-off-by: Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
---
 db2bin.py  |    2 +-
 dbparse.py |   25 ++++++++++++++++++++-----
 2 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/db2bin.py b/db2bin.py
index 23d3ee2..41d3741 100755
--- a/db2bin.py
+++ b/db2bin.py
@@ -116,7 +116,7 @@ countrynames.sort()
 for alpha2 in countrynames:
     coll = countries[alpha2]
     # struct regdb_file_reg_country
-    output.write(struct.pack('>ccxxI', str(alpha2[0]), str(alpha2[1]), reg_rules_collections[coll.permissions]))
+    output.write(struct.pack('>ccxBI', str(alpha2[0]), str(alpha2[1]), coll.dfs_region, reg_rules_collections[coll.permissions]))
 
 
 if len(sys.argv) > 3:
diff --git a/dbparse.py b/dbparse.py
index 2c0d738..893d64e 100755
--- a/dbparse.py
+++ b/dbparse.py
@@ -18,6 +18,12 @@ flag_definitions = {
     'NO-HT40':		1<<10,
 }
 
+dfs_regions = {
+    'DFS-FCC':		1,
+    'DFS-ETSI':		2,
+    'DFS-JP':		3,
+}
+
 class FreqBand(object):
     def __init__(self, start, end, bw, comments=None):
         self.start = start
@@ -61,6 +67,10 @@ class PowerRestriction(object):
         s = self
         return hash((s.max_ant_gain, s.max_eirp))
 
+class DFSRegionError(Exception):
+    def __init__(self, dfs_region):
+        self.dfs_region = dfs_region
+
 class FlagError(Exception):
     def __init__(self, flag):
         self.flag = flag
@@ -90,9 +100,15 @@ class Permission(object):
         return hash(self._as_tuple())
 
 class Country(object):
-    def __init__(self, permissions=None, comments=None):
+    def __init__(self, dfs_region, permissions=None, comments=None):
         self._permissions = permissions or []
         self.comments = comments or []
+	self.dfs_region = 0
+
+	if dfs_region:
+		if not dfs_region in dfs_regions:
+		    raise DFSRegionError(dfs_region)
+		self.dfs_region = dfs_regions[dfs_region]
 
     def add(self, perm):
         assert isinstance(perm, Permission)
@@ -224,11 +240,10 @@ class DBParser(object):
 
     def _parse_country(self, line):
         try:
-            cname, line = line.split(':', 1)
+            cname, cvals= line.split(':', 1)
+            dfs_region = cvals.strip()
             if not cname:
                 self._syntax_error("'country' keyword must be followed by name")
-            if line:
-                self._syntax_error("extra data at end of country line")
         except ValueError:
             self._syntax_error("country name must be followed by colon")
 
@@ -239,7 +254,7 @@ class DBParser(object):
             if len(cname) != 2:
                 self._warn("country '%s' not alpha2" % cname)
             if not cname in self._countries:
-                self._countries[cname] = Country(comments=self._comments)
+                self._countries[cname] = Country(dfs_region, comments=self._comments)
             self._current_countries[cname] = self._countries[cname]
         self._comments = []
 
-- 
1.7.4.15.g7811d


^ permalink raw reply related

* [PATCH v2 0/7] wireless: add DFS master support
From: Luis R. Rodriguez @ 2011-10-11 17:58 UTC (permalink / raw)
  To: linville, johannes; +Cc: linux-wireless, Luis R. Rodriguez

This is v2 of my DFS master support patches. The v2 addresses only 2 bits
on the wireless-regdb and leaves open what we do for the rest of the 6 bits.
The nl80211 interface remains the same but I also fixed a typo I had made in
my previous patches for the dfs region enums. I also throw in the fix for CRDA
for the odd behaviour observed on the last pad byte.

This set of 7 patches adds DFS master support to the Linux wireless subsystem.
I've reviewed future possible changes to DFS master regions and it seems that
we are not going to be having multiple DFS regions for one country, instead
we'll always have one DFS region for one country.

The changes here are spread out throughout wireless-regdb, crda the kernel and
lastly iw. The changes made allow for older verions of CRDA to work with new
wireless-regdb files with DFS region support. If you want DFS master region
support you'll need to upgrade your CRDA, your kernel and then hope someone
implements DFS master support for your respective driver.

This patch series does not have specific driver changes, although some seem to
be backing in the oven right now.

Luis R. Rodriguez (6):
  wireless-regdb: Add master DFS region support
  wireless-regdb: add FCC as the DFS region for US
  crda: fix null string assumption for alpha2
  crda: add support to send DFS master region
  cfg80211: process regulatory DFS region for countries
  cfg80211: pass DFS region to drivers through reg_notifier()
  iw: add DFS region parsing support

 db.txt     |    2 +-
 db2bin.py  |    2 +-
 dbparse.py |   25 ++++++++++++++++++++-----
 3 files changed, 22 insertions(+), 7 deletions(-)

 crda.c    |    5 +++--
 nl80211.h |   21 +++++++++++++++++++++
 regdb.h   |    3 ++-
 reglib.h  |   13 -------------
 4 files changed, 26 insertions(+), 16 deletions(-)

 include/linux/nl80211.h  |   21 +++++++++++++++++++++
 include/net/regulatory.h |    6 ++++++
 net/wireless/nl80211.c   |   15 +++++++++++++++
 net/wireless/reg.c       |   39 +++++++++++++++++++++++++++++++++++++++
 net/wireless/reg.h       |    1 +
 5 files changed, 82 insertions(+), 0 deletions(-)

 nl80211.h |   65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 reg.c     |   31 +++++++++++++++++++++++++++++
 2 files changed, 96 insertions(+), 0 deletions(-)

-- 
1.7.4.15.g7811d


^ permalink raw reply

* Re: Re: [PATCH 1/2] mac80211: Build TX radiotap header dynamically
From: Johannes Berg @ 2011-10-11 17:38 UTC (permalink / raw)
  To: Helmut Schaa; +Cc: linux-wireless, linville
In-Reply-To: <3634905.slyix8Dz5L@helmutmobil.site>

On Tue, 2011-10-11 at 19:19 +0200, Helmut Schaa wrote:
> Am Dienstag, 11. Oktober 2011, 18:25:45 schrieb Johannes Berg:
> > On Tue, 2011-10-11 at 18:08 +0200, Helmut Schaa wrote:
> > Since there's no over-all memset I think you need to clear the padding
> > explicitly now.
> 
> Like this one? :)
> 
> > +	rthdr = (struct ieee80211_radiotap_header *) skb_push(skb, rtap_len);
> > +
> > +	memset(rthdr, 0, rtap_len);

Oh, oops, sorry!

Looks good to me then.

johannes


^ permalink raw reply

* Re: bug server
From: John W. Linville @ 2011-10-11 17:16 UTC (permalink / raw)
  To: abutalip; +Cc: linux-wireless
In-Reply-To: <4E946F75.5000207@gmail.com>

On Tue, Oct 11, 2011 at 07:31:49PM +0300, abutalip wrote:
> Hi all,
> 
> I'm new here. After I studied the notes from linuxwireless.org I
> want to start fix some bugs to become familiar with linux wireless
> code. My question is the next on: what is the IP address for the bug
> server?
> Thanks!
> 
> Stefan

bugzilla.kernel.org, but it is currently unavailable...

-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: Re: [PATCH 1/2] mac80211: Build TX radiotap header dynamically
From: Helmut Schaa @ 2011-10-11 17:19 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, linville
In-Reply-To: <1318350345.3965.11.camel@jlt3.sipsolutions.net>

Am Dienstag, 11. Oktober 2011, 18:25:45 schrieb Johannes Berg:
> On Tue, 2011-10-11 at 18:08 +0200, Helmut Schaa wrote:
> Since there's no over-all memset I think you need to clear the padding
> explicitly now.

Like this one? :)

> +	rthdr = (struct ieee80211_radiotap_header *) skb_push(skb, rtap_len);
> +
> +	memset(rthdr, 0, rtap_len);

Helmut

^ permalink raw reply

* Re: [PATCH v2 1/5] ath6kl: Add endpoint_stats debugfs file
From: Joe Perches @ 2011-10-11 16:39 UTC (permalink / raw)
  To: Jouni Malinen; +Cc: kvalo, linux-wireless
In-Reply-To: <1318343517-15292-2-git-send-email-jouni@qca.qualcomm.com>

On Tue, 2011-10-11 at 17:31 +0300, Jouni Malinen wrote:
> This file can be used to fetch endpoint statistics counters and
> to clear them by writing 0 to it.

Hi Jouni.

[petty carping follows]

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

Perhaps the function name is wrong.
This doesn't print, it fills a buffer.
len and offset are to me oddly used variable names.

> +{
> +	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;
> +

perhaps:

static int endpoint_stats(struct htc_target *target,
			  char *buf, size_t len,
			  size_t pos, int index, const char *name)
{
	int i;

	pos += scnprintf(buf + pos, len - pos, "%s:", name);
	for (i = 0; i < ENDPOINT_MAX; i++) {
		u32 *stats = (u32 *)&target->endpoint[i].ep_st;
		offset += scnprintf(buf + pos, len - pos, " %u", stats[index]);
	}
	pos += scnprintf(buf + pos, len - pos, "\n");

	return pos;
}

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

size_t len = 0;
(or maybe pos instead)

> +	ssize_t ret_cnt;
> +
> +	buf_len = 1000 + ENDPOINT_MAX * 100;

It seems odd to start with size using 1000

There's ENDPOINT_MAX rows (9)
Each row contains:
	up to 20 byte row name
	20 counters * up to 10 bytes per counter
up to 220 bytes per row

Perhaps this?
	const size_t buf_len = ENDPOINT_MAX * (20 + sizeof(struct htc_endpoint_stats) / sizeof(u32) * 10);

> +	buf = kzalloc(buf_len, GFP_KERNEL);

kzalloc doesn't seem necessary,
everything is overwritten.  just kmalloc?

As is, it's (barely) possible to overflow
the buffer length and end up non-null terminated.
Perhaps that doesn't matter.

> +	if (!buf)
> +		return -ENOMEM;
> +
> +#define EPSTAT(name)							\
> +	len = print_endpoint_stat(target, buf, buf_len, len,		\
> +				  offsetof(struct htc_endpoint_stats, name), \
> +				  #name)

perhaps

#define EPSTAT(name)							\
	len = endpoint_stat(target, buf, buf_len, len,			\
			    offsetof(struct htc_endpoint_stats, name) / sizeof(u32), \
			    #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;

Maybe it's better to ensure 0 termination?
	if (len > buf_len) {
		len = buf_len;
		buf[buf_len - 1] = 0;
	}

> +	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
> +	kfree(buf);
> +	return ret_cnt;
> +}



^ permalink raw reply

* bug server
From: abutalip @ 2011-10-11 16:31 UTC (permalink / raw)
  To: linux-wireless

Hi all,

I'm new here. After I studied the notes from linuxwireless.org I want to 
start fix some bugs to become familiar with linux wireless code. My 
question is the next on: what is the IP address for the bug server?
Thanks!

Stefan

^ permalink raw reply

* Re: [PATCH 1/2] mac80211: Build TX radiotap header dynamically
From: Johannes Berg @ 2011-10-11 16:25 UTC (permalink / raw)
  To: Helmut Schaa; +Cc: linux-wireless, linville
In-Reply-To: <1318349335-22514-1-git-send-email-helmut.schaa@googlemail.com>

On Tue, 2011-10-11 at 18:08 +0200, Helmut Schaa wrote:

> +	/* 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;

Since there's no over-all memset I think you need to clear the padding
explicitly now.

johannes



^ permalink raw reply

* Re: [PATCH] wl12xx: remove warning message during IBSS Tx
From: Luciano Coelho @ 2011-10-11 16:18 UTC (permalink / raw)
  To: Shahar Lev; +Cc: linux-wireless
In-Reply-To: <1318344193.9690.528.camel@cumari>

On Tue, 2011-10-11 at 17:43 +0300, Luciano Coelho wrote: 
> 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!

Actually I had to merge this with Eliad's vif patches, so I did this
before applying:

diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 1bc00ca..27a45e1 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -429,7 +429,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
        hlid = wl12xx_tx_get_hlid(wl, wlvif, skb);
        if (hlid == WL12XX_INVALID_LINK_ID) {
                if (wlvif->bss_type == BSS_TYPE_IBSS &&
-                   !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) {
+                   !test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags)) {
                        /* It's ok to drop packets when not joined to IBSS */
                        wl1271_debug(DEBUG_TX, "dropping skb while IBSS not "
                                     " joined");


-- 
Cheers,
Luca.


^ permalink raw reply related

* Re: [PATCH v2 0/5] ath6kl: Debugging and roaming
From: Kalle Valo @ 2011-10-11 16:13 UTC (permalink / raw)
  To: Jouni Malinen; +Cc: linux-wireless
In-Reply-To: <1318343517-15292-1-git-send-email-jouni@qca.qualcomm.com>

On 10/11/2011 05:31 PM, Jouni Malinen wrote:
> 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.

Thanks, all five applied.

Kalle

^ permalink raw reply

* [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


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox