Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH 18/40] crda: rename world and prev_world on intersect.c
From: Luis R. Rodriguez @ 2013-05-31  2:09 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

The assumption was that intersect.c was creating a world
regulatory domain for by doing an intersection of all
regulatory domains. This is technically still true however
it does not add passive scan flag'd frequency ranges and
as such to be precise lets just rename the "world" and
"prev_world" variables as intersection variables.

This change introduces no functional changes.

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 intersect.c |   44 ++++++++++++++++++++++----------------------
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/intersect.c b/intersect.c
index 970f4db..7903dd7 100644
--- a/intersect.c
+++ b/intersect.c
@@ -13,7 +13,7 @@ int main(int argc, char **argv)
 {
 	int r = 0;
 	const struct ieee80211_regdomain *rd;
-	struct ieee80211_regdomain *prev_world = NULL, *world = NULL;
+	struct ieee80211_regdomain *prev_rd_intsct = NULL, *rd_intsct = NULL;
 	int intersected = 0;
 	unsigned int idx = 0;
 
@@ -29,19 +29,19 @@ int main(int argc, char **argv)
 			continue;
 		}
 
-		if (!prev_world) {
-			prev_world = (struct ieee80211_regdomain *) rd;
+		if (!prev_rd_intsct) {
+			prev_rd_intsct = (struct ieee80211_regdomain *) rd;
 			continue;
 		}
 
-		if (world) {
-			free(prev_world);
-			prev_world = (struct ieee80211_regdomain *) world;
+		if (rd_intsct) {
+			free(prev_rd_intsct);
+			prev_rd_intsct = (struct ieee80211_regdomain *) rd_intsct;
 		}
 
-		world = regdom_intersect(prev_world, rd);
-		if (!world) {
-			free(prev_world);
+		rd_intsct = regdom_intersect(prev_rd_intsct, rd);
+		if (!rd_intsct) {
+			free(prev_rd_intsct);
 			free((struct ieee80211_regdomain *) rd);
 			fprintf(stderr, "Intersection not possible\n");
 			return -ENOENT;
@@ -50,20 +50,20 @@ int main(int argc, char **argv)
 		if (intersected)
 			/* Use UTF-8 Intersection symbol ? (0xE2,0x88,0xA9) :) */
 			printf("WW (%d) intersect %c%c (%d) ==> %d rules\n",
-				prev_world->n_reg_rules,
+				prev_rd_intsct->n_reg_rules,
 				rd->alpha2[0],
 				rd->alpha2[1],
 				rd->n_reg_rules,
-				world->n_reg_rules);
+				rd_intsct->n_reg_rules);
 		else
 			printf("%c%c (%d) intersect %c%c (%d) ==> %d rules\n",
-				prev_world->alpha2[0],
-				prev_world->alpha2[1],
-				prev_world->n_reg_rules,
+				prev_rd_intsct->alpha2[0],
+				prev_rd_intsct->alpha2[1],
+				prev_rd_intsct->n_reg_rules,
 				rd->alpha2[0],
 				rd->alpha2[1],
 				rd->n_reg_rules,
-				world->n_reg_rules);
+				rd_intsct->n_reg_rules);
 		intersected++;
 		free((struct ieee80211_regdomain *) rd);
 	}
@@ -77,26 +77,26 @@ int main(int argc, char **argv)
 	if (intersected > 1)
 		printf("%d regulatory domains intersected\n", intersected);
 	else {
-		world = prev_world;
-		prev_world = NULL;
+		rd_intsct = prev_rd_intsct;
+		prev_rd_intsct = NULL;
 		printf("No intersections completed\n");
 		if (idx > 1) {
 			printf("Since more than one regulatory domain is "
 			       "present and no intersections were possible "
 			       "no globally allowed spectrum is possible so "
 			       "consider enabling passive scan flags\n");
-			free(world);
+			free(rd_intsct);
 			return r;
 		}
 	}
 
-	if (prev_world)
-		free(prev_world);
+	if (prev_rd_intsct)
+		free(prev_rd_intsct);
 
 	/* Tada! */
 	printf("== World regulatory domain: ==\n");
-	print_regdom(world);
+	print_regdom(rd_intsct);
 
-	free(world);
+	free(rd_intsct);
 	return r;
 }
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 17/40] crda: use gcry_mpi_release() when using gcry_mpi_scan()
From: Luis R. Rodriguez @ 2013-05-31  2:09 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

Its not well documented you should do this but I found out
through valgrind. This fixes the last 4 valgrind issues
I was seeing with regdbdump.

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 reglib.c |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/reglib.c b/reglib.c
index 3d13782..72ea78f 100644
--- a/reglib.c
+++ b/reglib.c
@@ -158,10 +158,14 @@ int crda_verify_db_signature(uint8_t *db, int dblen, int siglen)
 				    "(public-key (rsa (n %m) (e %m)))",
 				    mpi_n, mpi_e)) {
 			fprintf(stderr, "Failed to build RSA S-expression.\n");
+			gcry_mpi_release(mpi_e);
+			gcry_mpi_release(mpi_n);
 			goto out;
 		}
 
 		ok = gcry_pk_verify(signature, data, rsa) == 0;
+		gcry_mpi_release(mpi_e);
+		gcry_mpi_release(mpi_n);
 		gcry_sexp_release(rsa);
 	}
 
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 16/40] crda: explicitly use close() and munmap() on reglib_get_rd_alpha2()
From: Luis R. Rodriguez @ 2013-05-31  2:09 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 reglib.c |   23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/reglib.c b/reglib.c
index 634525b..3d13782 100644
--- a/reglib.c
+++ b/reglib.c
@@ -262,33 +262,37 @@ reglib_get_rd_idx(unsigned int idx, const char *file)
 	if (fd < 0)
 		return NULL;
 
-	if (fstat(fd, &stat))
+	if (fstat(fd, &stat)) {
+		close(fd);
 		return NULL;
+	}
 
 	dblen = stat.st_size;
 
 	db = mmap(NULL, dblen, PROT_READ, MAP_PRIVATE, fd, 0);
-	if (db == MAP_FAILED)
+	if (db == MAP_FAILED) {
+		close(fd);
 		return NULL;
+	}
 
 	header = crda_get_file_ptr(db, dblen, sizeof(*header), 0);
 
 	if (ntohl(header->magic) != REGDB_MAGIC)
-		return NULL;
+		goto out;
 
 	if (ntohl(header->version) != REGDB_VERSION)
-		return NULL;
+		goto out;
 
 	siglen = ntohl(header->signature_length);
 	/* adjust dblen so later sanity checks don't run into the signature */
 	dblen -= siglen;
 
 	if (dblen <= (int)sizeof(*header))
-		return NULL;
+		goto out;
 
 	/* verify signature */
 	if (!crda_verify_db_signature(db, dblen, siglen))
-		return NULL;
+		goto out;
 
 	num_countries = ntohl(header->reg_country_num);
 	countries = crda_get_file_ptr(db, dblen,
@@ -296,14 +300,17 @@ reglib_get_rd_idx(unsigned int idx, const char *file)
 			header->reg_country_ptr);
 
 	if (idx >= num_countries)
-		return NULL;
+		goto out;
 
 	country = countries + idx;
 
 	rd = country2rd(db, dblen, country);
 	if (!rd)
-		return NULL;
+		goto out;
 
+out:
+	close(fd);
+	munmap(db, dblen);
 	return rd;
 }
 
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 15/40] crda: use gcry_sexp_release() on crda_verify_db_signature()
From: Luis R. Rodriguez @ 2013-05-31  2:09 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

This fixes 6 of 10 reported valgrind errors when
crda_verify_db_signature() is used through regdbdump.

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 reglib.c |    8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/reglib.c b/reglib.c
index 17e3f31..634525b 100644
--- a/reglib.c
+++ b/reglib.c
@@ -135,13 +135,14 @@ int crda_verify_db_signature(uint8_t *db, int dblen, int siglen)
 	if (gcry_sexp_build(&data, NULL, "(data (flags pkcs1) (hash sha1 %b))",
 			    20, hash)) {
 		fprintf(stderr, "Failed to build data S-expression.\n");
-		goto out;
+		return ok;
 	}
 
 	if (gcry_sexp_build(&signature, NULL, "(sig-val (rsa (s %b)))",
 			    siglen, db + dblen)) {
 		fprintf(stderr, "Failed to build signature S-expression.\n");
-		goto out;
+		gcry_sexp_release(data);
+		return ok;
 	}
 
 	for (i = 0; (i < sizeof(keys)/sizeof(keys[0])) && (!ok); i++) {
@@ -161,12 +162,15 @@ int crda_verify_db_signature(uint8_t *db, int dblen, int siglen)
 		}
 
 		ok = gcry_pk_verify(signature, data, rsa) == 0;
+		gcry_sexp_release(rsa);
 	}
 
 	if (!ok)
 		fprintf(stderr, "Database signature verification failed.\n");
 
 out:
+	gcry_sexp_release(data);
+	gcry_sexp_release(signature);
 	return ok;
 }
 #endif /* USE_GCRYPT */
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 14/40] crda: separate crda_verify_db_signature() implementations
From: Luis R. Rodriguez @ 2013-05-31  2:09 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

This will allow us to handle the error codes more cleanly
and in a readible manner. This change should have no
functional change.

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 reglib.c |   27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/reglib.c b/reglib.c
index cbe9676..17e3f31 100644
--- a/reglib.c
+++ b/reglib.c
@@ -50,14 +50,17 @@ void *crda_get_file_ptr(uint8_t *db, int dblen, int structlen, uint32_t ptr)
 }
 
 /*
+ * crda_verify_db_signature():
+ *
  * Checks the validity of the signature found on the regulatory
  * database against the array 'keys'. Returns 1 if there exists
  * at least one key in the array such that the signature is valid
  * against that key; 0 otherwise.
  */
+
+#ifdef USE_OPENSSL
 int crda_verify_db_signature(uint8_t *db, int dblen, int siglen)
 {
-#ifdef USE_OPENSSL
 	RSA *rsa;
 	uint8_t hash[SHA_DIGEST_LENGTH];
 	unsigned int i;
@@ -105,9 +108,18 @@ int crda_verify_db_signature(uint8_t *db, int dblen, int siglen)
 		}
 		closedir(pubkey_dir);
 	}
-#endif
+
+	if (!ok)
+		fprintf(stderr, "Database signature verification failed.\n");
+
+out:
+	return ok;
+}
+#endif /* USE_OPENSSL */
 
 #ifdef USE_GCRYPT
+int crda_verify_db_signature(uint8_t *db, int dblen, int siglen)
+{
 	gcry_mpi_t mpi_e, mpi_n;
 	gcry_sexp_t rsa, signature, data;
 	uint8_t hash[20];
@@ -150,18 +162,21 @@ int crda_verify_db_signature(uint8_t *db, int dblen, int siglen)
 
 		ok = gcry_pk_verify(signature, data, rsa) == 0;
 	}
-#endif
 
-#if defined(USE_OPENSSL) || defined(USE_GCRYPT)
 	if (!ok)
 		fprintf(stderr, "Database signature verification failed.\n");
 
 out:
 	return ok;
-#else
+}
+#endif /* USE_GCRYPT */
+
+#if !defined(USE_OPENSSL) && !defined(USE_GCRYPT)
+int crda_verify_db_signature(uint8_t *db, int dblen, int siglen)
+{
 	return 1;
-#endif
 }
+#endif
 
 static void reg_rule2rd(uint8_t *db, int dblen,
 	uint32_t ruleptr, struct ieee80211_reg_rule *rd_reg_rule)
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 13/40] crda: explicitly close file descriptor and munmap() on failures
From: Luis R. Rodriguez @ 2013-05-31  2:09 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

Just do this explicitly.

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 reglib.c |   16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/reglib.c b/reglib.c
index bb6f23f..cbe9676 100644
--- a/reglib.c
+++ b/reglib.c
@@ -307,33 +307,37 @@ reglib_get_rd_alpha2(const char *alpha2, const char *file)
 	if (fd < 0)
 		return NULL;
 
-	if (fstat(fd, &stat))
+	if (fstat(fd, &stat)) {
+		close(fd);
 		return NULL;
+	}
 
 	dblen = stat.st_size;
 
 	db = mmap(NULL, dblen, PROT_READ, MAP_PRIVATE, fd, 0);
-	if (db == MAP_FAILED)
+	if (db == MAP_FAILED) {
+		close(fd);
 		return NULL;
+	}
 
 	header = crda_get_file_ptr(db, dblen, sizeof(*header), 0);
 
 	if (ntohl(header->magic) != REGDB_MAGIC)
-		return NULL;
+		goto out;
 
 	if (ntohl(header->version) != REGDB_VERSION)
-		return NULL;
+		goto out;
 
 	siglen = ntohl(header->signature_length);
 	/* adjust dblen so later sanity checks don't run into the signature */
 	dblen -= siglen;
 
 	if (dblen <= (int)sizeof(*header))
-		return NULL;
+		goto out;
 
 	/* verify signature */
 	if (!crda_verify_db_signature(db, dblen, siglen))
-		return NULL;
+		goto out;
 
 	num_countries = ntohl(header->reg_country_num);
 	countries = crda_get_file_ptr(db, dblen,
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 12/40] crda: explicitly munmap() on reglib_get_rd_alpha2()
From: Luis R. Rodriguez @ 2013-05-31  2:09 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

Although the region mapped by mmap() is also automatically
unmapped when the process is terminated lets just munmap()
it ourselves to be more tidy.

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 reglib.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/reglib.c b/reglib.c
index 867e8cf..bb6f23f 100644
--- a/reglib.c
+++ b/reglib.c
@@ -357,6 +357,7 @@ reglib_get_rd_alpha2(const char *alpha2, const char *file)
 
 out:
 	close(fd);
+	munmap(db, dblen);
 	return rd;
 }
 
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 11/40] crda: fix intersect.c memory management
From: Luis R. Rodriguez @ 2013-05-31  2:09 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

We didn't free memory in some cases, fix this and
to help with the complexity also simplify the case
where any regdom_intersect() fails by completely
failing. In such cases we need an alternative strategy
to build "world regulatory" domains.

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 intersect.c |   34 +++++++++++++---------------------
 1 file changed, 13 insertions(+), 21 deletions(-)

diff --git a/intersect.c b/intersect.c
index 169fe1a..970f4db 100644
--- a/intersect.c
+++ b/intersect.c
@@ -24,8 +24,10 @@ int main(int argc, char **argv)
 
 	/* We intersect only when we have to rd structures ready */
 	reglib_for_each_country(rd, idx, argv[1]) {
-		if (is_world_regdom((const char *) rd->alpha2))
+		if (is_world_regdom((const char *) rd->alpha2)) {
+			free((struct ieee80211_regdomain *) rd);
 			continue;
+		}
 
 		if (!prev_world) {
 			prev_world = (struct ieee80211_regdomain *) rd;
@@ -39,18 +41,10 @@ int main(int argc, char **argv)
 
 		world = regdom_intersect(prev_world, rd);
 		if (!world) {
-			/* Could be something else but we'll live with this */
-			r = -ENOMEM;
-			if (intersected)
-				fprintf(stderr, "Could not intersect world "
-					"with country (%.2s)\n",
-					rd->alpha2);
-			else
-				fprintf(stderr, "Could not intersect country (%.2s) "
-					"with country (%.2s)\n",
-					prev_world->alpha2,
-					rd->alpha2);
-			continue;
+			free(prev_world);
+			free((struct ieee80211_regdomain *) rd);
+			fprintf(stderr, "Intersection not possible\n");
+			return -ENOENT;
 		}
 
 		if (intersected)
@@ -71,6 +65,7 @@ int main(int argc, char **argv)
 				rd->n_reg_rules,
 				world->n_reg_rules);
 		intersected++;
+		free((struct ieee80211_regdomain *) rd);
 	}
 
 	if (!idx) {
@@ -83,28 +78,25 @@ int main(int argc, char **argv)
 		printf("%d regulatory domains intersected\n", intersected);
 	else {
 		world = prev_world;
+		prev_world = NULL;
 		printf("No intersections completed\n");
 		if (idx > 1) {
 			printf("Since more than one regulatory domain is "
 			       "present and no intersections were possible "
 			       "no globally allowed spectrum is possible so "
 			       "consider enabling passive scan flags\n");
+			free(world);
 			return r;
 		}
 	}
 
+	if (prev_world)
+		free(prev_world);
+
 	/* Tada! */
 	printf("== World regulatory domain: ==\n");
 	print_regdom(world);
 
-	if (!intersected) {
-		free(world);
-		return r;
-	}
-	if (intersected > 1) {
-		free((struct ieee80211_regdomain *)rd);
-		free(prev_world);
-	}
 	free(world);
 	return r;
 }
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 10/40] crda: annotate intersection worst case scenerio
From: Luis R. Rodriguez @ 2013-05-31  2:08 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

In the worst case scenerio of regulatory domain intersections
between a different set of regulatory rules you will end up
without being able to initiate radiation on any frequency
range. Provide a hint as to what needs to be done next in
order to actually build a useful regulatory domain. Currently
we do this manually but building the mathematics would be
even more useful as we grow usage of the spectrum.

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 intersect.c |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/intersect.c b/intersect.c
index dea9145..169fe1a 100644
--- a/intersect.c
+++ b/intersect.c
@@ -83,7 +83,14 @@ int main(int argc, char **argv)
 		printf("%d regulatory domains intersected\n", intersected);
 	else {
 		world = prev_world;
-		printf("Only one intersection completed\n");
+		printf("No intersections completed\n");
+		if (idx > 1) {
+			printf("Since more than one regulatory domain is "
+			       "present and no intersections were possible "
+			       "no globally allowed spectrum is possible so "
+			       "consider enabling passive scan flags\n");
+			return r;
+		}
 	}
 
 	/* Tada! */
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 09/40] crda: do not double count on reglib_for_each_country()
From: Luis R. Rodriguez @ 2013-05-31  2:08 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

Commit ebcbfcf4 introduced reglib_for_each_country() used
by regdbump and later intersect. This helper however only
increased the index count after we requestd getting a new
regulatory domain, this is incorrect and causes us to iterate
over the same element twice in the beginning. This means
intersection and regdb printing was going over the first
element twice. This has been present since v1.1.

This also requires an adjustment on intersect due to the
way things were being handled before.

mcgrof@frijol ~/devel/crda (git::master)$ git describe --contains ebcbfcf4
v1.1.3~9

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 intersect.c |   10 +++-------
 reglib.h    |    3 +--
 2 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/intersect.c b/intersect.c
index 5cb7d7c..dea9145 100644
--- a/intersect.c
+++ b/intersect.c
@@ -79,16 +79,12 @@ int main(int argc, char **argv)
 		return -EINVAL;
 	}
 
-	if (idx == 1) {
-		world = (struct ieee80211_regdomain *) rd;
-		rd = NULL;
-	}
-
-
 	if (intersected > 1)
 		printf("%d regulatory domains intersected\n", intersected);
-	else
+	else {
+		world = prev_world;
 		printf("Only one intersection completed\n");
+	}
 
 	/* Tada! */
 	printf("== World regulatory domain: ==\n");
diff --git a/reglib.h b/reglib.h
index b52d717..8bd9e03 100644
--- a/reglib.h
+++ b/reglib.h
@@ -79,8 +79,7 @@ reglib_get_rd_idx(unsigned int idx, const char *file);
 #define reglib_for_each_country(__rd, __idx, __file)			\
 	for (__rd = reglib_get_rd_idx(__idx, __file);		\
 	     __rd != NULL;						\
-	     __rd = reglib_get_rd_idx(__idx, __file),		\
-	     __idx++)
+	     __rd = reglib_get_rd_idx(++__idx, __file))		\
 
 const struct ieee80211_regdomain *
 reglib_get_rd_alpha2(const char *alpha2, const char *file);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 08/40] crda: move intersection if first attempt failed
From: Luis R. Rodriguez @ 2013-05-31  2:08 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

The intersection should be able to continue on even if
the first two countries could not be intersected.

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 intersect.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/intersect.c b/intersect.c
index 8f826a0..5cb7d7c 100644
--- a/intersect.c
+++ b/intersect.c
@@ -50,7 +50,7 @@ int main(int argc, char **argv)
 					"with country (%.2s)\n",
 					prev_world->alpha2,
 					rd->alpha2);
-			goto out;
+			continue;
 		}
 
 		if (intersected)
@@ -94,7 +94,6 @@ int main(int argc, char **argv)
 	printf("== World regulatory domain: ==\n");
 	print_regdom(world);
 
-out:
 	if (!intersected) {
 		free(world);
 		return r;
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 07/40] crda: fix regression when using reglib_for_each_country()
From: Luis R. Rodriguez @ 2013-05-31  2:08 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

When reglib_for_each_country() was introduced via ebcbfcf4
its users were not updated with the possibility of rd being
NULL due to the fact that the parsed file could be invalid
or empty. The users

mcgrof@frijol ~/devel/crda (git::master)$ git describe --contains 7a09f4dd
v1.1.3~8

mcgrof@frijol ~/devel/crda (git::master)$ git describe --contains ebcbfcf45
v1.1.3~9

This regression exists since v1.1. Fix this.

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 intersect.c |    6 ++++++
 regdbdump.c |    7 +++++++
 2 files changed, 13 insertions(+)

diff --git a/intersect.c b/intersect.c
index 1c00a67..8f826a0 100644
--- a/intersect.c
+++ b/intersect.c
@@ -73,6 +73,12 @@ int main(int argc, char **argv)
 		intersected++;
 	}
 
+	if (!idx) {
+		printf("Invalid or empty regulatory file, note: "
+		       "a binary regulatory file should be used.\n");
+		return -EINVAL;
+	}
+
 	if (idx == 1) {
 		world = (struct ieee80211_regdomain *) rd;
 		rd = NULL;
diff --git a/regdbdump.c b/regdbdump.c
index 26cbef7..dcbed71 100644
--- a/regdbdump.c
+++ b/regdbdump.c
@@ -1,4 +1,5 @@
 #include <stdio.h>
+#include <errno.h>
 #include "reglib.h"
 
 int main(int argc, char **argv)
@@ -16,5 +17,11 @@ int main(int argc, char **argv)
 		free((struct ieee80211_regdomain *) rd);
 	}
 
+	if (!idx) {
+		printf("Invalid or empty regulatory file, note: "
+		       "a binary regulatory file should be used.\n");
+		return -EINVAL;
+	}
+
 	return 0;
 }
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 06/40] crda: move regdom_intersect() to reglib
From: Luis R. Rodriguez @ 2013-05-31  2:08 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

This will be used later by other code so just share it.

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 intersect.c |  157 ----------------------------------------------------------
 reglib.c    |  159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 reglib.h    |    3 ++
 3 files changed, 162 insertions(+), 157 deletions(-)

diff --git a/intersect.c b/intersect.c
index 7352e73..1c00a67 100644
--- a/intersect.c
+++ b/intersect.c
@@ -9,163 +9,6 @@
 /* Intersects regulatory domains, this will skip any regulatory marked with
  * an alpha2 of '00', which is used to indicate a regulatory domain */
 
-/* Sanity check on a regulatory rule */
-static int is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
-{
-	const struct ieee80211_freq_range *freq_range = &rule->freq_range;
-	uint32_t freq_diff;
-
-	if (freq_range->start_freq_khz == 0 || freq_range->end_freq_khz == 0)
-		return 0;
-
-	if (freq_range->start_freq_khz > freq_range->end_freq_khz)
-		return 0;
-
-	freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
-
-	if (freq_range->end_freq_khz <= freq_range->start_freq_khz ||
-	    freq_range->max_bandwidth_khz > freq_diff)
-		return 0;
-
-	return 1;
-}
-
-/* Helper for regdom_intersect(), this does the real
- * mathematical intersection fun */
-static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1,
-			       const struct ieee80211_reg_rule *rule2,
-			       struct ieee80211_reg_rule *intersected_rule)
-{
-	const struct ieee80211_freq_range *freq_range1, *freq_range2;
-	struct ieee80211_freq_range *freq_range;
-	const struct ieee80211_power_rule *power_rule1, *power_rule2;
-	struct ieee80211_power_rule *power_rule;
-	uint32_t freq_diff;
-
-	freq_range1 = &rule1->freq_range;
-	freq_range2 = &rule2->freq_range;
-	freq_range = &intersected_rule->freq_range;
-
-	power_rule1 = &rule1->power_rule;
-	power_rule2 = &rule2->power_rule;
-	power_rule = &intersected_rule->power_rule;
-
-	freq_range->start_freq_khz = max(freq_range1->start_freq_khz,
-					 freq_range2->start_freq_khz);
-	freq_range->end_freq_khz = min(freq_range1->end_freq_khz,
-				       freq_range2->end_freq_khz);
-	freq_range->max_bandwidth_khz = min(freq_range1->max_bandwidth_khz,
-					    freq_range2->max_bandwidth_khz);
-
-	freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
-	if (freq_range->max_bandwidth_khz > freq_diff)
-		freq_range->max_bandwidth_khz = freq_diff;
-
-	power_rule->max_eirp = min(power_rule1->max_eirp,
-		power_rule2->max_eirp);
-	power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain,
-		power_rule2->max_antenna_gain);
-
-	intersected_rule->flags = rule1->flags | rule2->flags;
-
-	if (!is_valid_reg_rule(intersected_rule))
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- * regdom_intersect - do the intersection between two regulatory domains
- * @rd1: first regulatory domain
- * @rd2: second regulatory domain
- *
- * Use this function to get the intersection between two regulatory domains.
- * Once completed we will mark the alpha2 for the rd as intersected, "98",
- * as no one single alpha2 can represent this regulatory domain.
- *
- * Returns a pointer to the regulatory domain structure which will hold the
- * resulting intersection of rules between rd1 and rd2. We will
- * malloc() this structure for you.
- */
-static struct ieee80211_regdomain *
-regdom_intersect(const struct ieee80211_regdomain *rd1,
-		 const struct ieee80211_regdomain *rd2)
-{
-	int r, size_of_regd;
-	unsigned int x, y;
-	unsigned int num_rules = 0, rule_idx = 0;
-	const struct ieee80211_reg_rule *rule1, *rule2;
-	struct ieee80211_reg_rule *intersected_rule;
-	struct ieee80211_regdomain *rd;
-	/* This is just a dummy holder to help us count */
-	struct ieee80211_reg_rule irule;
-
-	/* Uses the stack temporarily for counter arithmetic */
-	intersected_rule = &irule;
-
-	memset(intersected_rule, 0, sizeof(struct ieee80211_reg_rule));
-
-	if (!rd1 || !rd2)
-		return NULL;
-
-	/* First we get a count of the rules we'll need, then we actually
-	 * build them. This is to so we can malloc() and free() a
-	 * regdomain once. The reason we use reg_rules_intersect() here
-	 * is it will return -EINVAL if the rule computed makes no sense.
-	 * All rules that do check out OK are valid. */
-
-	for (x = 0; x < rd1->n_reg_rules; x++) {
-		rule1 = &rd1->reg_rules[x];
-		for (y = 0; y < rd2->n_reg_rules; y++) {
-			rule2 = &rd2->reg_rules[y];
-			if (!reg_rules_intersect(rule1, rule2,
-					intersected_rule))
-				num_rules++;
-			memset(intersected_rule, 0,
-					sizeof(struct ieee80211_reg_rule));
-		}
-	}
-
-	if (!num_rules)
-		return NULL;
-
-	size_of_regd = sizeof(struct ieee80211_regdomain) +
-		((num_rules + 1) * sizeof(struct ieee80211_reg_rule));
-
-	rd = malloc(size_of_regd);
-	if (!rd)
-		return NULL;
-
-	memset(rd, 0, size_of_regd);
-
-	for (x = 0; x < rd1->n_reg_rules; x++) {
-		rule1 = &rd1->reg_rules[x];
-		for (y = 0; y < rd2->n_reg_rules; y++) {
-			rule2 = &rd2->reg_rules[y];
-			/* This time around instead of using the stack lets
-			 * write to the target rule directly saving ourselves
-			 * a memcpy() */
-			intersected_rule = &rd->reg_rules[rule_idx];
-			r = reg_rules_intersect(rule1, rule2,
-				intersected_rule);
-			if (r)
-				continue;
-			rule_idx++;
-		}
-	}
-
-	if (rule_idx != num_rules) {
-		free(rd);
-		return NULL;
-	}
-
-	rd->n_reg_rules = num_rules;
-	rd->alpha2[0] = '9';
-	rd->alpha2[1] = '9';
-
-	return rd;
-}
-
 int main(int argc, char **argv)
 {
 	int r = 0;
diff --git a/reglib.c b/reglib.c
index 0b1599b..867e8cf 100644
--- a/reglib.c
+++ b/reglib.c
@@ -359,3 +359,162 @@ out:
 	close(fd);
 	return rd;
 }
