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

From: Ben Hutchings
Date: Tue Nov 27 2012 - 11:02:32 EST


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@xxxxxxxxx>
>
> 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@xxxxxxxxx>
> Signed-off-by: Johannes Berg <johannes.berg@xxxxxxxxx>
> [ 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@xxxxxxxxxxxxx>

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 = {

--
Ben Hutchings
Never attribute to conspiracy what can adequately be explained by stupidity.

Attachment: signature.asc
Description: This is a digitally signed message part