linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] mwifiex: correct aid value during tdls setup
@ 2016-08-09 14:50 Amitkumar Karwar
  2016-08-09 14:50 ` [PATCH 2/3] mwifiex: add CHAN_REGION_CFG command Amitkumar Karwar
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Amitkumar Karwar @ 2016-08-09 14:50 UTC (permalink / raw)
  To: linux-wireless
  Cc: Cathy Luo, Nishant Sarmukadam, Xinming Hu, Amitkumar Karwar

From: Xinming Hu <huxm@marvell.com>

AID gets updated during TDLS setup, but modified value isn't reflected
in "priv->assoc_rsp_buf". This causes TDLS setup failure. The problem is
fixed here.

Fixes: 4aff53ef18e4a4 ("mwifiex: parsing aid while receiving..")
Signed-off-by: Xinming Hu <huxm@marvell.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
---
 drivers/net/wireless/marvell/mwifiex/join.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/join.c b/drivers/net/wireless/marvell/mwifiex/join.c
index 1c7b006..b89596c 100644
--- a/drivers/net/wireless/marvell/mwifiex/join.c
+++ b/drivers/net/wireless/marvell/mwifiex/join.c
@@ -669,9 +669,8 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
 	priv->assoc_rsp_size = min(le16_to_cpu(resp->size) - S_DS_GEN,
 				   sizeof(priv->assoc_rsp_buf));
 
-	memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size);
-
 	assoc_rsp->a_id = cpu_to_le16(aid);
+	memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size);
 
 	if (status_code) {
 		priv->adapter->dbg.num_cmd_assoc_failure++;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] mwifiex: add CHAN_REGION_CFG command
  2016-08-09 14:50 [PATCH 1/3] mwifiex: correct aid value during tdls setup Amitkumar Karwar
@ 2016-08-09 14:50 ` Amitkumar Karwar
  2016-08-09 14:50 ` [PATCH 3/3] mwifiex: add custom regulatory domain support Amitkumar Karwar
  2016-09-03 10:06 ` [1/3] mwifiex: correct aid value during tdls setup Kalle Valo
  2 siblings, 0 replies; 5+ messages in thread
From: Amitkumar Karwar @ 2016-08-09 14:50 UTC (permalink / raw)
  To: linux-wireless; +Cc: Cathy Luo, Nishant Sarmukadam, Amitkumar Karwar

This patch adds command preparation and response handling for
CHAN_REGION_CFG command. These changes are prerequisites for adding
custom regulatory domain support.

Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
---
 drivers/net/wireless/marvell/mwifiex/fw.h          |  7 ++++
 drivers/net/wireless/marvell/mwifiex/sta_cmd.c     | 21 +++++++++++
 drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c | 41 ++++++++++++++++++++++
 3 files changed, 69 insertions(+)

diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
index a88030a..085db99 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -190,6 +190,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define TLV_BTCOEX_WL_SCANTIME      (PROPRIETARY_TLV_BASE_ID + 203)
 #define TLV_TYPE_BSS_MODE           (PROPRIETARY_TLV_BASE_ID + 206)
 #define TLV_TYPE_RANDOM_MAC         (PROPRIETARY_TLV_BASE_ID + 236)
+#define TLV_TYPE_CHAN_ATTR_CFG      (PROPRIETARY_TLV_BASE_ID + 237)
 
 #define MWIFIEX_TX_DATA_BUF_SIZE_2K        2048
 
@@ -382,6 +383,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define HostCmd_CMD_MC_POLICY                         0x0121
 #define HostCmd_CMD_TDLS_OPER                         0x0122
 #define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG               0x0223
+#define HostCmd_CMD_CHAN_REGION_CFG		      0x0242
 
 #define PROTOCOL_NO_SECURITY        0x01
 #define PROTOCOL_STATIC_WEP         0x02
@@ -2224,6 +2226,10 @@ struct host_cmd_ds_gtk_rekey_params {
 	__le32 replay_ctr_high;
 } __packed;
 