+
+/* Sanity check on a regulatory rule */
+static int is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
+{
+	const struct ieee80211_freq_range *freq_range = &rule->freq_range;
+	uint32_t freq_diff;
+
+	if (freq_range->start_freq_khz == 0 || freq_range->end_freq_khz == 0)
+		return 0;
+
+	if (freq_range->start_freq_khz > freq_range->end_freq_khz)
+		return 0;
+
+	freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
+
+	if (freq_range->end_freq_khz <= freq_range->start_freq_khz ||
+	    freq_range->max_bandwidth_khz > freq_diff)
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Helper for regdom_intersect(), this does the real
+ * mathematical intersection fun
+ */
+static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1,
+			       const struct ieee80211_reg_rule *rule2,
+			       struct ieee80211_reg_rule *intersected_rule)
+{
+	const struct ieee80211_freq_range *freq_range1, *freq_range2;
+	struct ieee80211_freq_range *freq_range;
+	const struct ieee80211_power_rule *power_rule1, *power_rule2;
+	struct ieee80211_power_rule *power_rule;
+	uint32_t freq_diff;
+
+	freq_range1 = &rule1->freq_range;
+	freq_range2 = &rule2->freq_range;
+	freq_range = &intersected_rule->freq_range;
+
+	power_rule1 = &rule1->power_rule;
+	power_rule2 = &rule2->power_rule;
+	power_rule = &intersected_rule->power_rule;
+
+	freq_range->start_freq_khz = max(freq_range1->start_freq_khz,
+					 freq_range2->start_freq_khz);
+	freq_range->end_freq_khz = min(freq_range1->end_freq_khz,
+				       freq_range2->end_freq_khz);
+	freq_range->max_bandwidth_khz = min(freq_range1->max_bandwidth_khz,
+					    freq_range2->max_bandwidth_khz);
+
+	freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
+	if (freq_range->max_bandwidth_khz > freq_diff)
+		freq_range->max_bandwidth_khz = freq_diff;
+
+	power_rule->max_eirp = min(power_rule1->max_eirp,
+		power_rule2->max_eirp);
+	power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain,
+		power_rule2->max_antenna_gain);
+
+	intersected_rule->flags = rule1->flags | rule2->flags;
+
+	if (!is_valid_reg_rule(intersected_rule))
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * regdom_intersect - do the intersection between two regulatory domains
+ * @rd1: first regulatory domain
+ * @rd2: second regulatory domain
+ *
+ * Use this function to get the intersection between two regulatory domains.
+ * Once completed we will mark the alpha2 for the rd as intersected, "98",
+ * as no one single alpha2 can represent this regulatory domain.
+ *
+ * Returns a pointer to the regulatory domain structure which will hold the
+ * resulting intersection of rules between rd1 and rd2. We will
+ * malloc() this structure for you.
+ */
+struct ieee80211_regdomain *
+regdom_intersect(const struct ieee80211_regdomain *rd1,
+		 const struct ieee80211_regdomain *rd2)
+{
+	int r, size_of_regd;
+	unsigned int x, y;
+	unsigned int num_rules = 0, rule_idx = 0;
+	const struct ieee80211_reg_rule *rule1, *rule2;
+	struct ieee80211_reg_rule *intersected_rule;
+	struct ieee80211_regdomain *rd;
+	/* This is just a dummy holder to help us count */
+	struct ieee80211_reg_rule irule;
+
+	/* Uses the stack temporarily for counter arithmetic */
+	intersected_rule = &irule;
+
+	memset(intersected_rule, 0, sizeof(struct ieee80211_reg_rule));
+
+	if (!rd1 || !rd2)
+		return NULL;
+
+	/* First we get a count of the rules we'll need, then we actually
+	 * build them. This is to so we can malloc() and free() a
+	 * regdomain once. The reason we use reg_rules_intersect() here
+	 * is it will return -EINVAL if the rule computed makes no sense.
+	 * All rules that do check out OK are valid. */
+
+	for (x = 0; x < rd1->n_reg_rules; x++) {
+		rule1 = &rd1->reg_rules[x];
+		for (y = 0; y < rd2->n_reg_rules; y++) {
+			rule2 = &rd2->reg_rules[y];
+			if (!reg_rules_intersect(rule1, rule2,
+					intersected_rule))
+				num_rules++;
+			memset(intersected_rule, 0,
+					sizeof(struct ieee80211_reg_rule));
+		}
+	}
+
+	if (!num_rules)
+		return NULL;
+
+	size_of_regd = sizeof(struct ieee80211_regdomain) +
+		((num_rules + 1) * sizeof(struct ieee80211_reg_rule));
+
+	rd = malloc(size_of_regd);
+	if (!rd)
+		return NULL;
+
+	memset(rd, 0, size_of_regd);
+
+	for (x = 0; x < rd1->n_reg_rules; x++) {
+		rule1 = &rd1->reg_rules[x];
+		for (y = 0; y < rd2->n_reg_rules; y++) {
+			rule2 = &rd2->reg_rules[y];
+			/* This time around instead of using the stack lets
+			 * write to the target rule directly saving ourselves
+			 * a memcpy() */
+			intersected_rule = &rd->reg_rules[rule_idx];
+			r = reg_rules_intersect(rule1, rule2,
+				intersected_rule);
+			if (r)
+				continue;
+			rule_idx++;
+		}
+	}
+
+	if (rule_idx != num_rules) {
+		free(rd);
+		return NULL;
+	}
+
+	rd->n_reg_rules = num_rules;
+	rd->alpha2[0] = '9';
+	rd->alpha2[1] = '9';
+
+	return rd;
+}
diff --git a/reglib.h b/reglib.h
index e5da38b..b52d717 100644
--- a/reglib.h
+++ b/reglib.h
@@ -87,5 +87,8 @@ reglib_get_rd_alpha2(const char *alpha2, const char *file);
 
 /* reg helpers */
 void print_regdom(const struct ieee80211_regdomain *rd);
+struct ieee80211_regdomain *
+regdom_intersect(const struct ieee80211_regdomain *rd1,
+		 const struct ieee80211_regdomain *rd2);
 
 #endif
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 05/40] crda: remove unused BUG_ON() from intersect.c
From: Luis R. Rodriguez @ 2013-05-31  2:08 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 intersect.c |    7 -------
 1 file changed, 7 deletions(-)

diff --git a/intersect.c b/intersect.c
index 59fd007..7352e73 100644
--- a/intersect.c
+++ b/intersect.c
@@ -9,13 +9,6 @@
 /* Intersects regulatory domains, this will skip any regulatory marked with
  * an alpha2 of '00', which is used to indicate a regulatory domain */
 
-#define BUG_ON(foo) do { \
-	if (foo) { \
-		printf("BUG\n"); \
-		exit(-1); \
-	} \
-	} while (0)
-
 /* Sanity check on a regulatory rule */
 static int is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
 {
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 04/40] crda: constify usage of struct ieee80211_regdomain
From: Luis R. Rodriguez @ 2013-05-31  2:08 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

Where we can use const.

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 crda.c         |   12 ++++++------
 intersect.c    |   33 ++++++++++++++++++---------------
 print-regdom.c |    8 ++++----
 regdbdump.c    |    4 ++--
 reglib.c       |   10 +++++-----
 reglib.h       |    6 +++---
 6 files changed, 38 insertions(+), 35 deletions(-)

diff --git a/crda.c b/crda.c
index cdbc69a..fc7a25f 100644
--- a/crda.c
+++ b/crda.c
@@ -116,10 +116,10 @@ static int error_handler(struct sockaddr_nl __attribute__((unused)) *nla,
 	exit(err->error);
 }
 
-static int put_reg_rule(struct ieee80211_reg_rule *rule, struct nl_msg *msg)
+static int put_reg_rule(const struct ieee80211_reg_rule *rule, struct nl_msg *msg)
 {
-	struct ieee80211_freq_range *freq_range;
-	struct ieee80211_power_rule *power_rule;
+	const struct ieee80211_freq_range *freq_range;
+	const struct ieee80211_power_rule *power_rule;
 
 	freq_range = &rule->freq_range;
 	power_rule = &rule->power_rule;
@@ -149,7 +149,7 @@ int main(int argc, char **argv)
 	int finished = 0;
 
 	struct nlattr *nl_reg_rules;
-	struct ieee80211_regdomain *rd = NULL;
+	const struct ieee80211_regdomain *rd = NULL;
 
 	const char *regdb_paths[] = {
 		"/usr/local/lib/crda/regulatory.bin", /* Users/preloads can override */
@@ -199,7 +199,7 @@ int main(int argc, char **argv)
 
 	r = nl80211_init(&nlstate);
 	if (r) {
-		free(rd);
+		free((struct ieee80211_regdomain *) rd);
 		return -EIO;
 	}
 
@@ -267,7 +267,7 @@ nla_put_failure:
 	nlmsg_free(msg);
 out:
 	nl80211_cleanup(&nlstate);
-	free(rd);
+	free((struct ieee80211_regdomain *) rd);
 
 	return r;
 }
diff --git a/intersect.c b/intersect.c
index bd2976f..59fd007 100644
--- a/intersect.c
+++ b/intersect.c
@@ -39,13 +39,14 @@ static int is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
 
 /* Helper for regdom_intersect(), this does the real
  * mathematical intersection fun */
-static int reg_rules_intersect(
-	struct ieee80211_reg_rule *rule1,
-	struct ieee80211_reg_rule *rule2,
-	struct ieee80211_reg_rule *intersected_rule)
+static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1,
+			       const struct ieee80211_reg_rule *rule2,
+			       struct ieee80211_reg_rule *intersected_rule)
 {
-	struct ieee80211_freq_range *freq_range1, *freq_range2, *freq_range;
-	struct ieee80211_power_rule *power_rule1, *power_rule2, *power_rule;
+	const struct ieee80211_freq_range *freq_range1, *freq_range2;
+	struct ieee80211_freq_range *freq_range;
+	const struct ieee80211_power_rule *power_rule1, *power_rule2;
+	struct ieee80211_power_rule *power_rule;
 	uint32_t freq_diff;
 
 	freq_range1 = &rule1->freq_range;
@@ -93,14 +94,15 @@ static int reg_rules_intersect(
  * resulting intersection of rules between rd1 and rd2. We will
  * malloc() this structure for you.
  */
-static struct ieee80211_regdomain *regdom_intersect(
-	struct ieee80211_regdomain *rd1,
-	struct ieee80211_regdomain *rd2)
+static struct ieee80211_regdomain *
+regdom_intersect(const struct ieee80211_regdomain *rd1,
+		 const struct ieee80211_regdomain *rd2)
 {
 	int r, size_of_regd;
 	unsigned int x, y;
 	unsigned int num_rules = 0, rule_idx = 0;
-	struct ieee80211_reg_rule *rule1, *rule2, *intersected_rule;
+	const struct ieee80211_reg_rule *rule1, *rule2;
+	struct ieee80211_reg_rule *intersected_rule;
 	struct ieee80211_regdomain *rd;
 	/* This is just a dummy holder to help us count */
 	struct ieee80211_reg_rule irule;
@@ -174,7 +176,8 @@ static struct ieee80211_regdomain *regdom_intersect(
 int main(int argc, char **argv)
 {
 	int r = 0;
-	struct ieee80211_regdomain *prev_world = NULL, *rd = NULL, *world = NULL;
+	const struct ieee80211_regdomain *rd;
+	struct ieee80211_regdomain *prev_world = NULL, *world = NULL;
 	int intersected = 0;
 	unsigned int idx = 0;
 
@@ -189,13 +192,13 @@ int main(int argc, char **argv)
 			continue;
 
 		if (!prev_world) {
-			prev_world = rd;
+			prev_world = (struct ieee80211_regdomain *) rd;
 			continue;
 		}
 
 		if (world) {
 			free(prev_world);
-			prev_world = world;
+			prev_world = (struct ieee80211_regdomain *) world;
 		}
 
 		world = regdom_intersect(prev_world, rd);
@@ -235,7 +238,7 @@ int main(int argc, char **argv)
 	}
 
 	if (idx == 1) {
-		world = rd;
+		world = (struct ieee80211_regdomain *) rd;
 		rd = NULL;
 	}
 
@@ -255,7 +258,7 @@ out:
 		return r;
 	}
 	if (intersected > 1) {
-		free(rd);
+		free((struct ieee80211_regdomain *)rd);
 		free(prev_world);
 	}
 	free(world);
diff --git a/print-regdom.c b/print-regdom.c
index 9c65872..abd6488 100644
--- a/print-regdom.c
+++ b/print-regdom.c
@@ -23,10 +23,10 @@ static const char *dfs_domain_name(enum nl80211_dfs_regions region)
 	}
 }
 
-static void print_reg_rule(struct ieee80211_reg_rule *rule)
+static void print_reg_rule(const struct ieee80211_reg_rule *rule)
 {
-	struct ieee80211_freq_range *freq;
-	struct ieee80211_power_rule *power;
+	const struct ieee80211_freq_range *freq;
+	const struct ieee80211_power_rule *power;
 
 	freq  = &rule->freq_range;
 	power = &rule->power_rule;
@@ -70,7 +70,7 @@ static void print_reg_rule(struct ieee80211_reg_rule *rule)
 	printf("\n");
 }
 
-void print_regdom(struct ieee80211_regdomain *rd)
+void print_regdom(const struct ieee80211_regdomain *rd)
 {
 	unsigned int i;
 	printf("country %.2s: %s\n", rd->alpha2,
diff --git a/regdbdump.c b/regdbdump.c
index 6f9592a..26cbef7 100644
--- a/regdbdump.c
+++ b/regdbdump.c
@@ -3,7 +3,7 @@
 
 int main(int argc, char **argv)
 {
-	struct ieee80211_regdomain *rd = NULL;
+	const struct ieee80211_regdomain *rd = NULL;
 	unsigned int idx = 0;
 
 	if (argc != 2) {
@@ -13,7 +13,7 @@ int main(int argc, char **argv)
 
 	reglib_for_each_country(rd, idx, argv[1]) {
 		print_regdom(rd);
-		free(rd);
+		free((struct ieee80211_regdomain *) rd);
 	}
 
 	return 0;
diff --git a/reglib.c b/reglib.c
index 1fafd37..0b1599b 100644
--- a/reglib.c
+++ b/reglib.c
@@ -188,7 +188,7 @@ static void reg_rule2rd(uint8_t *db, int dblen,
 }
 
 /* Converts a file regdomain to ieee80211_regdomain, easier to manage */
-static struct ieee80211_regdomain *
+const static struct ieee80211_regdomain *
 country2rd(uint8_t *db, int dblen,
 	   struct regdb_file_reg_country *country)
 {
@@ -226,7 +226,7 @@ country2rd(uint8_t *db, int dblen,
 	return rd;
 }
 
-struct ieee80211_regdomain *
+const struct ieee80211_regdomain *
 reglib_get_rd_idx(unsigned int idx, const char *file)
 {
 	int fd;
@@ -235,7 +235,7 @@ reglib_get_rd_idx(unsigned int idx, const char *file)
 	struct regdb_file_header *header;
 	struct regdb_file_reg_country *countries;
 	int dblen, siglen, num_countries;
-	struct ieee80211_regdomain *rd = NULL;
+	const struct ieee80211_regdomain *rd = NULL;
 	struct regdb_file_reg_country *country;
 
 	fd = open(file, O_RDONLY);
@@ -288,7 +288,7 @@ reglib_get_rd_idx(unsigned int idx, const char *file)
 	return rd;
 }
 
-struct ieee80211_regdomain *
+const struct ieee80211_regdomain *
 reglib_get_rd_alpha2(const char *alpha2, const char *file)
 {
 	int fd;
@@ -297,7 +297,7 @@ reglib_get_rd_alpha2(const char *alpha2, const char *file)
 	struct regdb_file_header *header;
 	struct regdb_file_reg_country *countries;
 	int dblen, siglen, num_countries;
-	struct ieee80211_regdomain *rd = NULL;
+	const struct ieee80211_regdomain *rd = NULL;
 	struct regdb_file_reg_country *country;
 	unsigned int i;
 	bool found_country = false;
diff --git a/reglib.h b/reglib.h
index 9b9bd5c..e5da38b 100644
--- a/reglib.h
+++ b/reglib.h
@@ -73,7 +73,7 @@ static inline uint32_t min(uint32_t a, uint32_t b)
 void *crda_get_file_ptr(uint8_t *db, int dblen, int structlen, uint32_t ptr);
 int crda_verify_db_signature(uint8_t *db, int dblen, int siglen);
 
-struct ieee80211_regdomain *
+const struct ieee80211_regdomain *
 reglib_get_rd_idx(unsigned int idx, const char *file);
 
 #define reglib_for_each_country(__rd, __idx, __file)			\
@@ -82,10 +82,10 @@ reglib_get_rd_idx(unsigned int idx, const char *file);
 	     __rd = reglib_get_rd_idx(__idx, __file),		\
 	     __idx++)
 
-struct ieee80211_regdomain *
+const struct ieee80211_regdomain *
 reglib_get_rd_alpha2(const char *alpha2, const char *file);
 
 /* reg helpers */
-void print_regdom(struct ieee80211_regdomain *rd);
+void print_regdom(const struct ieee80211_regdomain *rd);
 
 #endif
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 03/40] crda: remove verbose errors out of regdom_intersect()
From: Luis R. Rodriguez @ 2013-05-31  2:08 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

We want to move this to reglib so nuke all that fluff.

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 intersect.c |   13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/intersect.c b/intersect.c
index e35f2cc..bd2976f 100644
--- a/intersect.c
+++ b/intersect.c
@@ -110,10 +110,8 @@ static struct ieee80211_regdomain *regdom_intersect(
 
 	memset(intersected_rule, 0, sizeof(struct ieee80211_reg_rule));
 
-	if (!rd1 || !rd2) {
-		fprintf(stderr, "rd1 or or rd2 is null\n");
+	if (!rd1 || !rd2)
 		return NULL;
-	}
 
 	/* First we get a count of the rules we'll need, then we actually
 	 * build them. This is to so we can malloc() and free() a
@@ -133,19 +131,15 @@ static struct ieee80211_regdomain *regdom_intersect(
 		}
 	}
 
-	if (!num_rules) {
-		fprintf(stderr, "error: num_rules == 0\n");
+	if (!num_rules)
 		return NULL;
-	}
 
 	size_of_regd = sizeof(struct ieee80211_regdomain) +
 		((num_rules + 1) * sizeof(struct ieee80211_reg_rule));
 
 	rd = malloc(size_of_regd);
-	if (!rd) {
-		fprintf(stderr, "no memory left\n");
+	if (!rd)
 		return NULL;
-	}
 
 	memset(rd, 0, size_of_regd);
 
@@ -166,7 +160,6 @@ static struct ieee80211_regdomain *regdom_intersect(
 	}
 
 	if (rule_idx != num_rules) {
-		fprintf(stderr, "Error while doing regdom interesection :(\n");
 		free(rd);
 		return NULL;
 	}
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 02/40] crda: port over Linux is_valid_reg_rule() change bd05f28e
From: Luis R. Rodriguez @ 2013-05-31  2:08 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

This was added upstream:

mcgrof@frijol ~/linux-stable (git::master)$ git describe --contains bd05f28e
v2.6.29~3^2~47

commit bd05f28e1a15ae62994fe309a524695fe26dd834
Author: Roel Kluin <roel.kluin@gmail.com>
Date:   Tue Mar 3 22:55:21 2009 +0100

    cfg80211: test before subtraction on unsigned

    freq_diff is unsigned, so test before subtraction

    Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    Signed-off-by: John W. Linville <linville@tuxdriver.com>

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 intersect.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/intersect.c b/intersect.c
index aa67dbc..e35f2cc 100644
--- a/intersect.c
+++ b/intersect.c
@@ -30,7 +30,8 @@ static int is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
 
 	freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
 
-	if (freq_diff == 0 || freq_range->max_bandwidth_khz > freq_diff)
+	if (freq_range->end_freq_khz <= freq_range->start_freq_khz ||
+	    freq_range->max_bandwidth_khz > freq_diff)
 		return 0;
 
 	return 1;
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 01/40] crda: make reg_rules_intersect() style match Linux
From: Luis R. Rodriguez @ 2013-05-31  2:08 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1369966169-23640-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

This makes reg_rules_intersect() style match exactly
as it is upstream as of next-20130522.

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
 intersect.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/intersect.c b/intersect.c
index 012750d..aa67dbc 100644
--- a/intersect.c
+++ b/intersect.c
@@ -56,11 +56,11 @@ static int reg_rules_intersect(
 	power_rule = &intersected_rule->power_rule;
 
 	freq_range->start_freq_khz = max(freq_range1->start_freq_khz,
-		freq_range2->start_freq_khz);
+					 freq_range2->start_freq_khz);
 	freq_range->end_freq_khz = min(freq_range1->end_freq_khz,
-		freq_range2->end_freq_khz);
+				       freq_range2->end_freq_khz);
 	freq_range->max_bandwidth_khz = min(freq_range1->max_bandwidth_khz,
-		freq_range2->max_bandwidth_khz);
+					    freq_range2->max_bandwidth_khz);
 
 	freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
 	if (freq_range->max_bandwidth_khz > freq_diff)
@@ -71,7 +71,7 @@ static int reg_rules_intersect(
 	power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain,
 		power_rule2->max_antenna_gain);
 
-	intersected_rule->flags = (rule1->flags | rule2->flags);
+	intersected_rule->flags = rule1->flags | rule2->flags;
 
 	if (!is_valid_reg_rule(intersected_rule))
 		return -EINVAL;
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 00/40] crda: reglib enhancements
From: Luis R. Rodriguez @ 2013-05-31  2:08 UTC (permalink / raw)
  To: wireless-regdb; +Cc: linux-wireless, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>

I've hinted I've been working towards a regdb regulatory
library. This pushes that idea further as I was inclined
recently to develop a union algorithm and saw we still
had quite a bit of work to be able to share more consistently.

I'll likely be using the intersection code as basis for this
and as such I've cleaned that up and also ran valgrind over
most of the code. I believe I've fixed all reglib memory
related issues the rest of things valgrind bitches about
are due to netlink.

mcgrof@frijol ~ $ cat .valgrindrc 
--memcheck:leak-check=full
--memcheck:leak-resolution=high
--memcheck:show-reachable=yes
--memcheck:num-callers=50

If this looks OK I'll next start working towards the union
code. The purpose of this is two fold:

Help build regulatory domains out of arbitrary custom
regulatory definitions and to also allow us to build
more thorough world regulatory domains that have passive
scan flags on regulatory rules that are do not fit the
intersection.

Luis R. Rodriguez (40):
  crda: make reg_rules_intersect() style match Linux
  crda: port over Linux is_valid_reg_rule() change bd05f28e
  crda: remove verbose errors out of regdom_intersect()
  crda: constify usage of struct ieee80211_regdomain
  crda: remove unused BUG_ON() from intersect.c
  crda: move regdom_intersect() to reglib
  crda: fix regression when using reglib_for_each_country()
  crda: move intersection if first attempt failed
  crda: do not double count on reglib_for_each_country()
  crda: annotate intersection worst case scenerio
  crda: fix intersect.c memory management
  crda: explicitly munmap() on reglib_get_rd_alpha2()
  crda: explicitly close file descriptor and munmap() on failures
  crda: separate crda_verify_db_signature() implementations
  crda: use gcry_sexp_release() on crda_verify_db_signature()
  crda: explicitly use close() and munmap() on reglib_get_rd_alpha2()
  crda: use gcry_mpi_release() when using gcry_mpi_scan()
  crda: rename world and prev_world on intersect.c
  crda: remove verbosity out of intersect.c
  crda: rename regdom_intersect() to reglib_intersect_rds()
  crda: rename crda_get_file_ptr() to reglib_get_file_ptr()
  crda: rename crda_verify_db_signature() to
    reglib_verify_db_signature()
  crda: rename print_regdom() to reglib_print_regdom()
  crda: add regdb_dfs_regions
  crda: make print-regdom use internal flags
  crda: move reg print helpers to reglib
  crda: rename is_world_regdom() to reglib_is_world_regdom()
  crda: rename isalpha_upper() to reglib_isalpha_upper()
  crda: rename is_alpha2() to reglib_is_alpha2()
  crda: rename is_valid_regdom() to reglib_is_valid_regdom()
  crda: rename max() to reglib_max()
  crda: rename min() to reglib_min()
  crda: fix spacing on reglib_for_each_country()
  crda: clarify intersect.c only computes an intersection
  crda: separate intersecting a full db into a helper
  crda: move reglib_intersect_regdb() to reglib
  crda: move regdbprint to its own helper
  crda: add reglib regdb context helpers:
    reglib_(malloc|free)_regdb_ctx()
  crda: pass struct reglib_regdb_ctx to country2rd()
  crda: make reglib_for_each_country() use the reglib context

 Makefile       |    4 +-
 crda.c         |   14 +-
 intersect.c    |  264 ++---------------------------
 print-regdom.c |   81 ---------
 regdb.h        |   24 ++-
 regdbdump.c    |   30 +++-
 reglib.c       |  518 +++++++++++++++++++++++++++++++++++++++++++++-----------
 reglib.h       |  125 +++++++++++---
 8 files changed, 589 insertions(+), 471 deletions(-)
 delete mode 100644 print-regdom.c

-- 
1.7.10.4


^ permalink raw reply

* [PATCH v3 2/2] iw: add coalesce support
From: Bing Zhao @ 2013-05-30 23:36 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Luis R. Rodriguez, Jouni Malinen,
	Vasanthakumar Thiagarajan, Senthil Balasubramanian,
	Luciano Coelho, Amitkumar Karwar, Bing Zhao
In-Reply-To: <1369956986-23071-1-git-send-email-bzhao@marvell.com>

From: Amitkumar Karwar <akarwar@marvell.com>

User can add one coalesce rule at a time using 'iw coalesce add'
command. The settings can be cleared using 'iw coalesce disable'
command. 'iw coalesce show' displays current configuration.

Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
v3: match cfg80211/nl80211 v3 patchset

 Makefile   |   2 +-
 coalesce.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 info.c     |  14 ++++
 3 files changed, 244 insertions(+), 1 deletion(-)
 create mode 100644 coalesce.c

diff --git a/Makefile b/Makefile
index c485b5e..f042e30 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ OBJS = iw.o genl.o event.o info.o phy.o \
 	interface.o ibss.o station.o survey.o util.o \
 	mesh.o mpath.o scan.o reg.o version.o \
 	reason.o status.o connect.o link.o offch.o ps.o cqm.o \
-	bitrate.o wowlan.o roc.o p2p.o
+	bitrate.o wowlan.o coalesce.o roc.o p2p.o
 OBJS += sections.o
 
 OBJS-$(HWSIM) += hwsim.o
diff --git a/coalesce.c b/coalesce.c
new file mode 100644
index 0000000..c3551e3
--- /dev/null
+++ b/coalesce.c
@@ -0,0 +1,229 @@
+#include <net/if.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+
+#include <arpa/inet.h>
+
+#include "nl80211.h"
+#include "iw.h"
+
+SECTION(coalesce);
+
+static int handle_coalesce_add(struct nl80211_state *state, struct nl_cb *cb,
+			       struct nl_msg *msg, int argc, char **argv,
+			       enum id_input id)
+{
+	struct nlattr *coalesce, *pattern;
+	struct nl_msg *patterns = NULL;
+	enum {
+		PS_REG,
+		PS_PAT,
+	} parse_state = PS_REG;
+	int err = -ENOBUFS;
+	unsigned char *pat, *mask;
+	size_t patlen;
+	int patnum = 0, pkt_offset;
+	char *eptr, *value1, *value2, *sptr = NULL, *end;
+	enum nl80211_coalesce_condition condition;
+
+	coalesce = nla_nest_start(msg, NL80211_ATTR_COALESCE_RULE);
+	if (!coalesce)
+		return -ENOBUFS;
+
+	NLA_PUT_U32(msg, NL80211_ATTR_COALESCE_RULE_DELAY,
+		    strtoul(argv[0], &end, 10));
+	if (*end != '\0')
+		return 1;
+
+	argv++;
+	argc--;
+
+	condition = strtoul(argv[0], &end, 10);
+
+	if (*end)
+		return 1;
+
+	NLA_PUT_U32(msg, NL80211_ATTR_COALESCE_RULE_CONDITION, condition);
+
+	argv++;
+	argc--;
+
+	while (argc) {
+		switch (parse_state) {
+		case PS_REG:
+			if (strcmp(argv[0], "patterns") == 0) {
+				parse_state = PS_PAT;
+				patterns = nlmsg_alloc();
+				if (!patterns) {
+					err = -ENOMEM;
+					goto nla_put_failure;
+				}
+			} else {
+				err = 1;
+				goto nla_put_failure;
+			}
+			break;
+		case PS_PAT:
+			value1 = strtok_r(argv[0], "+", &sptr);
+			value2 = strtok_r(NULL, "+", &sptr);
+
+			if (!value2) {
+				pkt_offset = 0;
+				value2 = value1;
+			} else {
+				pkt_offset = strtoul(value1, &eptr, 10);
+				if (eptr != value1 + strlen(value1)) {
+					err = 1;
+					goto nla_put_failure;
+				}
+			}
+
+			if (parse_hex_mask(value2, &pat, &patlen, &mask)) {
+				err = 1;
+				goto nla_put_failure;
+			}
+
+			pattern = nla_nest_start(patterns, ++patnum);
+			NLA_PUT(patterns, NL80211_PKTPAT_MASK,
+				DIV_ROUND_UP(patlen, 8), mask);
+			NLA_PUT(patterns, NL80211_PKTPAT_PATTERN, patlen, pat);
+			NLA_PUT_U32(patterns, NL80211_PKTPAT_OFFSET,
+				    pkt_offset);
+			nla_nest_end(patterns, pattern);
+			free(mask);
+			free(pat);
+			break;
+		}
+		argv++;
+		argc--;
+	}
+
+	if (patterns)
+		nla_put_nested(msg, NL80211_ATTR_COALESCE_RULE_PKT_PATTERN,
+			       patterns);
+
+	nla_nest_end(msg, coalesce);
+	err = 0;
+ nla_put_failure:
+	nlmsg_free(patterns);
+	return err;
+}
+COMMAND(coalesce, add, "<delay> <0|1> patterns [offset1+]<pattern1> ...]",
+	NL80211_CMD_SET_COALESCE, 0, CIB_PHY, handle_coalesce_add,
+	"Add coalesce rule.\n"
+	"Maximum coalescing delay in msec.\n"
+	"Condition is 0/1 i.e. 'not match'/'match' the patterns\n"
+	"Each pattern is given as a bytestring with '-' in places where any byte\n"
+	"may be present, e.g. 00:11:22:-:44 will match 00:11:22:33:44 and\n"
+	"00:11:22:33:ff:44 etc.\n"
+	"Offset and pattern should be separated by '+', e.g. 18+43:34:00:12 will\n"
+	"match '43:34:00:12' after 18 bytes of offset in Rx packet.\n");
+
+static int
+handle_coalesce_disable(struct nl80211_state *state, struct nl_cb *cb,
+			struct nl_msg *msg, int argc, char **argv,
+			enum id_input id)
+{
+	/* just a set w/o coalesce attribute */
+	return 0;
+}
+COMMAND(coalesce, disable, "", NL80211_CMD_SET_COALESCE, 0, CIB_PHY,
+	handle_coalesce_disable, "Disable coalesce.");
+
+static int print_coalesce_handler(struct nl_msg *msg, void *arg)
+{
+	struct nlattr *attrs[NL80211_ATTR_MAX + 1];
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	struct nlattr *pattern, *rule;
+	int rem_pattern, rem_rule;
+	enum nl80211_coalesce_condition condition;
+	int delay;
+
+	nla_parse(attrs, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+		  genlmsg_attrlen(gnlh, 0), NULL);
+
+	if (!attrs[NL80211_ATTR_COALESCE_RULE]) {
+		printf("Coalesce is disabled.\n");
+		return NL_SKIP;
+	}
+
+	printf("Coalesce is enabled:\n");
+
+	nla_for_each_nested(rule, attrs[NL80211_ATTR_COALESCE_RULE], rem_rule) {
+		struct nlattr *ruleattr[NUM_NL80211_ATTR_COALESCE_RULE];
+
+		nla_parse(ruleattr, NL80211_ATTR_COALESCE_RULE_MAX,
+			  nla_data(rule), nla_len(rule), NULL);
+
+		delay = nla_get_u32(ruleattr[NL80211_ATTR_COALESCE_RULE_DELAY]);
+		condition =
+		     nla_get_u32(ruleattr[NL80211_ATTR_COALESCE_RULE_CONDITION]);
+
+		printf("Rule - max coalescing delay: %dmsec condition:", delay);
+		if (condition)
+			printf("match\n");
+		else
+			printf("not match\n");
+
+		if (ruleattr[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN]) {
+			nla_for_each_nested(pattern,
+					ruleattr[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
+					rem_pattern) {
+				struct nlattr *patattr[NUM_NL80211_PKTPAT];
+				int i, patlen, masklen, pkt_offset;
+				uint8_t *mask, *pat;
+
+				nla_parse(patattr, MAX_NL80211_PKTPAT,
+					  nla_data(pattern), nla_len(pattern),
+					  NULL);
+				if (!patattr[NL80211_PKTPAT_MASK] ||
+				    !patattr[NL80211_PKTPAT_PATTERN] ||
+				    !patattr[NL80211_PKTPAT_OFFSET]) {
+					printf(" * (invalid pattern specification)\n");
+					continue;
+				}
+				masklen = nla_len(patattr[NL80211_PKTPAT_MASK]);
+				patlen = nla_len(patattr[NL80211_PKTPAT_PATTERN]);
+				pkt_offset = nla_get_u32(patattr[NL80211_PKTPAT_OFFSET]);
+				if (DIV_ROUND_UP(patlen, 8) != masklen) {
+					printf(" * (invalid pattern specification)\n");
+					continue;
+				}
+				printf(" * packet offset: %d", pkt_offset);
+				printf(" pattern: ");
+				pat = nla_data(patattr[NL80211_PKTPAT_PATTERN]);
+				mask = nla_data(patattr[NL80211_PKTPAT_MASK]);
+				for (i = 0; i < patlen; i++) {
+					if (mask[i / 8] & (1 << (i % 8)))
+						printf("%.2x", pat[i]);
+					else
+						printf("--");
+					if (i != patlen - 1)
+						printf(":");
+				}
+				printf("\n");
+			}
+		}
+	}
+
+	return NL_SKIP;
+}
+
+static int handle_coalesce_show(struct nl80211_state *state, struct nl_cb *cb,
+			      struct nl_msg *msg, int argc, char **argv,
+			      enum id_input id)
+{
+	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
+		  print_coalesce_handler, NULL);
+
+	return 0;
+}
+COMMAND(coalesce, show, "", NL80211_CMD_GET_COALESCE, 0, CIB_PHY, handle_coalesce_show,
+	"Show coalesce status.");
diff --git a/info.c b/info.c
index d893ffc..849da67 100644
--- a/info.c
+++ b/info.c
@@ -528,6 +528,20 @@ broken_combination:
 			printf("\tDevice supports AP scan.\n");
 	}
 
+	if (tb_msg[NL80211_ATTR_COALESCE_RULE]) {
+		struct nl80211_coalesce_rule_support *rule;
+		struct nl80211_pattern_support *pat;
+
+		printf("\tCoalesce support:\n");
+		rule = nla_data(tb_msg[NL80211_ATTR_COALESCE_RULE]);
+		pat = &rule->pat;
+		printf("\t\t * Maximum %u coalesce rules supported\n"
+		       "\t\t * Each rule contains upto %u patterns of %u-%u bytes,\n"
+		       "\t\t   maximum packet offset %u bytes\n",
+			rule->max_rules, pat->max_patterns, pat->min_pattern_len,
+			pat->max_pattern_len, pat->max_pkt_offset);
+	}
+
 	return NL_SKIP;
 }
 
-- 
1.8.0


^ permalink raw reply related

* [PATCH v3 1/2] iw: use updated structures and enums for packet pattern
From: Bing Zhao @ 2013-05-30 23:36 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Luis R. Rodriguez, Jouni Malinen,
	Vasanthakumar Thiagarajan, Senthil Balasubramanian,
	Luciano Coelho, Amitkumar Karwar, Bing Zhao

From: Amitkumar Karwar <akarwar@marvell.com>

They are renamed in new nl80211.h so that they can be used for
new feature. This patch uses those updated structures and enums
to make the code look nicer.

Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
v3: use new structure/enum names to make the code look nicer

 info.c   |  2 +-
 wowlan.c | 32 ++++++++++++++++----------------
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/info.c b/info.c
index 54d9a8d..d893ffc 100644
--- a/info.c
+++ b/info.c
@@ -432,7 +432,7 @@ broken_combination:
 			[NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG },
 			[NL80211_WOWLAN_TRIG_TCP_CONNECTION] = { .type = NLA_NESTED },
 		};
-		struct nl80211_wowlan_pattern_support *pat;
+		struct nl80211_pattern_support *pat;
 		int err;
 
 		err = nla_parse_nested(tb_wowlan, MAX_NL80211_WOWLAN_TRIG,
diff --git a/wowlan.c b/wowlan.c
index b4a2715..d323ca7 100644
--- a/wowlan.c
+++ b/wowlan.c
@@ -261,11 +261,11 @@ static int handle_wowlan_enable(struct nl80211_state *state, struct nl_cb *cb,
 			}
 
 			pattern = nla_nest_start(patterns, ++patnum);
-			NLA_PUT(patterns, NL80211_WOWLAN_PKTPAT_MASK,
+			NLA_PUT(patterns, NL80211_PKTPAT_MASK,
 				DIV_ROUND_UP(patlen, 8), mask);
-			NLA_PUT(patterns, NL80211_WOWLAN_PKTPAT_PATTERN,
-				patlen, pat);
-			NLA_PUT_U32(patterns, NL80211_WOWLAN_PKTPAT_OFFSET, pkt_offset);
+			NLA_PUT(patterns, NL80211_PKTPAT_PATTERN, patlen, pat);
+			NLA_PUT_U32(patterns, NL80211_PKTPAT_OFFSET,
+				    pkt_offset);
 			nla_nest_end(patterns, pattern);
 			free(mask);
 			free(pat);
@@ -356,29 +356,29 @@ static int print_wowlan_handler(struct nl_msg *msg, void *arg)
 		nla_for_each_nested(pattern,
 				    trig[NL80211_WOWLAN_TRIG_PKT_PATTERN],
 				    rem_pattern) {
-			struct nlattr *patattr[NUM_NL80211_WOWLAN_PKTPAT];
+			struct nlattr *patattr[NUM_NL80211_PKTPAT];
 			int i, patlen, masklen, pkt_offset;
 			uint8_t *mask, *pat;
-			nla_parse(patattr, MAX_NL80211_WOWLAN_PKTPAT,
-				  nla_data(pattern), nla_len(pattern),
-				  NULL);
-			if (!patattr[NL80211_WOWLAN_PKTPAT_MASK] ||
-			    !patattr[NL80211_WOWLAN_PKTPAT_PATTERN] ||
-			    !patattr[NL80211_WOWLAN_PKTPAT_OFFSET]) {
+			nla_parse(patattr, MAX_NL80211_PKTPAT,
+				  nla_data(pattern), nla_len(pattern), NULL);
+			if (!patattr[NL80211_PKTPAT_MASK] ||
+			    !patattr[NL80211_PKTPAT_PATTERN] ||
+			    !patattr[NL80211_PKTPAT_OFFSET]) {
 				printf(" * (invalid pattern specification)\n");
 				continue;
 			}
-			masklen = nla_len(patattr[NL80211_WOWLAN_PKTPAT_MASK]);
-			patlen = nla_len(patattr[NL80211_WOWLAN_PKTPAT_PATTERN]);
-			pkt_offset = nla_get_u32(patattr[NL80211_WOWLAN_PKTPAT_OFFSET]);
+			masklen = nla_len(patattr[NL80211_PKTPAT_MASK]);
+			patlen = nla_len(patattr[NL80211_PKTPAT_PATTERN]);
+			pkt_offset =
+				nla_get_u32(patattr[NL80211_PKTPAT_OFFSET]);
 			if (DIV_ROUND_UP(patlen, 8) != masklen) {
 				printf(" * (invalid pattern specification)\n");
 				continue;
 			}
 			printf(" * wake up on packet offset: %d", pkt_offset);
 			printf(" pattern: ");
-			pat = nla_data(patattr[NL80211_WOWLAN_PKTPAT_PATTERN]);
-			mask = nla_data(patattr[NL80211_WOWLAN_PKTPAT_MASK]);
+			pat = nla_data(patattr[NL80211_PKTPAT_PATTERN]);
+			mask = nla_data(patattr[NL80211_PKTPAT_MASK]);
 			for (i = 0; i < patlen; i++) {
 				if (mask[i / 8] & (1 << (i % 8)))
 					printf("%.2x", pat[i]);
-- 
1.8.0


^ permalink raw reply related

* [PATCH v3 2/2] cfg80211/nl80211: Add packet coalesce support
From: Bing Zhao @ 2013-05-30 23:36 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Luis R. Rodriguez, Jouni Malinen,
	Vasanthakumar Thiagarajan, Senthil Balasubramanian,
	Luciano Coelho, Amitkumar Karwar, Bing Zhao
In-Reply-To: <1369956962-23038-1-git-send-email-bzhao@marvell.com>

From: Amitkumar Karwar <akarwar@marvell.com>

In most cases, host that receives IPv4 and IPv6 multicast/broadcast
packets does not do anything with these packets. Therefore the
reception of these unwanted packets causes unnecessary processing
and power consumption.

Packet coalesce feature helps to reduce number of received
interrupts to host by buffering these packets in firmware/hardware
for some predefined time. Received interrupt will be generated when
one of the following events occur.
a) Expiration of hardware timer whose expiration time is set to
maximum coalescing delay of matching coalesce rule.
b) Coalescing buffer in hardware reaches it's limit.
c) Packet doesn't match any of the configured coalesce rules.

This patch adds set/get configuration support for packet coalesce.
User needs to configure following parameters for creating a coalesce
rule.
a) Maximum coalescing delay
b) List of packet patterns which needs to be matched
c) Condition for coalescence. pattern 'match' or 'no match'
Multiple such rules can be created.

This feature needs to be advertised during driver initialization.
Drivers are supposed to do required firmware/hardware settings based
on user configuration.

Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
v2: add documentation in nl80211.h and elabiration of "coalesce"
    in commit log (Luis R. Rodriguez)
v3: address comments (Johannes Berg):
    use enum variable for 'condition';
    remove new feature flag;
    remove spurious;
    update documentation

 include/net/cfg80211.h       |  51 ++++++++
 include/uapi/linux/nl80211.h |  89 +++++++++++++-
 net/wireless/core.c          |   2 +
 net/wireless/core.h          |   2 +
 net/wireless/nl80211.c       | 287 +++++++++++++++++++++++++++++++++++++++++++
 net/wireless/nl80211.h       |   2 +
 6 files changed, 431 insertions(+), 2 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9d50877..758c783 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1742,6 +1742,35 @@ struct cfg80211_wowlan {
 };
 
 /**
+ * struct cfg80211_coalesce_rules - Coalesce rule parameters
+ *
+ * This structure defines coalesce rule for the device.
+ * @delay: maximum coalescing delay in msecs.
+ * @condition: condition for packet coalescence.
+ *	see &enum nl80211_coalesce_condition.
+ * @patterns: array of packet patterns
+ * @n_patterns: number of patterns
+ */
+struct cfg80211_coalesce_rules {
+	int delay;
+	enum nl80211_coalesce_condition condition;
+	struct cfg80211_pkt_pattern *patterns;
+	int n_patterns;
+};
+
+/**
+ * struct cfg80211_coalesce - Packet coalescing settings
+ *
+ * This structure defines coalescing settings.
+ * @rules: array of coalesce rules
+ * @n_rules: number of rules
+ */
+struct cfg80211_coalesce {
+	struct cfg80211_coalesce_rules **rules;
+	int n_rules;
+};
+
+/**
  * struct cfg80211_wowlan_wakeup - wakeup report
  * @disconnect: woke up by getting disconnected
  * @magic_pkt: woke up by receiving magic packet
@@ -2037,6 +2066,7 @@ struct cfg80211_update_ft_ies_params {
  *	driver can take the most appropriate actions.
  * @crit_proto_stop: Indicates critical protocol no longer needs increased link
  *	reliability. This operation can not fail.
+ * @set_coalesce: Set coalesce parameters.
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -2272,6 +2302,8 @@ struct cfg80211_ops {
 				    u16 duration);
 	void	(*crit_proto_stop)(struct wiphy *wiphy,
 				   struct wireless_dev *wdev);
+	int	(*set_coalesce)(struct wiphy *wiphy,
+				struct cfg80211_coalesce_rules *rule);
 };
 
 /*
@@ -2496,6 +2528,23 @@ struct wiphy_wowlan_support {
 };
 
 /**
+ * struct wiphy_coalesce_support - coalesce support data
+ * @n_rules: maximum number of coalesce rules
+ * @n_patterns: number of supported patterns
+ *	(see nl80211.h for the pattern definition)
+ * @pattern_max_len: maximum length of each pattern
+ * @pattern_min_len: minimum length of each pattern
+ * @max_pkt_offset: maximum Rx packet offset
+ */
+struct wiphy_coalesce_support {
+	int n_rules;
+	int n_patterns;
+	int pattern_max_len;
+	int pattern_min_len;
+	int max_pkt_offset;
+};
+
+/**
  * struct wiphy - wireless hardware description
  * @reg_notifier: the driver's regulatory notification callback,
  *	note that if your driver uses wiphy_apply_custom_regulatory()
@@ -2605,6 +2654,7 @@ struct wiphy_wowlan_support {
  *	802.11-2012 8.4.2.29 for the defined fields.
  * @extended_capabilities_mask: mask of the valid values
  * @extended_capabilities_len: length of the extended capabilities
+ * @wiphy_coalesce_support coalesce: coalesce support information
  */
 struct wiphy {
 	/* assign these fields before you register the wiphy */
@@ -2714,6 +2764,7 @@ struct wiphy {
 	const struct iw_handler_def *wext;
 #endif
 
+	struct wiphy_coalesce_support coalesce;
 	char priv[0] __aligned(NETDEV_ALIGN);
 };
 
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 7afc244..f09df31 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -126,6 +126,31 @@
  */
 
 /**
+ * DOC: packet coalesce support
+ *
+ * In most cases, host that receives IPv4 and IPv6 multicast/broadcast
+ * packets does not do anything with these packets. Therefore the
+ * reception of these unwanted packets causes unnecessary processing
+ * and power consumption.
+ *
+ * Packet coalesce feature helps to reduce number of received interrupts
+ * to host by buffering these packets in firmware/hardware for some
+ * predefined time. Received interrupt will be generated when one of the
+ * following events occur.
+ * a) Expiration of hardware timer whose expiration time is set to maximum
+ * coalescing delay of matching coalesce rule.
+ * b) Coalescing buffer in hardware reaches it's limit.
+ * c) Packet doesn't match any of the configured coalesce rules.
+ *
+ * User needs to configure following parameters for creating a coalesce
+ * rule.
+ * a) Maximum coalescing delay
+ * b) List of packet patterns which needs to be matched
+ * c) Condition for coalescence. pattern 'match' or 'no match'
+ * Multiple such rules can be created.
+ */
+
+/**
  * enum nl80211_commands - supported nl80211 commands
  *
  * @NL80211_CMD_UNSPEC: unspecified command to catch errors
@@ -648,6 +673,10 @@
  * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can
  *	return back to normal.
  *
+ * @NL80211_CMD_GET_COALESCE: Get currently supported coalesce rules.
+ *
+ * @NL80211_CMD_SET_COALESCE: Add new coalesce rule or clear existing rules.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -810,6 +839,9 @@ enum nl80211_commands {
 	NL80211_CMD_CRIT_PROTOCOL_START,
 	NL80211_CMD_CRIT_PROTOCOL_STOP,
 
+	NL80211_CMD_GET_COALESCE,
+	NL80211_CMD_SET_COALESCE,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -1436,6 +1468,8 @@ enum nl80211_commands {
  *	allowed to be used with the first @NL80211_CMD_SET_STATION command to
  *	update a TDLS peer STA entry.
  *
+ * @NL80211_ATTR_COALESCE_RULE: Coalesce rule information.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1736,6 +1770,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_PEER_AID,
 
+	NL80211_ATTR_COALESCE_RULE,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -3089,8 +3125,10 @@ enum nl80211_packet_pattern_attr {
  * @max_pkt_offset: maximum Rx packet offset
  *
  * This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when
- * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the
- * capability information given by the kernel to userspace.
+ * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED or in
+ * %NL80211_ATTR_COALESCE_RULE_PKT_PATTERN when that is part of
+ * %NL80211_ATTR_COALESCE_RULE in the capability information given
+ * by the kernel to userspace.
  */
 struct nl80211_pattern_support {
 	__u32 max_patterns;
@@ -3309,6 +3347,53 @@ enum nl80211_wowlan_tcp_attrs {
 };
 
 /**
+ * struct nl80211_coalesce_rule_support - coalesce rule support information
+ * @max_rules: maximum number of rules supported
+ * @pat: packet pattern support information
+ *
+ * This struct is carried in %NL80211_ATTR_COALESCE_RULE in the
+ * capability information given by the kernel to userspace.
+ */
+struct nl80211_coalesce_rule_support {
+	__u32 max_rules;
+	struct nl80211_pattern_support pat;
+} __attribute__((packed));
+
+/**
+ * enum nl80211_attr_coalesce_rule - coalesce rule attribute
+ * @__NL80211_COALESCE_RULE_INVALID: invalid number for nested attribute
+ * @NL80211_ATTR_COALESCE_RULE_DELAY: delay in msecs used for packet coalescing
+ * @NL80211_ATTR_COALESCE_RULE_CONDITION: condition for packet coalescence,
+ *	see &enum nl80211_coalesce_condition.
+ * @NL80211_ATTR_COALESCE_RULE_PKT_PATTERN: packet offset, pattern is matched
+ *	after these fixed number of bytes of received packet
+ * @NUM_NL80211_ATTR_COALESCE_RULE: number of attributes
+ * @NL80211_ATTR_COALESCE_RULE_MAX: max attribute number
+ */
+enum nl80211_attr_coalesce_rule {
+	__NL80211_COALESCE_RULE_INVALID,
+	NL80211_ATTR_COALESCE_RULE_DELAY,
+	NL80211_ATTR_COALESCE_RULE_CONDITION,
+	NL80211_ATTR_COALESCE_RULE_PKT_PATTERN,
+
+	/* keep last */
+	NUM_NL80211_ATTR_COALESCE_RULE,
+	NL80211_ATTR_COALESCE_RULE_MAX = NUM_NL80211_ATTR_COALESCE_RULE - 1
+};
+
+/**
+ * enum nl80211_coalesce_condition - coalesce rule conditions
+ * @NL80211_COALESCE_CONDITION_MATCH: coalaesce Rx packets when patterns
+ *	in a rule are matched.
+ * @NL80211_COALESCE_CONDITION_NO_MATCH: coalesce Rx packets when patterns
+ *	in a rule are not matched.
+ */
+enum nl80211_coalesce_condition {
+	NL80211_COALESCE_CONDITION_MATCH,
+	NL80211_COALESCE_CONDITION_NO_MATCH
+};
+
+/**
  * enum nl80211_iface_limit_attrs - limit attributes
  * @NL80211_IFACE_LIMIT_UNSPEC: (reserved)
  * @NL80211_IFACE_LIMIT_MAX: maximum number of interfaces that
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 41cec17..524dffc 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -668,6 +668,8 @@ void wiphy_unregister(struct wiphy *wiphy)
 		rdev_set_wakeup(rdev, false);
 #endif
 	cfg80211_rdev_free_wowlan(rdev);
+
+	cfg80211_rdev_free_coalesce(rdev);
 }
 EXPORT_SYMBOL(wiphy_unregister);
 
diff --git a/net/wireless/core.h b/net/wireless/core.h
index a65eaf8..f6b744b 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -79,6 +79,8 @@ struct cfg80211_registered_device {
 	/* netlink port which started critical protocol (0 means not started) */
 	u32 crit_proto_nlportid;
 
+	struct cfg80211_coalesce *coalesce;
+
 	/* must be last because of the way we do wiphy_priv(),
 	 * and it should at least be aligned to NETDEV_ALIGN */
 	struct wiphy wiphy __aligned(NETDEV_ALIGN);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index af605fe..461f808 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -403,6 +403,14 @@ nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
 	[NL80211_WOWLAN_TCP_WAKE_MASK] = { .len = 1 },
 };
 
+/* policy for coalesce rule attributes */
+static const struct nla_policy
+nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {
+	[NL80211_ATTR_COALESCE_RULE_DELAY] = { .type = NLA_U32 },
+	[NL80211_ATTR_COALESCE_RULE_CONDITION] = { .type = NLA_U32 },
+	[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED },
+};
+
 /* policy for GTK rekey offload attributes */
 static const struct nla_policy
 nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
@@ -998,6 +1006,27 @@ static int nl80211_send_wowlan(struct sk_buff *msg,
 }
 #endif
 
+static int nl80211_send_coalesce(struct sk_buff *msg,
+				 struct cfg80211_registered_device *dev,
+				 bool large)
+{
+	struct nl80211_coalesce_rule_support rule;
+
+	if (!dev->wiphy.coalesce.n_patterns || !dev->wiphy.coalesce.n_rules)
+		return 0;
+
+	rule.max_rules = dev->wiphy.coalesce.n_rules;
+	rule.pat.max_patterns = dev->wiphy.coalesce.n_patterns;
+	rule.pat.min_pattern_len = dev->wiphy.coalesce.pattern_min_len;
+	rule.pat.max_pattern_len = dev->wiphy.coalesce.pattern_max_len;
+	rule.pat.max_pkt_offset = dev->wiphy.coalesce.max_pkt_offset;
+
+	if (nla_put(msg, NL80211_ATTR_COALESCE_RULE, sizeof(rule), &rule))
+		return -ENOBUFS;
+
+	return 0;
+}
+
 static int nl80211_send_band_rateinfo(struct sk_buff *msg,
 				      struct ieee80211_supported_band *sband)
 {
@@ -1509,6 +1538,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
 			    dev->wiphy.vht_capa_mod_mask))
 			goto nla_put_failure;
 
+		(*split_start)++;
+		break;
+	case 10:
+		if (nl80211_send_coalesce(msg, dev, split))
+			goto nla_put_failure;
+
 		/* done */
 		*split_start = 0;
 		break;
@@ -7956,6 +7991,243 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 }
 #endif
 
