Commit 735dbc9e authored by Johannes Berg's avatar Johannes Berg Committed by Ben Hutchings

iwlwifi: fix 6000 series channel switch command

commit 8f7b8db6 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: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
[bwh: Backported to 3.2: adjust filename, context]
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent de5bfe1d
......@@ -193,7 +193,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;
......@@ -203,18 +203,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;
/*
......@@ -230,30 +237,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,
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_trans_send_cmd(trans(priv), &hcmd);
err = iwl_trans_send_cmd(trans(priv), &hcmd);
kfree(cmd);
return err;
}
static struct iwl_lib_ops iwl6000_lib = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment