aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-09-25 10:40:12 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-10-16 10:28:36 -0400
commit8f7b8db6e0557c8437adf9371e020cd89a7e85dc (patch)
treefaf84e66c6e6bd0864012a3e56b3dd19e5b4cca0 /drivers/net
parentbf11315eeda510ea4fc1a2bf972d8155d31d89b4 (diff)
iwlwifi: fix 6000 series channel switch command
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. Cc: stable@kernel.org Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/devices.c39
1 files changed, 24 insertions, 15 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c
index 349c205d5f6..da586206419 100644
--- a/drivers/net/wireless/iwlwifi/dvm/devices.c
+++ b/drivers/net/wireless/iwlwifi/dvm/devices.c
@@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
518 * See iwlagn_mac_channel_switch. 518 * See iwlagn_mac_channel_switch.
519 */ 519 */
520 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; 520 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
521 struct iwl6000_channel_switch_cmd cmd; 521 struct iwl6000_channel_switch_cmd *cmd;
522 u32 switch_time_in_usec, ucode_switch_time; 522 u32 switch_time_in_usec, ucode_switch_time;
523 u16 ch; 523 u16 ch;
524 u32 tsf_low; 524 u32 tsf_low;
@@ -527,18 +527,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
527 struct ieee80211_vif *vif = ctx->vif; 527 struct ieee80211_vif *vif = ctx->vif;
528 struct iwl_host_cmd hcmd = { 528 struct iwl_host_cmd hcmd = {
529 .id = REPLY_CHANNEL_SWITCH, 529 .id = REPLY_CHANNEL_SWITCH,
530 .len = { sizeof(cmd), }, 530 .len = { sizeof(*cmd), },
531 .flags = CMD_SYNC, 531 .flags = CMD_SYNC,
532 .data = { &cmd, }, 532 .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
533 }; 533 };
534 int err;
534 535
535 cmd.band = priv->band == IEEE80211_BAND_2GHZ; 536 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
537 if (!cmd)
538 return -ENOMEM;
539
540 hcmd.data[0] = cmd;
541
542 cmd->band = priv->band == IEEE80211_BAND_2GHZ;
536 ch = ch_switch->channel->hw_value; 543 ch = ch_switch->channel->hw_value;
537 IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", 544 IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
538 ctx->active.channel, ch); 545 ctx->active.channel, ch);
539 cmd.channel = cpu_to_le16(ch); 546 cmd->channel = cpu_to_le16(ch);
540 cmd.rxon_flags = ctx->staging.flags; 547 cmd->rxon_flags = ctx->staging.flags;
541 cmd.rxon_filter_flags = ctx->staging.filter_flags; 548 cmd->rxon_filter_flags = ctx->staging.filter_flags;
542 switch_count = ch_switch->count; 549 switch_count = ch_switch->count;
543 tsf_low = ch_switch->timestamp & 0x0ffffffff; 550 tsf_low = ch_switch->timestamp & 0x0ffffffff;
544 /* 551 /*
@@ -554,23 +561,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
554 switch_count = 0; 561 switch_count = 0;
555 } 562 }
556 if (switch_count <= 1) 563 if (switch_count <= 1)
557 cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); 564 cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time);
558 else { 565 else {
559 switch_time_in_usec = 566 switch_time_in_usec =
560 vif->bss_conf.beacon_int * switch_count * TIME_UNIT; 567 vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
561 ucode_switch_time = iwl_usecs_to_beacons(priv, 568 ucode_switch_time = iwl_usecs_to_beacons(priv,
562 switch_time_in_usec, 569 switch_time_in_usec,
563 beacon_interval); 570 beacon_interval);
564 cmd.switch_time = iwl_add_beacon_time(priv, 571 cmd->switch_time = iwl_add_beacon_time(priv,
565 priv->ucode_beacon_time, 572 priv->ucode_beacon_time,
566 ucode_switch_time, 573 ucode_switch_time,
567 beacon_interval); 574 beacon_interval);
568 } 575 }
569 IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", 576 IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
570 cmd.switch_time); 577 cmd->switch_time);
571 cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; 578 cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
572 579
573 return iwl_dvm_send_cmd(priv, &hcmd); 580 err = iwl_dvm_send_cmd(priv, &hcmd);
581 kfree(cmd);
582 return err;
574} 583}
575 584
576struct iwl_lib_ops iwl6000_lib = { 585struct iwl_lib_ops iwl6000_lib = {