+static int nl80211_send_coalesce_rules(struct sk_buff *msg,
+				       struct cfg80211_registered_device *rdev)
+{
+	struct nlattr *nl_pats, *nl_pat, *nl_rule, *nl_rules;
+	int i, j, pat_len;
+	struct cfg80211_coalesce_rules *rule;
+
+	if (!rdev->coalesce->n_rules)
+		return 0;
+
+	nl_rules = nla_nest_start(msg, NL80211_ATTR_COALESCE_RULE);
+	if (!nl_rules)
+		return -ENOBUFS;
+
+	for (i = 0; i < rdev->coalesce->n_rules; i++) {
+		nl_rule = nla_nest_start(msg, i + 1);
+		if (!nl_rule)
+			return -ENOBUFS;
+
+		rule = rdev->coalesce->rules[i];
+		if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_DELAY,
+				rule->delay))
+			return -ENOBUFS;
+
+		if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_CONDITION,
+				rule->condition))
+			return -ENOBUFS;
+
+		nl_pats = nla_nest_start(msg,
+				NL80211_ATTR_COALESCE_RULE_PKT_PATTERN);
+		if (!nl_pats)
+			return -ENOBUFS;
+
+		for (j = 0; j < rule->n_patterns; j++) {
+			nl_pat = nla_nest_start(msg, j + 1);
+			if (!nl_pat)
+				return -ENOBUFS;
+			pat_len = rule->patterns[j].pattern_len;
+			if (nla_put(msg, NL80211_PKTPAT_MASK,
+				    DIV_ROUND_UP(pat_len, 8),
+				    rule->patterns[j].mask) ||
+			    nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
+				    rule->patterns[j].pattern) ||
+			    nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
+					rule->patterns[j].pkt_offset))
+				return -ENOBUFS;
+			nla_nest_end(msg, nl_pat);
+		}
+		nla_nest_end(msg, nl_pats);
+		nla_nest_end(msg, nl_rule);
+	}
+	nla_nest_end(msg, nl_rules);
+
+	return 0;
+}
+
+static int nl80211_get_coalesce(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct sk_buff *msg;
+	void *hdr;
+
+	if (!rdev->wiphy.coalesce.n_patterns || !rdev->wiphy.coalesce.n_rules)
+		return -EOPNOTSUPP;
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
+			     NL80211_CMD_GET_COALESCE);
+	if (!hdr)
+		goto nla_put_failure;
+
+	if (rdev->coalesce && nl80211_send_coalesce_rules(msg, rdev))
+		goto nla_put_failure;
+
+	genlmsg_end(msg, hdr);
+	return genlmsg_reply(msg, info);
+
+nla_put_failure:
+	nlmsg_free(msg);
+	return -ENOBUFS;
+}
+
+void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev)
+{
+	int i, j;
+	struct cfg80211_coalesce_rules *rule;
+
+	if (!rdev->coalesce)
+		return;
+
+	for (i = 0; i < rdev->coalesce->n_rules; i++) {
+		rule = rdev->coalesce->rules[i];
+		for (j = 0; j < rule->n_patterns; j++)
+			kfree(rule->patterns[j].mask);
+		kfree(rule->patterns);
+		kfree(rule);
+	}
+	kfree(rdev->coalesce->rules);
+	kfree(rdev->coalesce);
+}
+
+static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct nlattr *tb[NUM_NL80211_ATTR_COALESCE_RULE];
+	struct wiphy_coalesce_support *coalesce = &rdev->wiphy.coalesce;
+	struct cfg80211_coalesce_rules new_rule = {};
+	struct cfg80211_coalesce_rules *nrule;
+	int err, i;
+
+	if (!rdev->wiphy.coalesce.n_patterns || !rdev->wiphy.coalesce.n_rules)
+		return -EOPNOTSUPP;
+	if (!rdev->ops->set_coalesce)
+		return -EOPNOTSUPP;
+
+	if (!info->attrs[NL80211_ATTR_COALESCE_RULE]) {
+		cfg80211_rdev_free_coalesce(rdev);
+		rdev->coalesce = NULL;
+		rdev->ops->set_coalesce(&rdev->wiphy, NULL);
+		return 0;
+	}
+
+	if (!rdev->coalesce) {
+		rdev->coalesce = kzalloc(sizeof(*rdev->coalesce), GFP_KERNEL);
+		rdev->coalesce->rules = kcalloc(coalesce->n_rules,
+						sizeof(void *), GFP_KERNEL);
+	}
+
+	if (rdev->coalesce->n_rules >= coalesce->n_rules)
+		return -EOPNOTSUPP;
+
+	err = nla_parse(tb, NL80211_ATTR_COALESCE_RULE_MAX,
+			nla_data(info->attrs[NL80211_ATTR_COALESCE_RULE]),
+			nla_len(info->attrs[NL80211_ATTR_COALESCE_RULE]),
+			nl80211_coalesce_policy);
+	if (err)
+		return err;
+
+	new_rule.delay = nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_DELAY]);
+	new_rule.condition =
+		nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]);
+	if (new_rule.condition != NL80211_COALESCE_CONDITION_MATCH &&
+	    new_rule.condition != NL80211_COALESCE_CONDITION_NO_MATCH)
+		return -EINVAL;
+
+	if (tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN]) {
+		struct nlattr *pat;
+		int n_patterns = 0;
+		int rem, pat_len, mask_len, pkt_offset;
+		struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
+
+		nla_for_each_nested(pat,
+				    tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
+				    rem)
+			n_patterns++;
+		if (n_patterns > coalesce->n_patterns)
+			return -EINVAL;
+
+		new_rule.patterns = kcalloc(n_patterns,
+						sizeof(new_rule.patterns[0]),
+						GFP_KERNEL);
+		if (!new_rule.patterns)
+			return -ENOMEM;
+
+		new_rule.n_patterns = n_patterns;
+		i = 0;
+
+		nla_for_each_nested(pat,
+				    tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
+				    rem) {
+			nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
+				  nla_len(pat), NULL);
+			err = -EINVAL;
+			if (!pat_tb[NL80211_PKTPAT_MASK] ||
+			    !pat_tb[NL80211_PKTPAT_PATTERN])
+				goto error;
+			pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
+			mask_len = DIV_ROUND_UP(pat_len, 8);
+			if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) !=
+			    mask_len)
+				goto error;
+			if (pat_len > coalesce->pattern_max_len ||
+			    pat_len < coalesce->pattern_min_len)
+				goto error;
+
+			if (!pat_tb[NL80211_PKTPAT_OFFSET])
+				pkt_offset = 0;
+			else
+				pkt_offset = nla_get_u32(
+					pat_tb[NL80211_PKTPAT_OFFSET]);
+			if (pkt_offset > coalesce->max_pkt_offset)
+				goto error;
+			new_rule.patterns[i].pkt_offset = pkt_offset;
+
+			new_rule.patterns[i].mask =
+				kmalloc(mask_len + pat_len, GFP_KERNEL);
+			if (!new_rule.patterns[i].mask) {
+				err = -ENOMEM;
+				goto error;
+			}
+			new_rule.patterns[i].pattern =
+				new_rule.patterns[i].mask + mask_len;
+			memcpy(new_rule.patterns[i].mask,
+			       nla_data(pat_tb[NL80211_PKTPAT_MASK]),
+			       mask_len);
+			new_rule.patterns[i].pattern_len = pat_len;
+			memcpy(new_rule.patterns[i].pattern,
+			       nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
+			       pat_len);
+			i++;
+		}
+	}
+
+	nrule = kmemdup(&new_rule, sizeof(new_rule), GFP_KERNEL);
+	if (!nrule) {
+		err = -ENOMEM;
+		goto error;
+	}
+
+	err = rdev->ops->set_coalesce(&rdev->wiphy, nrule);
+	if (err)
+		goto error;
+
+	rdev->coalesce->rules[rdev->coalesce->n_rules++] = nrule;
+
+	return 0;
+
+error:
+	for (i = 0; i < new_rule.n_patterns; i++)
+		kfree(new_rule.patterns[i].mask);
+	kfree(new_rule.patterns);
+	return err;
+}
+
 static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -8962,6 +9234,21 @@ static struct genl_ops nl80211_ops[] = {
 		.flags = GENL_ADMIN_PERM,
 		.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
 				  NL80211_FLAG_NEED_RTNL,
+	},
+	{
+		.cmd = NL80211_CMD_GET_COALESCE,
+		.doit = nl80211_get_coalesce,
+		.policy = nl80211_policy,
+		.internal_flags = NL80211_FLAG_NEED_WIPHY |
+				  NL80211_FLAG_NEED_RTNL,
+	},
+	{
+		.cmd = NL80211_CMD_SET_COALESCE,
+		.doit = nl80211_set_coalesce,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_WIPHY |
+				  NL80211_FLAG_NEED_RTNL,
 	}
 };
 
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index a4073e8..44341bf 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -74,4 +74,6 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev,
 		     enum nl80211_radar_event event,
 		     struct net_device *netdev, gfp_t gfp);
 