+struct host_cmd_ds_chan_region_cfg {
+	__le16 action;
+} __packed;
+
 struct host_cmd_ds_command {
 	__le16 command;
 	__le16 size;
@@ -2298,6 +2304,7 @@ struct host_cmd_ds_command {
 		struct host_cmd_ds_robust_coex coex;
 		struct host_cmd_ds_wakeup_reason hs_wakeup_reason;
 		struct host_cmd_ds_gtk_rekey_params rekey;
+		struct host_cmd_ds_chan_region_cfg reg_cfg;
 	} params;
 } __packed;
 
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
index 1d8f284..49048b4 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
@@ -1594,6 +1594,21 @@ static int mwifiex_cmd_gtk_rekey_offload(struct mwifiex_private *priv,
 	return 0;
 }
 
+static int mwifiex_cmd_chan_region_cfg(struct mwifiex_private *priv,
+				       struct host_cmd_ds_command *cmd,
+				       u16 cmd_action)
+{
+	struct host_cmd_ds_chan_region_cfg *reg = &cmd->params.reg_cfg;
+
+	cmd->command = cpu_to_le16(HostCmd_CMD_CHAN_REGION_CFG);
+	cmd->size = cpu_to_le16(sizeof(*reg) + S_DS_GEN);
+
+	if (cmd_action == HostCmd_ACT_GEN_GET)
+		reg->action = cpu_to_le16(cmd_action);
+
+	return 0;
+}
+
 static int
 mwifiex_cmd_coalesce_cfg(struct mwifiex_private *priv,
 			 struct host_cmd_ds_command *cmd,
@@ -2134,6 +2149,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
 		ret = mwifiex_cmd_gtk_rekey_offload(priv, cmd_ptr, cmd_action,
 						    data_buf);
 		break;
+	case HostCmd_CMD_CHAN_REGION_CFG:
+		ret = mwifiex_cmd_chan_region_cfg(priv, cmd_ptr, cmd_action);
+		break;
 	default:
 		mwifiex_dbg(priv->adapter, ERROR,
 			    "PREP_CMD: unknown cmd- %#x\n", cmd_no);
@@ -2271,6 +2289,9 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
 			if (ret)
 				return -1;
 		}
+
+		mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REGION_CFG,
+				 HostCmd_ACT_GEN_GET, 0, NULL, true);
 	}
 
 	/* get tx rate */
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
index 90e191b..db85330 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
@@ -1022,6 +1022,44 @@ static int mwifiex_ret_robust_coex(struct mwifiex_private *priv,
 	return 0;
 }
 
