iwlwifi: fix 6000 series channel switch command
commit 8f7b8db6e0 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>
[bwh: Backported to 3.2: adjust filename, context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
This commit is contained in:
committed by
Ben Hutchings
parent
de5bfe1d95
commit
735dbc9e51
@ -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,
|
||||
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_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 = {
|
||||
|
||||
Reference in New Issue
Block a user