+void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev);
+
 #endif /* __NET_WIRELESS_NL80211_H */
-- 
1.8.0


^ permalink raw reply related

* [PATCH v3 1/2] cfg80211/nl80211: rename packet pattern related structures and enums
From: Bing Zhao @ 2013-05-30 23:36 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Luis R. Rodriguez, Jouni Malinen,
	Vasanthakumar Thiagarajan, Senthil Balasubramanian,
	Luciano Coelho, Amitkumar Karwar, Bing Zhao

From: Amitkumar Karwar <akarwar@marvell.com>

Currently packet patterns and it's enum/structures are used only
for WoWLAN feature. As we intend to reuse them for new feature
packet coalesce, they are renamed in this patch.

Older names are kept for backward compatibility purpose.

Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
v2: more details about the renames in commit log (Luis R. Rodriguez)
    don't break the API with existing applications (Johannes Berg)
v3: __NL80211_PKTPAT_INVALID (Johannes Berg)

 drivers/net/wireless/ath/ath9k/main.c   |  2 +-
 drivers/net/wireless/mwifiex/cfg80211.c |  3 +--
 drivers/net/wireless/ti/wlcore/main.c   | 10 ++++----
 include/net/cfg80211.h                  |  6 ++---
 include/uapi/linux/nl80211.h            | 45 ++++++++++++++++++++-------------
 net/wireless/nl80211.c                  | 34 ++++++++++++-------------
 6 files changed, 53 insertions(+), 47 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index a18414b..5e7a771 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -2127,7 +2127,7 @@ static void ath9k_wow_add_pattern(struct ath_softc *sc,
 {
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath9k_wow_pattern *wow_pattern = NULL;
-	struct cfg80211_wowlan_trig_pkt_pattern *patterns = wowlan->patterns;
+	struct cfg80211_pkt_pattern *patterns = wowlan->patterns;
 	int mask_len;
 	s8 i = 0;
 
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index e42b266..70b8936 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -2247,8 +2247,7 @@ EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf);
 
 #ifdef CONFIG_PM
 static bool
-mwifiex_is_pattern_supported(struct cfg80211_wowlan_trig_pkt_pattern *pat,
-			     s8 *byte_seq)
+mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq)
 {
 	int j, k, valid_byte_cnt = 0;
 	bool dont_care_byte = false;
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 953111a..db3653f 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -1328,7 +1328,7 @@ static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl)
 
 #ifdef CONFIG_PM
 static int