+static int mwifiex_ret_chan_region_cfg(struct mwifiex_private *priv,
+				       struct host_cmd_ds_command *resp)
+{
+	struct host_cmd_ds_chan_region_cfg *reg = &resp->params.reg_cfg;
+	u16 action = le16_to_cpu(reg->action);
+	u16 tlv, tlv_buf_len, tlv_buf_left;
+	struct mwifiex_ie_types_header *head;
+	u8 *tlv_buf;
+
+	if (action != HostCmd_ACT_GEN_GET)
+		return 0;
+
+	tlv_buf = (u8 *)reg + sizeof(*reg);
+	tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*reg);
+
+	while (tlv_buf_left >= sizeof(*head)) {
+		head = (struct mwifiex_ie_types_header *)tlv_buf;
+		tlv = le16_to_cpu(head->type);
+		tlv_buf_len = le16_to_cpu(head->len);
+
+		if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
+			break;
+
+		switch (tlv) {
+		case TLV_TYPE_CHAN_ATTR_CFG:
+			mwifiex_dbg_dump(priv->adapter, CMD_D, "CHAN:",
+					 (u8 *)head + sizeof(*head),
+					 tlv_buf_len);
+			break;
+		}
+
+		tlv_buf += (sizeof(*head) + tlv_buf_len);
+		tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
+	}
+
+	return 0;
+}
+
 /*
  * This function handles the command responses.
  *
@@ -1239,6 +1277,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
 		break;
 	case HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG:
 		break;
+	case HostCmd_CMD_CHAN_REGION_CFG:
+		ret = mwifiex_ret_chan_region_cfg(priv, resp);
+		break;
 	default:
 		mwifiex_dbg(adapter, ERROR,
 			    "CMD_RESP: unknown cmd response %#x\n",
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] mwifiex: add custom regulatory domain support
  2016-08-09 14:50 [PATCH 1/3] mwifiex: correct aid value during tdls setup Amitkumar Karwar
  2016-08-09 14:50 ` [PATCH 2/3] mwifiex: add CHAN_REGION_CFG command Amitkumar Karwar
@ 2016-08-09 14:50 ` Amitkumar Karwar
  2016-09-09 15:47   ` Bob Copeland
  2016-09-03 10:06 ` [1/3] mwifiex: correct aid value during tdls setup Kalle Valo
  2 siblings, 1 reply; 5+ messages in thread
From: Amitkumar Karwar @ 2016-08-09 14:50 UTC (permalink / raw)
  To: linux-wireless; +Cc: Cathy Luo, Nishant Sarmukadam, Amitkumar Karwar

This patch creates custom regulatory rules based on the information
received from firmware and enable them during wiphy registration.

Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
---
 drivers/net/wireless/marvell/mwifiex/cfg80211.c    | 39 ++++++----
 drivers/net/wireless/marvell/mwifiex/fw.h          |  8 ++
 drivers/net/wireless/marvell/mwifiex/main.c        |  2 +
 drivers/net/wireless/marvell/mwifiex/main.h        |  1 +
 drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c | 91 ++++++++++++++++++++++
 5 files changed, 127 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 86b31b1..a91d442 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -4224,9 +4224,12 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
 	wiphy->cipher_suites = mwifiex_cipher_suites;
 	wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
 
-	if (adapter->region_code)
-		wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS |
+	if (adapter->regd) {
+		wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
+					   REGULATORY_DISABLE_BEACON_HINTS |
 					   REGULATORY_COUNTRY_IE_IGNORE;
+		wiphy_apply_custom_regulatory(wiphy, adapter->regd);
+	}
 
 	ether_addr_copy(wiphy->perm_addr, adapter->perm_addr);
 	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
@@ -4292,19 +4295,27 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
 		return ret;
 	}
 
-	if (reg_alpha2 && mwifiex_is_valid_alpha2(reg_alpha2)) {
-		mwifiex_dbg(adapter, INFO,
-			    "driver hint alpha2: %2.2s\n", reg_alpha2);
-		regulatory_hint(wiphy, reg_alpha2);
-	} else {
-		if (adapter->region_code == 0x00) {
-			mwifiex_dbg(adapter, WARN, "Ignore world regulatory domain\n");
+	if (!adapter->regd) {
+		if (reg_alpha2 && mwifiex_is_valid_alpha2(reg_alpha2)) {
+			mwifiex_dbg(adapter, INFO,
+				    "driver hint alpha2: %2.2s\n", reg_alpha2);
+			regulatory_hint(wiphy, reg_alpha2);
 		} else {
-			country_code =
-				mwifiex_11d_code_2_region(adapter->region_code);
-			if (country_code &&
-			    regulatory_hint(wiphy, country_code))
-				mwifiex_dbg(priv->adapter, ERROR, "regulatory_hint() failed\n");
+			if (adapter->region_code == 0x00) {
+				mwifiex_dbg(adapter, WARN,
+					    "Ignore world regulatory domain\n");
+			} else {
+				wiphy->regulatory_flags |=
+					REGULATORY_DISABLE_BEACON_HINTS |
+					REGULATORY_COUNTRY_IE_IGNORE;
+				country_code =
+					mwifiex_11d_code_2_region(
+						adapter->region_code);
+				if (country_code &&
+				    regulatory_hint(wiphy, country_code))
+					mwifiex_dbg(priv->adapter, ERROR,
+						    "regulatory_hint() failed\n");
+			}
 		}
 	}
 
diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
index 085db99..18aa525 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -416,6 +416,14 @@ enum P2P_MODES {
 	P2P_MODE_CLIENT = 3,
 };
 
+enum mwifiex_channel_flags {
+	MWIFIEX_CHANNEL_PASSIVE = BIT(0),
+	MWIFIEX_CHANNEL_DFS = BIT(1),
+	MWIFIEX_CHANNEL_NOHT40 = BIT(2),
+	MWIFIEX_CHANNEL_NOHT80 = BIT(3),
+	MWIFIEX_CHANNEL_DISABLED = BIT(7),
+};
+
 #define HostCmd_RET_BIT                       0x8000
 #define HostCmd_ACT_GEN_GET                   0x0000
 #define HostCmd_ACT_GEN_SET                   0x0001
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 0181247..7f2fb81 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -143,6 +143,8 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter)
 		adapter->nd_info = NULL;
 	}
 
+	kfree(adapter->regd);
+
 	vfree(adapter->chan_stats);
 	kfree(adapter);
 	return 0;
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 2d32768..26df28f 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -1009,6 +1009,7 @@ struct mwifiex_adapter {
 	bool usb_mc_status;
 	bool usb_mc_setup;
 	struct cfg80211_wowlan_nd_info *nd_info;
+	struct ieee80211_regdomain *regd;
 };
 
 void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
index db85330..3344a26 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
@@ -1022,6 +1022,93 @@ static int mwifiex_ret_robust_coex(struct mwifiex_private *priv,
 	return 0;
 }
 
+static struct ieee80211_regdomain *
+mwifiex_create_custom_regdomain(struct mwifiex_private *priv,
+				u8 *buf, u16 buf_len)
+{
+	u16 num_chan = buf_len / 2;
+	struct ieee80211_regdomain *regd;
+	struct ieee80211_reg_rule *rule;
+	bool new_rule;
+	int regd_size, idx, freq, prev_freq = 0;
+	u32 bw, prev_bw = 0;
+	u8 chflags, prev_chflags = 0, valid_rules = 0;
+
+	if (WARN_ON_ONCE(num_chan > NL80211_MAX_SUPP_REG_RULES))
+		return ERR_PTR(-EINVAL);
+
+	regd_size = sizeof(struct ieee80211_regdomain) +
+		    num_chan * sizeof(struct ieee80211_reg_rule);
+
+	regd = kzalloc(regd_size, GFP_KERNEL);
+	if (!regd)
+		return ERR_PTR(-ENOMEM);
+
+	for (idx = 0; idx < num_chan; idx++) {
+		u8 chan;
+		enum nl80211_band band;
+
+		chan = *buf++;
+		if (!chan)
+			return NULL;
+		chflags = *buf++;
+		band = (chan <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
+		freq = ieee80211_channel_to_frequency(chan, band);
+		new_rule = false;
+
+		if (chflags & MWIFIEX_CHANNEL_DISABLED)
+			continue;
+
+		if (band == NL80211_BAND_5GHZ) {
+			if (!(chflags & MWIFIEX_CHANNEL_NOHT80))
+				bw = MHZ_TO_KHZ(80);
+			else if (!(chflags & MWIFIEX_CHANNEL_NOHT40))
+				bw = MHZ_TO_KHZ(40);
+			else
+				bw = MHZ_TO_KHZ(20);
+		} else {
+			if (!(chflags & MWIFIEX_CHANNEL_NOHT40))
+				bw = MHZ_TO_KHZ(40);
+			else
+				bw = MHZ_TO_KHZ(20);
+		}
+
+		if (idx == 0 || prev_chflags != chflags || prev_bw != bw ||
+		    freq - prev_freq > 20) {
+			valid_rules++;
+			new_rule = true;
+		}
+
+		rule = &regd->reg_rules[valid_rules - 1];
+
+		rule->freq_range.end_freq_khz = MHZ_TO_KHZ(freq + 10);
+
+		prev_chflags = chflags;
+		prev_freq = freq;
+		prev_bw = bw;
+
+		if (!new_rule)
+			continue;
+
+		rule->freq_range.start_freq_khz = MHZ_TO_KHZ(freq - 10);
+		rule->power_rule.max_eirp = DBM_TO_MBM(19);
+
+		if (chflags & MWIFIEX_CHANNEL_PASSIVE)
+			rule->flags = NL80211_RRF_NO_IR;
+
+		if (chflags & MWIFIEX_CHANNEL_DFS)
+			rule->flags = NL80211_RRF_DFS;
+
+		rule->freq_range.max_bandwidth_khz = bw;
+	}
+
+	regd->n_reg_rules = valid_rules;
+	regd->alpha2[0] = '9';
+	regd->alpha2[1] = '9';
+
+	return regd;
+}
+
 static int mwifiex_ret_chan_region_cfg(struct mwifiex_private *priv,
 				       struct host_cmd_ds_command *resp)
 {
@@ -1050,6 +1137,10 @@ static int mwifiex_ret_chan_region_cfg(struct mwifiex_private *priv,
 			mwifiex_dbg_dump(priv->adapter, CMD_D, "CHAN:",
 					 (u8 *)head + sizeof(*head),
 					 tlv_buf_len);
+			priv->adapter->regd =
+				mwifiex_create_custom_regdomain(priv,
+								(u8 *)head +
+						sizeof(*head), tlv_buf_len);
 			break;
 		}
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [1/3] mwifiex: correct aid value during tdls setup
  2016-08-09 14:50 [PATCH 1/3] mwifiex: correct aid value during tdls setup Amitkumar Karwar
  2016-08-09 14:50 ` [PATCH 2/3] mwifiex: add CHAN_REGION_CFG command Amitkumar Karwar
  2016-08-09 14:50 ` [PATCH 3/3] mwifiex: add custom regulatory domain support Amitkumar Karwar
@ 2016-09-03 10:06 ` Kalle Valo
  2 siblings, 0 replies; 5+ messages in thread
From: Kalle Valo @ 2016-09-03 10:06 UTC (permalink / raw)
  To: Amitkumar Karwar
  Cc: linux-wireless, Cathy Luo, Nishant Sarmukadam, Xinming Hu,
	Amitkumar Karwar

Amitkumar Karwar <akarwar@marvell.com> wrote:
> From: Xinming Hu <huxm@marvell.com>
> 
> AID gets updated during TDLS setup, but modified value isn't reflected
> in "priv->assoc_rsp_buf". This causes TDLS setup failure. The problem is
> fixed here.
> 
> Fixes: 4aff53ef18e4a4 ("mwifiex: parsing aid while receiving..")
> Signed-off-by: Xinming Hu <huxm@marvell.com>
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>

Thanks, 3 patches applied to wireless-drivers-next.git:

b64db1b252e9 mwifiex: correct aid value during tdls setup
41960b4dfdfc mwifiex: add CHAN_REGION_CFG command
72539799104d mwifiex: add custom regulatory domain support

-- 
Sent by pwcli
https://patchwork.kernel.org/patch/9271429/

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 3/3] mwifiex: add custom regulatory domain support
  2016-08-09 14:50 ` [PATCH 3/3] mwifiex: add custom regulatory domain support Amitkumar Karwar
@ 2016-09-09 15:47   ` Bob Copeland
  0 siblings, 0 replies; 5+ messages in thread
From: Bob Copeland @ 2016-09-09 15:47 UTC (permalink / raw)
  To: Amitkumar Karwar; +Cc: linux-wireless, Cathy Luo, Nishant Sarmukadam

On Tue, Aug 09, 2016 at 08:20:46PM +0530, Amitkumar Karwar wrote:
> This patch creates custom regulatory rules based on the information
> received from firmware and enable them during wiphy registration.
> 
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>

Hi,

This patch recently landed in wireless-testing but I noticed (or well,
smatch noticed) some issues with the error paths:

> +	if (adapter->regd) {

does null-check here and elsewhere...

> +static struct ieee80211_regdomain *
> +mwifiex_create_custom_regdomain(struct mwifiex_private *priv,
> +				u8 *buf, u16 buf_len)
> +{
> +	u16 num_chan = buf_len / 2;
> +	struct ieee80211_regdomain *regd;
> +	struct ieee80211_reg_rule *rule;
> +	bool new_rule;
> +	int regd_size, idx, freq, prev_freq = 0;
> +	u32 bw, prev_bw = 0;
> +	u8 chflags, prev_chflags = 0, valid_rules = 0;
> +
> +	if (WARN_ON_ONCE(num_chan > NL80211_MAX_SUPP_REG_RULES))
> +		return ERR_PTR(-EINVAL);
> +

...returns ERR_PTR here

> +	regd_size = sizeof(struct ieee80211_regdomain) +
> +		    num_chan * sizeof(struct ieee80211_reg_rule);
> +
> +	regd = kzalloc(regd_size, GFP_KERNEL);
> +	if (!regd)
> +		return ERR_PTR(-ENOMEM);

and here.

> +
> +	for (idx = 0; idx < num_chan; idx++) {
> +		u8 chan;
> +		enum nl80211_band band;
> +
> +		chan = *buf++;
> +		if (!chan)
> +			return NULL;

^ here, returns null, leaking regd

> +		chflags = *buf++;
> +		band = (chan <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
> +		freq = ieee80211_channel_to_frequency(chan, band);
> +		new_rule = false;
> +
> +		if (chflags & MWIFIEX_CHANNEL_DISABLED)
> +			continue;
> +
> +		if (band == NL80211_BAND_5GHZ) {
> +			if (!(chflags & MWIFIEX_CHANNEL_NOHT80))
> +				bw = MHZ_TO_KHZ(80);
> +			else if (!(chflags & MWIFIEX_CHANNEL_NOHT40))
> +				bw = MHZ_TO_KHZ(40);
> +			else
> +				bw = MHZ_TO_KHZ(20);
> +		} else {
> +			if (!(chflags & MWIFIEX_CHANNEL_NOHT40))
> +				bw = MHZ_TO_KHZ(40);
> +			else
> +				bw = MHZ_TO_KHZ(20);
> +		}
> +
> +		if (idx == 0 || prev_chflags != chflags || prev_bw != bw ||
> +		    freq - prev_freq > 20) {
> +			valid_rules++;
> +			new_rule = true;
> +		}
> +
> +		rule = &regd->reg_rules[valid_rules - 1];
> +
> +		rule->freq_range.end_freq_khz = MHZ_TO_KHZ(freq + 10);
> +
> +		prev_chflags = chflags;
> +		prev_freq = freq;
> +		prev_bw = bw;
> +
> +		if (!new_rule)
> +			continue;
> +
> +		rule->freq_range.start_freq_khz = MHZ_TO_KHZ(freq - 10);
> +		rule->power_rule.max_eirp = DBM_TO_MBM(19);
> +
> +		if (chflags & MWIFIEX_CHANNEL_PASSIVE)
> +			rule->flags = NL80211_RRF_NO_IR;
> +
> +		if (chflags & MWIFIEX_CHANNEL_DFS)
> +			rule->flags = NL80211_RRF_DFS;
> +
> +		rule->freq_range.max_bandwidth_khz = bw;
> +	}
> +
> +	regd->n_reg_rules = valid_rules;
> +	regd->alpha2[0] = '9';
> +	regd->alpha2[1] = '9';
> +
> +	return regd;
> +}

[...]

>  static int mwifiex_ret_chan_region_cfg(struct mwifiex_private *priv,
>  				       struct host_cmd_ds_command *resp)
>  {
> @@ -1050,6 +1137,10 @@ static int mwifiex_ret_chan_region_cfg(struct mwifiex_private *priv,
>  			mwifiex_dbg_dump(priv->adapter, CMD_D, "CHAN:",
>  					 (u8 *)head + sizeof(*head),
>  					 tlv_buf_len);
> +			priv->adapter->regd =
> +				mwifiex_create_custom_regdomain(priv,
> +								(u8 *)head +
> +						sizeof(*head), tlv_buf_len);

Here regd is assigned without checking IS_ERR.

-- 
Bob Copeland %% http://bobcopeland.com/

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-09-09 15:49 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-09 14:50 [PATCH 1/3] mwifiex: correct aid value during tdls setup Amitkumar Karwar
2016-08-09 14:50 ` [PATCH 2/3] mwifiex: add CHAN_REGION_CFG command Amitkumar Karwar
2016-08-09 14:50 ` [PATCH 3/3] mwifiex: add custom regulatory domain support Amitkumar Karwar
2016-09-09 15:47   ` Bob Copeland
2016-09-03 10:06 ` [1/3] mwifiex: correct aid value during tdls setup Kalle Valo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).