Patchwork [188/270] iwlwifi: fix 6000 series channel switch command

login
register
mail settings
Submitter Herton Ronaldo Krzesinski
Date Nov. 26, 2012, 4:57 p.m.
Message ID <1353949160-26803-189-git-send-email-herton.krzesinski@canonical.com>
Download mbox | patch
Permalink /patch/201920/
State New
Headers show

Comments

Herton Ronaldo Krzesinski - Nov. 26, 2012, 4:57 p.m.
3.5.7u1 -stable review patch.  If anyone has any objections, please let me know.

------------------

From: Johannes Berg <johannes.berg@intel.com>

commit 8f7b8db6e0557c8437adf9371e020cd89a7e85dc upstream.

The channel switch command for 6000 series devices
is larger than the maximum inline command size of
320 bytes. The command is therefore refused with a
warning. Fix this by allocating the command and
using the NOCOPY mechanism.

Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
[ herton: file name is different on 3.5, code differs a little bit at
  the end, adjusted context ]
Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn-devices.c |   39 +++++++++++++++---------
 1 file changed, 24 insertions(+), 15 deletions(-)
Ben Hutchings - Nov. 27, 2012, 4:02 p.m.
On Mon, 2012-11-26 at 14:57 -0200, Herton Ronaldo Krzesinski wrote:
> 3.5.7u1 -stable review patch.  If anyone has any objections, please let me know.
> 
> ------------------
> 
> From: Johannes Berg <johannes.berg@intel.com>
> 
> commit 8f7b8db6e0557c8437adf9371e020cd89a7e85dc upstream.
> 
> The channel switch command for 6000 series devices
> is larger than the maximum inline command size of
> 320 bytes. The command is therefore refused with a
> warning. Fix this by allocating the command and
> using the NOCOPY mechanism.
> 
> Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> [ herton: file name is different on 3.5, code differs a little bit at
>   the end, adjusted context ]
> Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>

Also missing from 3.4; the filename is different again
(drivers/net/wireless/iwlwifi/iwl-6000.c) but this should otherwise be
applicable with one line of fuzz at the end.

Ben.

> ---
>  drivers/net/wireless/iwlwifi/iwl-agn-devices.c |   39 +++++++++++++++---------
>  1 file changed, 24 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-devices.c b/drivers/net/wireless/iwlwifi/iwl-agn-devices.c
> index 48533b3..8ab0a7c 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-agn-devices.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-agn-devices.c
> @@ -653,7 +653,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
>  	 * See iwlagn_mac_channel_switch.
>  	 */
>  	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
> -	struct iwl6000_channel_switch_cmd cmd;
> +	struct iwl6000_channel_switch_cmd *cmd;
>  	const struct iwl_channel_info *ch_info;
>  	u32 switch_time_in_usec, ucode_switch_time;
>  	u16 ch;
> @@ -663,18 +663,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
>  	struct ieee80211_vif *vif = ctx->vif;
>  	struct iwl_host_cmd hcmd = {
>  		.id = REPLY_CHANNEL_SWITCH,
> -		.len = { sizeof(cmd), },
> +		.len = { sizeof(*cmd), },
>  		.flags = CMD_SYNC,
> -		.data = { &cmd, },
> +		.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
>  	};
> +	int err;
>  
> -	cmd.band = priv->band == IEEE80211_BAND_2GHZ;
> +	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
> +	if (!cmd)
> +		return -ENOMEM;
> +
> +	hcmd.data[0] = cmd;
> +
> +	cmd->band = priv->band == IEEE80211_BAND_2GHZ;
>  	ch = ch_switch->channel->hw_value;
>  	IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
>  		      ctx->active.channel, ch);
> -	cmd.channel = cpu_to_le16(ch);
> -	cmd.rxon_flags = ctx->staging.flags;
> -	cmd.rxon_filter_flags = ctx->staging.filter_flags;
> +	cmd->channel = cpu_to_le16(ch);
> +	cmd->rxon_flags = ctx->staging.flags;
> +	cmd->rxon_filter_flags = ctx->staging.filter_flags;
>  	switch_count = ch_switch->count;
>  	tsf_low = ch_switch->timestamp & 0x0ffffffff;
>  	/*
> @@ -690,30 +697,32 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
>  			switch_count = 0;
>  	}
>  	if (switch_count <= 1)
> -		cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
> +		cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time);
>  	else {
>  		switch_time_in_usec =
>  			vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
>  		ucode_switch_time = iwl_usecs_to_beacons(priv,
>  							 switch_time_in_usec,
>  							 beacon_interval);
> -		cmd.switch_time = iwl_add_beacon_time(priv,
> -						      priv->ucode_beacon_time,
> -						      ucode_switch_time,
> -						      beacon_interval);
> +		cmd->switch_time = iwl_add_beacon_time(priv,
> +						       priv->ucode_beacon_time,
> +						       ucode_switch_time,
> +						       beacon_interval);
>  	}
>  	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
> -		      cmd.switch_time);
> +		      cmd->switch_time);
>  	ch_info = iwl_get_channel_info(priv, priv->band, ch);
>  	if (ch_info)
> -		cmd.expect_beacon = is_channel_radar(ch_info);
> +		cmd->expect_beacon = is_channel_radar(ch_info);
>  	else {
>  		IWL_ERR(priv, "invalid channel switch from %u to %u\n",
>  			ctx->active.channel, ch);
>  		return -EFAULT;
>  	}
>  
> -	return iwl_dvm_send_cmd(priv, &hcmd);
> +	err = iwl_dvm_send_cmd(priv, &hcmd);
> +	kfree(cmd);
> +	return err;
>  }
>  
>  struct iwl_lib_ops iwl6000_lib = {
Greg KH - Nov. 30, 2012, 1:58 a.m.
On Tue, Nov 27, 2012 at 04:02:38PM +0000, Ben Hutchings wrote:
> On Mon, 2012-11-26 at 14:57 -0200, Herton Ronaldo Krzesinski wrote:
> > 3.5.7u1 -stable review patch.  If anyone has any objections, please let me know.
> > 
> > ------------------
> > 
> > From: Johannes Berg <johannes.berg@intel.com>
> > 
> > commit 8f7b8db6e0557c8437adf9371e020cd89a7e85dc upstream.
> > 
> > The channel switch command for 6000 series devices
> > is larger than the maximum inline command size of
> > 320 bytes. The command is therefore refused with a
> > warning. Fix this by allocating the command and
> > using the NOCOPY mechanism.
> > 
> > Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
> > Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> > [ herton: file name is different on 3.5, code differs a little bit at
> >   the end, adjusted context ]
> > Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
> 
> Also missing from 3.4; the filename is different again
> (drivers/net/wireless/iwlwifi/iwl-6000.c) but this should otherwise be
> applicable with one line of fuzz at the end.

Thanks, I forced it in by hand.

greg k-h

Patch

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-devices.c b/drivers/net/wireless/iwlwifi/iwl-agn-devices.c
index 48533b3..8ab0a7c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-devices.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-devices.c
@@ -653,7 +653,7 @@  static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
 	 * See iwlagn_mac_channel_switch.
 	 */
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	struct iwl6000_channel_switch_cmd cmd;
+	struct iwl6000_channel_switch_cmd *cmd;
 	const struct iwl_channel_info *ch_info;
 	u32 switch_time_in_usec, ucode_switch_time;
 	u16 ch;