-wl1271_validate_wowlan_pattern(struct cfg80211_wowlan_trig_pkt_pattern *p)
+wl1271_validate_wowlan_pattern(struct cfg80211_pkt_pattern *p)
 {
 	int num_fields = 0, in_field = 0, fields_size = 0;
 	int i, pattern_len = 0;
@@ -1471,9 +1471,9 @@ void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter,
  * Allocates an RX filter returned through f
  * which needs to be freed using rx_filter_free()
  */
-static int wl1271_convert_wowlan_pattern_to_rx_filter(
-	struct cfg80211_wowlan_trig_pkt_pattern *p,
-	struct wl12xx_rx_filter **f)
+static int
+wl1271_convert_wowlan_pattern_to_rx_filter(struct cfg80211_pkt_pattern *p,
+					   struct wl12xx_rx_filter **f)
 {
 	int i, j, ret = 0;
 	struct wl12xx_rx_filter *filter;
@@ -1575,7 +1575,7 @@ static int wl1271_configure_wowlan(struct wl1271 *wl,
 
 	/* Translate WoWLAN patterns into filters */
 	for (i = 0; i < wow->n_patterns; i++) {
-		struct cfg80211_wowlan_trig_pkt_pattern *p;
+		struct cfg80211_pkt_pattern *p;
 		struct wl12xx_rx_filter *filter = NULL;
 
 		p = &wow->patterns[i];
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 6dd1959..9d50877 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1664,7 +1664,7 @@ struct cfg80211_pmksa {
 };
 
 /**
- * struct cfg80211_wowlan_trig_pkt_pattern - packet pattern
+ * struct cfg80211_pkt_pattern - packet pattern
  * @mask: bitmask where to match pattern and where to ignore bytes,
  *	one bit per byte, in same format as nl80211
  * @pattern: bytes to match where bitmask is 1
@@ -1674,7 +1674,7 @@ struct cfg80211_pmksa {
  * Internal note: @mask and @pattern are allocated in one chunk of
  * memory, free @mask only!
  */
-struct cfg80211_wowlan_trig_pkt_pattern {
+struct cfg80211_pkt_pattern {
 	u8 *mask, *pattern;
 	int pattern_len;
 	int pkt_offset;
@@ -1736,7 +1736,7 @@ struct cfg80211_wowlan {
 	bool any, disconnect, magic_pkt, gtk_rekey_failure,
 	     eap_identity_req, four_way_handshake,
 	     rfkill_release;
-	struct cfg80211_wowlan_trig_pkt_pattern *patterns;
+	struct cfg80211_pkt_pattern *patterns;
 	struct cfg80211_wowlan_tcp *tcp;
 	int n_patterns;
 };
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 5920715..7afc244 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3051,11 +3051,11 @@ enum nl80211_tx_power_setting {
 };
 
 /**
- * enum nl80211_wowlan_packet_pattern_attr - WoWLAN packet pattern attribute
- * @__NL80211_WOWLAN_PKTPAT_INVALID: invalid number for nested attribute
- * @NL80211_WOWLAN_PKTPAT_PATTERN: the pattern, values where the mask has
+ * enum nl80211_packet_pattern_attr - packet pattern attribute
+ * @__NL80211_PKTPAT_INVALID: invalid number for nested attribute
+ * @NL80211_PKTPAT_PATTERN: the pattern, values where the mask has
  *	a zero bit are ignored
- * @NL80211_WOWLAN_PKTPAT_MASK: pattern mask, must be long enough to have
+ * @NL80211_PKTPAT_MASK: pattern mask, must be long enough to have
  *	a bit for each byte in the pattern. The lowest-order bit corresponds
  *	to the first byte of the pattern, but the bytes of the pattern are
  *	in a little-endian-like format, i.e. the 9th byte of the pattern
@@ -3066,23 +3066,23 @@ enum nl80211_tx_power_setting {
  *	Note that the pattern matching is done as though frames were not
  *	802.11 frames but 802.3 frames, i.e. the frame is fully unpacked
  *	first (including SNAP header unpacking) and then matched.
- * @NL80211_WOWLAN_PKTPAT_OFFSET: packet offset, pattern is matched after
+ * @NL80211_PKTPAT_OFFSET: packet offset, pattern is matched after
  *	these fixed number of bytes of received packet
- * @NUM_NL80211_WOWLAN_PKTPAT: number of attributes
- * @MAX_NL80211_WOWLAN_PKTPAT: max attribute number
+ * @NUM_NL80211_PKTPAT: number of attributes
+ * @MAX_NL80211_PKTPAT: max attribute number
  */
-enum nl80211_wowlan_packet_pattern_attr {
-	__NL80211_WOWLAN_PKTPAT_INVALID,
-	NL80211_WOWLAN_PKTPAT_MASK,
-	NL80211_WOWLAN_PKTPAT_PATTERN,
-	NL80211_WOWLAN_PKTPAT_OFFSET,
+enum nl80211_packet_pattern_attr {
+	__NL80211_PKTPAT_INVALID,
+	NL80211_PKTPAT_MASK,
+	NL80211_PKTPAT_PATTERN,
+	NL80211_PKTPAT_OFFSET,
 
-	NUM_NL80211_WOWLAN_PKTPAT,
-	MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1,
+	NUM_NL80211_PKTPAT,
+	MAX_NL80211_PKTPAT = NUM_NL80211_PKTPAT - 1,
 };
 
 /**
- * struct nl80211_wowlan_pattern_support - pattern support information
+ * struct nl80211_pattern_support - packet pattern support information
  * @max_patterns: maximum number of patterns supported
  * @min_pattern_len: minimum length of each pattern
  * @max_pattern_len: maximum length of each pattern
@@ -3092,13 +3092,22 @@ enum nl80211_wowlan_packet_pattern_attr {
  * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the
  * capability information given by the kernel to userspace.
  */
-struct nl80211_wowlan_pattern_support {
+struct nl80211_pattern_support {
 	__u32 max_patterns;
 	__u32 min_pattern_len;
 	__u32 max_pattern_len;
 	__u32 max_pkt_offset;
 } __attribute__((packed));
 
+/* only for backward compatibility */
+#define __NL80211_WOWLAN_PKTPAT_INVALID __NL80211_PKTPAT_INVALID
+#define NL80211_WOWLAN_PKTPAT_MASK NL80211_PKTPAT_MASK
+#define NL80211_WOWLAN_PKTPAT_PATTERN NL80211_PKTPAT_PATTERN
+#define NL80211_WOWLAN_PKTPAT_OFFSET NL80211_PKTPAT_OFFSET
+#define NUM_NL80211_WOWLAN_PKTPAT NUM_NL80211_PKTPAT
+#define MAX_NL80211_WOWLAN_PKTPAT MAX_NL80211_PKTPAT
+#define nl80211_wowlan_pattern_support nl80211_pattern_support
+
 /**
  * enum nl80211_wowlan_triggers - WoWLAN trigger definitions
  * @__NL80211_WOWLAN_TRIG_INVALID: invalid number for nested attributes
@@ -3118,7 +3127,7 @@ struct nl80211_wowlan_pattern_support {
  *	pattern matching is done after the packet is converted to the MSDU.
  *
  *	In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute
- *	carrying a &struct nl80211_wowlan_pattern_support.
+ *	carrying a &struct nl80211_pattern_support.
  *
  *	When reporting wakeup. it is a u32 attribute containing the 0-based
  *	index of the pattern that caused the wakeup, in the patterns passed
@@ -3275,7 +3284,7 @@ struct nl80211_wowlan_tcp_data_token_feature {
  * @NL80211_WOWLAN_TCP_WAKE_PAYLOAD: wake packet payload, for advertising a
  *	u32 attribute holding the maximum length
  * @NL80211_WOWLAN_TCP_WAKE_MASK: Wake packet payload mask, not used for
- *	feature advertising. The mask works like @NL80211_WOWLAN_PKTPAT_MASK
+ *	feature advertising. The mask works like @NL80211_PKTPAT_MASK
  *	but on the TCP payload only.
  * @NUM_NL80211_WOWLAN_TCP: number of TCP attributes
  * @MAX_NL80211_WOWLAN_TCP: highest attribute number
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 31d265f..af605fe 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -977,7 +977,7 @@ static int nl80211_send_wowlan(struct sk_buff *msg,
 		return -ENOBUFS;
 
 	if (dev->wiphy.wowlan.n_patterns) {
-		struct nl80211_wowlan_pattern_support pat = {
+		struct nl80211_pattern_support pat = {
 			.max_patterns = dev->wiphy.wowlan.n_patterns,
 			.min_pattern_len = dev->wiphy.wowlan.pattern_min_len,
 			.max_pattern_len = dev->wiphy.wowlan.pattern_max_len,
@@ -7515,12 +7515,11 @@ static int nl80211_send_wowlan_patterns(struct sk_buff *msg,
 		if (!nl_pat)
 			return -ENOBUFS;
 		pat_len = wowlan->patterns[i].pattern_len;
-		if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK,
-			    DIV_ROUND_UP(pat_len, 8),
+		if (nla_put(msg, NL80211_PKTPAT_MASK, DIV_ROUND_UP(pat_len, 8),
 			    wowlan->patterns[i].mask) ||
-		    nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN,
-			    pat_len, wowlan->patterns[i].pattern) ||
-		    nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET,
+		    nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
+			    wowlan->patterns[i].pattern) ||
+		    nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
 				wowlan->patterns[i].pkt_offset))
 			return -ENOBUFS;
 		nla_nest_end(msg, nl_pat);
@@ -7863,7 +7862,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 		struct nlattr *pat;
 		int n_patterns = 0;
 		int rem, pat_len, mask_len, pkt_offset;
-		struct nlattr *pat_tb[NUM_NL80211_WOWLAN_PKTPAT];
+		struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
 
 		nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
 				    rem)
@@ -7882,26 +7881,25 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 
 		nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
 				    rem) {
-			nla_parse(pat_tb, MAX_NL80211_WOWLAN_PKTPAT,
-				  nla_data(pat), nla_len(pat), NULL);
+			nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
+				  nla_len(pat), NULL);
 			err = -EINVAL;
-			if (!pat_tb[NL80211_WOWLAN_PKTPAT_MASK] ||
-			    !pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN])
+			if (!pat_tb[NL80211_PKTPAT_MASK] ||
+			    !pat_tb[NL80211_PKTPAT_PATTERN])
 				goto error;
-			pat_len = nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]);
+			pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
 			mask_len = DIV_ROUND_UP(pat_len, 8);
-			if (nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]) !=
-			    mask_len)
+			if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
 				goto error;
 			if (pat_len > wowlan->pattern_max_len ||
 			    pat_len < wowlan->pattern_min_len)
 				goto error;
 
-			if (!pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET])
+			if (!pat_tb[NL80211_PKTPAT_OFFSET])
 				pkt_offset = 0;
 			else
 				pkt_offset = nla_get_u32(
-					pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET]);
+					pat_tb[NL80211_PKTPAT_OFFSET]);
 			if (pkt_offset > wowlan->max_pkt_offset)
 				goto error;
 			new_triggers.patterns[i].pkt_offset = pkt_offset;
@@ -7915,11 +7913,11 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 			new_triggers.patterns[i].pattern =
 				new_triggers.patterns[i].mask + mask_len;
 			memcpy(new_triggers.patterns[i].mask,
-			       nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]),
+			       nla_data(pat_tb[NL80211_PKTPAT_MASK]),
 			       mask_len);
 			new_triggers.patterns[i].pattern_len = pat_len;
 			memcpy(new_triggers.patterns[i].pattern,
-			       nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]),
+			       nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
 			       pat_len);
 			i++;
 		}
-- 
1.8.0


^ permalink raw reply related

* [PATCH V2 for 3.10] rtlwifi: rtl8192cu: Fix problem in connecting to WEP or WPA(1) networks
From: Larry Finger @ 2013-05-30 23:05 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Larry Finger, netdev, Stable, jogreene

Driver rtl8192cu can connect to WPA2 networks, but fails for any other
encryption method. The cause is a failure to set the rate control data
blocks. These changes fix https://bugzilla.redhat.com/show_bug.cgi?id=952793
and https://bugzilla.redhat.com/show_bug.cgi?id=761525.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---

John,

This patch is pretty large for this stage; however, it fixes a bad bug, and
it will only affect rtl8192cu even though it touches rtlwifi.

I held it for a while while Fedora and RHEL users tried it and responded.
As you well know, that can take a while.

Thanks,

Larry
---

 drivers/net/wireless/rtlwifi/rtl8192cu/hw.c  | 134 ++++++++++++++++++++-------
 drivers/net/wireless/rtlwifi/rtl8192cu/hw.h  |   4 -
 drivers/net/wireless/rtlwifi/rtl8192cu/mac.c |  18 +++-
 drivers/net/wireless/rtlwifi/rtl8192cu/sw.c  |   4 +-
 drivers/net/wireless/rtlwifi/rtl8192cu/sw.h  |   3 +
 drivers/net/wireless/rtlwifi/usb.c           |  13 +++
 drivers/net/wireless/rtlwifi/wifi.h          |   4 +
 7 files changed, 139 insertions(+), 41 deletions(-)

diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
index 3d0498e..189ba12 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
@@ -1973,26 +1973,35 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 	}
 }
 
-void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw,
-				   struct ieee80211_sta *sta,
-				   u8 rssi_level)
+static void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw,
+					  struct ieee80211_sta *sta)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	u32 ratr_value = (u32) mac->basic_rates;
-	u8 *mcsrate = mac->mcs;
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u32 ratr_value;
 	u8 ratr_index = 0;
 	u8 nmode = mac->ht_enable;
-	u8 mimo_ps = 1;
-	u16 shortgi_rate = 0;
-	u32 tmp_ratr_value = 0;
+	u8 mimo_ps = IEEE80211_SMPS_OFF;
+	u16 shortgi_rate;
+	u32 tmp_ratr_value;
 	u8 curtxbw_40mhz = mac->bw_40;
-	u8 curshortgi_40mhz = mac->sgi_40;
-	u8 curshortgi_20mhz = mac->sgi_20;
+	u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
+			       1 : 0;
+	u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
+			       1 : 0;
 	enum wireless_mode wirelessmode = mac->mode;
 
-	ratr_value |= ((*(u16 *) (mcsrate))) << 12;
+	if (rtlhal->current_bandtype == BAND_ON_5G)
+		ratr_value = sta->supp_rates[1] << 4;
+	else
+		ratr_value = sta->supp_rates[0];
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		ratr_value = 0xfff;
+
+	ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
+			sta->ht_cap.mcs.rx_mask[0] << 12);
 	switch (wirelessmode) {
 	case WIRELESS_MODE_B:
 		if (ratr_value & 0x0000000c)
@@ -2006,7 +2015,7 @@ void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw,
 	case WIRELESS_MODE_N_24G:
 	case WIRELESS_MODE_N_5G:
 		nmode = 1;
-		if (mimo_ps == 0) {
+		if (mimo_ps == IEEE80211_SMPS_STATIC) {
 			ratr_value &= 0x0007F005;
 		} else {
 			u32 ratr_mask;
@@ -2016,8 +2025,7 @@ void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw,
 				ratr_mask = 0x000ff005;
 			else
 				ratr_mask = 0x0f0ff005;
-			if (curtxbw_40mhz)
-				ratr_mask |= 0x00000010;
+
 			ratr_value &= ratr_mask;
 		}
 		break;
@@ -2026,41 +2034,74 @@ void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw,
 			ratr_value &= 0x000ff0ff;
 		else
 			ratr_value &= 0x0f0ff0ff;
+
 		break;
 	}
+
 	ratr_value &= 0x0FFFFFFF;
-	if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) ||
-	    (!curtxbw_40mhz && curshortgi_20mhz))) {
+
+	if (nmode && ((curtxbw_40mhz &&
+			 curshortgi_40mhz) || (!curtxbw_40mhz &&
+					       curshortgi_20mhz))) {
+
 		ratr_value |= 0x10000000;
 		tmp_ratr_value = (ratr_value >> 12);
+
 		for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) {
 			if ((1 << shortgi_rate) & tmp_ratr_value)
 				break;
 		}
+
 		shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) |
-			       (shortgi_rate << 4) | (shortgi_rate);
+		    (shortgi_rate << 4) | (shortgi_rate);
 	}
+
 	rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value);
+
+	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n",
+		 rtl_read_dword(rtlpriv, REG_ARFR0));
 }
 
-void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
+static void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw,
+					 struct ieee80211_sta *sta,
+					 u8 rssi_level)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	u32 ratr_bitmap = (u32) mac->basic_rates;
-	u8 *p_mcsrate = mac->mcs;
-	u8 ratr_index = 0;
-	u8 curtxbw_40mhz = mac->bw_40;
-	u8 curshortgi_40mhz = mac->sgi_40;
-	u8 curshortgi_20mhz = mac->sgi_20;
-	enum wireless_mode wirelessmode = mac->mode;
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_sta_info *sta_entry = NULL;
+	u32 ratr_bitmap;
+	u8 ratr_index;
+	u8 curtxbw_40mhz = (sta->bandwidth >= IEEE80211_STA_RX_BW_40) ? 1 : 0;
+	u8 curshortgi_40mhz = curtxbw_40mhz &&
+			      (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
+				1 : 0;
+	u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
+				1 : 0;
+	enum wireless_mode wirelessmode = 0;
 	bool shortgi = false;
 	u8 rate_mask[5];
 	u8 macid = 0;
-	u8 mimops = 1;
-
-	ratr_bitmap |= (p_mcsrate[1] << 20) | (p_mcsrate[0] << 12);
+	u8 mimo_ps = IEEE80211_SMPS_OFF;
+
+	sta_entry = (struct rtl_sta_info *) sta->drv_priv;
+	wirelessmode = sta_entry->wireless_mode;
+	if (mac->opmode == NL80211_IFTYPE_STATION ||
+	    mac->opmode == NL80211_IFTYPE_MESH_POINT)
+		curtxbw_40mhz = mac->bw_40;
+	else if (mac->opmode == NL80211_IFTYPE_AP ||
+		mac->opmode == NL80211_IFTYPE_ADHOC)
+		macid = sta->aid + 1;
+
+	if (rtlhal->current_bandtype == BAND_ON_5G)
+		ratr_bitmap = sta->supp_rates[1] << 4;
+	else
+		ratr_bitmap = sta->supp_rates[0];
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		ratr_bitmap = 0xfff;
+	ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
+			sta->ht_cap.mcs.rx_mask[0] << 12);
 	switch (wirelessmode) {
 	case WIRELESS_MODE_B:
 		ratr_index = RATR_INX_WIRELESS_B;
@@ -2071,6 +2112,7 @@ void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
 		break;
 	case WIRELESS_MODE_G:
 		ratr_index = RATR_INX_WIRELESS_GB;
+
 		if (rssi_level == 1)
 			ratr_bitmap &= 0x00000f00;
 		else if (rssi_level == 2)
@@ -2085,7 +2127,8 @@ void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
 	case WIRELESS_MODE_N_24G:
 	case WIRELESS_MODE_N_5G:
 		ratr_index = RATR_INX_WIRELESS_NGB;
-		if (mimops == 0) {
+
+		if (mimo_ps == IEEE80211_SMPS_STATIC) {
 			if (rssi_level == 1)
 				ratr_bitmap &= 0x00070000;
 			else if (rssi_level == 2)
@@ -2128,8 +2171,10 @@ void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
 				}
 			}
 		}
+
 		if ((curtxbw_40mhz && curshortgi_40mhz) ||
 		    (!curtxbw_40mhz && curshortgi_20mhz)) {
+
 			if (macid == 0)
 				shortgi = true;
 			else if (macid == 1)
@@ -2138,21 +2183,42 @@ void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
 		break;
 	default:
 		ratr_index = RATR_INX_WIRELESS_NGB;
+
 		if (rtlphy->rf_type == RF_1T2R)
 			ratr_bitmap &= 0x000ff0ff;
 		else
 			ratr_bitmap &= 0x0f0ff0ff;
 		break;
 	}
-	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "ratr_bitmap :%x\n",
-		 ratr_bitmap);
-	*(u32 *)&rate_mask = ((ratr_bitmap & 0x0fffffff) |
-				      ratr_index << 28);
+	sta_entry->ratr_index = ratr_index;
+
+	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
+		 "ratr_bitmap :%x\n", ratr_bitmap);
+	*(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) |
+				     (ratr_index << 28);
 	rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
 	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
 		 "Rate_index:%x, ratr_val:%x, %5phC\n",
 		 ratr_index, ratr_bitmap, rate_mask);
-	rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
+	memcpy(rtlpriv->rate_mask, rate_mask, 5);
+	/* rtl92c_fill_h2c_cmd() does USB I/O and will result in a
+	 * "scheduled while atomic" if called directly */
+	schedule_work(&rtlpriv->works.fill_h2c_cmd);
+
+	if (macid != 0)
+		sta_entry->ratr_index = ratr_index;
+}
+
+void rtl92cu_update_hal_rate_tbl(struct ieee80211_hw *hw,
+				 struct ieee80211_sta *sta,
+				 u8 rssi_level)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (rtlpriv->dm.useramask)
+		rtl92cu_update_hal_rate_mask(hw, sta, rssi_level);
+	else
+		rtl92cu_update_hal_rate_table(hw, sta);
 }
 
 void rtl92cu_update_channel_access_setting(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
index f41a3aa..8e3ec1e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
@@ -98,10 +98,6 @@ void rtl92cu_update_interrupt_mask(struct ieee80211_hw *hw,
 				   u32 add_msr, u32 rm_msr);
 void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
 void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
-void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw,
-				   struct ieee80211_sta *sta,
-				   u8 rssi_level);
-void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level);
 
 void rtl92cu_update_channel_access_setting(struct ieee80211_hw *hw);
 bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
index 85b6bdb..da4f587 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
@@ -289,14 +289,30 @@ void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index,
 				macaddr = cam_const_broad;
 				entry_id = key_index;
 			} else {
+				if (mac->opmode == NL80211_IFTYPE_AP ||
+				    mac->opmode == NL80211_IFTYPE_MESH_POINT) {
+					entry_id = rtl_cam_get_free_entry(hw,
+								 p_macaddr);
+					if (entry_id >=  TOTAL_CAM_ENTRY) {
+						RT_TRACE(rtlpriv, COMP_SEC,
+							 DBG_EMERG,
+							 "Can not find free hw security cam entry\n");
+						return;
+					}
+				} else {
+					entry_id = CAM_PAIRWISE_KEY_POSITION;
+				}
+
 				key_index = PAIRWISE_KEYIDX;
-				entry_id = CAM_PAIRWISE_KEY_POSITION;
 				is_pairwise = true;
 			}
 		}
 		if (rtlpriv->sec.key_len[key_index] == 0) {
 			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 				 "delete one entry\n");
+			if (mac->opmode == NL80211_IFTYPE_AP ||
+			    mac->opmode == NL80211_IFTYPE_MESH_POINT)
+				rtl_cam_del_entry(hw, p_macaddr);
 			rtl_cam_delete_one_entry(hw, p_macaddr, entry_id);
 		} else {
 			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
index 23d640a..a00e7d7 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
@@ -106,8 +106,7 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = {
 	.update_interrupt_mask = rtl92cu_update_interrupt_mask,
 	.get_hw_reg = rtl92cu_get_hw_reg,
 	.set_hw_reg = rtl92cu_set_hw_reg,
-	.update_rate_tbl = rtl92cu_update_hal_rate_table,
-	.update_rate_mask = rtl92cu_update_hal_rate_mask,
+	.update_rate_tbl = rtl92cu_update_hal_rate_tbl,
 	.fill_tx_desc = rtl92cu_tx_fill_desc,
 	.fill_fake_txdesc = rtl92cu_fill_fake_txdesc,
 	.fill_tx_cmddesc = rtl92cu_tx_fill_cmddesc,
@@ -137,6 +136,7 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = {
 	.phy_lc_calibrate = _rtl92cu_phy_lc_calibrate,
 	.phy_set_bw_mode_callback = rtl92cu_phy_set_bw_mode_callback,
 	.dm_dynamic_txpower = rtl92cu_dm_dynamic_txpower,
+	.fill_h2c_cmd = rtl92c_fill_h2c_cmd,
 };
 
 static struct rtl_mod_params rtl92cu_mod_params = {
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h
index a1310ab..262e1e4 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h
@@ -49,5 +49,8 @@ bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
 u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw,
 			    enum radio_path rfpath, u32 regaddr, u32 bitmask);
 void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
+void rtl92cu_update_hal_rate_tbl(struct ieee80211_hw *hw,
+				 struct ieee80211_sta *sta,
+				 u8 rssi_level);
 
 #endif
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
index 76732b0..a3532e0 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -824,6 +824,7 @@ static void rtl_usb_stop(struct ieee80211_hw *hw)
 
 	/* should after adapter start and interrupt enable. */
 	set_hal_stop(rtlhal);
+	cancel_work_sync(&rtlpriv->works.fill_h2c_cmd);
 	/* Enable software */
 	SET_USB_STOP(rtlusb);
 	rtl_usb_deinit(hw);
@@ -1026,6 +1027,16 @@ static bool rtl_usb_tx_chk_waitq_insert(struct ieee80211_hw *hw,
 	return false;
 }
 
+static void rtl_fill_h2c_cmd_work_callback(struct work_struct *work)
+{
+	struct rtl_works *rtlworks =
+	    container_of(work, struct rtl_works, fill_h2c_cmd);
+	struct ieee80211_hw *hw = rtlworks->hw;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->cfg->ops->fill_h2c_cmd(hw, H2C_RA_MASK, 5, rtlpriv->rate_mask);
+}
+
 static struct rtl_intf_ops rtl_usb_ops = {
 	.adapter_start = rtl_usb_start,
 	.adapter_stop = rtl_usb_stop,
@@ -1057,6 +1068,8 @@ int rtl_usb_probe(struct usb_interface *intf,
 
 	/* this spin lock must be initialized early */
 	spin_lock_init(&rtlpriv->locks.usb_lock);
+	INIT_WORK(&rtlpriv->works.fill_h2c_cmd,
+		  rtl_fill_h2c_cmd_work_callback);
 
 	rtlpriv->usb_data_index = 0;
 	init_completion(&rtlpriv->firmware_loading_complete);
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index 44328ba..cc03e7c 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -1736,6 +1736,8 @@ struct rtl_hal_ops {
 	void (*bt_wifi_media_status_notify) (struct ieee80211_hw *hw,
 					     bool mstate);
 	void (*bt_coex_off_before_lps) (struct ieee80211_hw *hw);
+	void (*fill_h2c_cmd) (struct ieee80211_hw *hw, u8 element_id,
+			      u32 cmd_len, u8 *p_cmdbuffer);
 };
 
 struct rtl_intf_ops {
@@ -1869,6 +1871,7 @@ struct rtl_works {
 	struct delayed_work fwevt_wq;
 
 	struct work_struct lps_change_work;
+	struct work_struct fill_h2c_cmd;
 };
 
 struct rtl_debug {
@@ -2048,6 +2051,7 @@ struct rtl_priv {
 		};
 	};
 	bool enter_ps;	/* true when entering PS */
+	u8 rate_mask[5];
 
 	/*This must be the last item so
 	   that it points to the data allocated
-- 
1.8.1.4


^ permalink raw reply related

* Re: [PATCH V3.10] rtlwifi: rtl8192cu: Fix problem in connecting to WEP or WPA(1) networks
From: Greg KH @ 2013-05-30 22:13 UTC (permalink / raw)
  To: Larry Finger; +Cc: linville, linux-wireless, netdev, Stable
In-Reply-To: <1369949040-9513-1-git-send-email-Larry.Finger@lwfinger.net>

On Thu, May 30, 2013 at 04:23:30PM -0500, Larry Finger wrote:
> Driver rtl8192cu can connect to WPA2 networks, but fails for any other
> encryption method. The cause is a failure to set the rate control data
> blocks. These changes fix https://bugzilla.redhat.com/show_bug.cgi?id=952793
> and https://bugzilla.redhat.com/show_bug.cgi?id=761525.
> 
> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
> ---
> 
> John,
> 
> This patch is pretty large for this stage; however, it fixes a bad bug, and
> it will only affect rtl8192cu even though it touches rtlwifi.
> 
> I held it for a while while Fedora and RHEL users tried it and responded.
> As you well know, that can take a while.


<formletter>

This is not the correct way to submit patches for inclusion in the
stable kernel tree.  Please read Documentation/stable_kernel_rules.txt
for how to do this properly.

</formletter>

^ permalink raw reply


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