@@ -663,18 +663,25 @@  static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
 	struct ieee80211_vif *vif = ctx->vif;
 	struct iwl_host_cmd hcmd = {
 		.id = REPLY_CHANNEL_SWITCH,
-		.len = { sizeof(cmd), },
+		.len = { sizeof(*cmd), },
 		.flags = CMD_SYNC,
-		.data = { &cmd, },
+		.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
 	};
+	int err;
 
-	cmd.band = priv->band == IEEE80211_BAND_2GHZ;
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd)
+		return -ENOMEM;
+
+	hcmd.data[0] = cmd;
+
+	cmd->band = priv->band == IEEE80211_BAND_2GHZ;
 	ch = ch_switch->channel->hw_value;
 	IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
 		      ctx->active.channel, ch);
-	cmd.channel = cpu_to_le16(ch);
-	cmd.rxon_flags = ctx->staging.flags;
-	cmd.rxon_filter_flags = ctx->staging.filter_flags;
+	cmd->channel = cpu_to_le16(ch);
+	cmd->rxon_flags = ctx->staging.flags;
+	cmd->rxon_filter_flags = ctx->staging.filter_flags;
 	switch_count = ch_switch->count;
 	tsf_low = ch_switch->timestamp & 0x0ffffffff;
 	/*
@@ -690,30 +697,32 @@  static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
 			switch_count = 0;
 	}
 	if (switch_count <= 1)
-		cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
+		cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time);
 	else {
 		switch_time_in_usec =
 			vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
 		ucode_switch_time = iwl_usecs_to_beacons(priv,
 							 switch_time_in_usec,
 							 beacon_interval);
-		cmd.switch_time = iwl_add_beacon_time(priv,
-						      priv->ucode_beacon_time,
-						      ucode_switch_time,
-						      beacon_interval);
+		cmd->switch_time = iwl_add_beacon_time(priv,
+						       priv->ucode_beacon_time,
+						       ucode_switch_time,
+						       beacon_interval);
 	}
 	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
-		      cmd.switch_time);
+		      cmd->switch_time);
 	ch_info = iwl_get_channel_info(priv, priv->band, ch);
 	if (ch_info)
-		cmd.expect_beacon = is_channel_radar(ch_info);
+		cmd->expect_beacon = is_channel_radar(ch_info);
 	else {
 		IWL_ERR(priv, "invalid channel switch from %u to %u\n",
 			ctx->active.channel, ch);
 		return -EFAULT;
 	}
 
-	return iwl_dvm_send_cmd(priv, &hcmd);
+	err = iwl_dvm_send_cmd(priv, &hcmd);
+	kfree(cmd);
+	return err;
 }
 
 struct iwl_lib_ops iwl6000_lib = {