aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c45
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h13
6 files changed, 68 insertions, 25 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index faa4c4e2d43c..1d22ea390c00 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -1449,14 +1449,14 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
1449 is_ht40 = is_ht40_channel(priv->staging_rxon.flags); 1449 is_ht40 = is_ht40_channel(priv->staging_rxon.flags);
1450 1450
1451 if (is_ht40 && 1451 if (is_ht40 &&
1452 (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) 1452 (priv->staging_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
1453 ctrl_chan_high = 1; 1453 ctrl_chan_high = 1;
1454 1454
1455 cmd.band = band; 1455 cmd.band = band;
1456 cmd.expect_beacon = 0; 1456 cmd.expect_beacon = 0;
1457 cmd.channel = cpu_to_le16(channel); 1457 cmd.channel = cpu_to_le16(channel);
1458 cmd.rxon_flags = priv->active_rxon.flags; 1458 cmd.rxon_flags = priv->staging_rxon.flags;
1459 cmd.rxon_filter_flags = priv->active_rxon.filter_flags; 1459 cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
1460 cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); 1460 cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
1461 if (ch_info) 1461 if (ch_info)
1462 cmd.expect_beacon = is_channel_radar(ch_info); 1462 cmd.expect_beacon = is_channel_radar(ch_info);
@@ -1473,8 +1473,10 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
1473 return rc; 1473 return rc;
1474 } 1474 }
1475 1475
1476 rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); 1476 priv->switch_rxon.channel = cpu_to_le16(channel);
1477 return rc; 1477 priv->switch_rxon.switch_in_progress = true;
1478
1479 return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
1478} 1480}
1479 1481
1480/** 1482/**
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 6ea5e2dc273c..6eaf26b07636 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -1391,8 +1391,8 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
1391 priv->active_rxon.channel, channel); 1391 priv->active_rxon.channel, channel);
1392 cmd.band = priv->band == IEEE80211_BAND_2GHZ; 1392 cmd.band = priv->band == IEEE80211_BAND_2GHZ;
1393 cmd.channel = cpu_to_le16(channel); 1393 cmd.channel = cpu_to_le16(channel);
1394 cmd.rxon_flags = priv->active_rxon.flags; 1394 cmd.rxon_flags = priv->staging_rxon.flags;
1395 cmd.rxon_filter_flags = priv->active_rxon.filter_flags; 1395 cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
1396 cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); 1396 cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
1397 ch_info = iwl_get_channel_info(priv, priv->band, channel); 1397 ch_info = iwl_get_channel_info(priv, priv->band, channel);
1398 if (ch_info) 1398 if (ch_info)
@@ -1402,6 +1402,8 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
1402 priv->active_rxon.channel, channel); 1402 priv->active_rxon.channel, channel);
1403 return -EFAULT; 1403 return -EFAULT;
1404 } 1404 }
1405 priv->switch_rxon.channel = cpu_to_le16(channel);
1406 priv->switch_rxon.switch_in_progress = true;
1405 1407
1406 return iwl_send_cmd_sync(priv, &hcmd); 1408 return iwl_send_cmd_sync(priv, &hcmd);
1407} 1409}
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 9ab79546b8a4..1f769ea23636 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -186,8 +186,8 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
186 186
187 cmd.band = priv->band == IEEE80211_BAND_2GHZ; 187 cmd.band = priv->band == IEEE80211_BAND_2GHZ;
188 cmd.channel = cpu_to_le16(channel); 188 cmd.channel = cpu_to_le16(channel);
189 cmd.rxon_flags = priv->active_rxon.flags; 189 cmd.rxon_flags = priv->staging_rxon.flags;
190 cmd.rxon_filter_flags = priv->active_rxon.filter_flags; 190 cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
191 cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); 191 cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
192 ch_info = iwl_get_channel_info(priv, priv->band, channel); 192 ch_info = iwl_get_channel_info(priv, priv->band, channel);
193 if (ch_info) 193 if (ch_info)
@@ -197,6 +197,8 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
197 priv->active_rxon.channel, channel); 197 priv->active_rxon.channel, channel);
198 return -EFAULT; 198 return -EFAULT;
199 } 199 }
200 priv->switch_rxon.channel = cpu_to_le16(channel);
201 priv->switch_rxon.switch_in_progress = true;
200 202
201 return iwl_send_cmd_sync(priv, &hcmd); 203 return iwl_send_cmd_sync(priv, &hcmd);
202} 204}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 1710815691d5..7bdedf61dd36 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -122,6 +122,17 @@ int iwl_commit_rxon(struct iwl_priv *priv)
122 return -EINVAL; 122 return -EINVAL;
123 } 123 }
124 124
125 /*
126 * receive commit_rxon request
127 * abort any previous channel switch if still in process
128 */
129 if (priv->switch_rxon.switch_in_progress &&
130 (priv->switch_rxon.channel != priv->staging_rxon.channel)) {
131 IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
132 le16_to_cpu(priv->switch_rxon.channel));
133 priv->switch_rxon.switch_in_progress = false;
134 }
135
125 /* If we don't need to send a full RXON, we can use 136 /* If we don't need to send a full RXON, we can use
126 * iwl_rxon_assoc_cmd which is used to reconfigure filter 137 * iwl_rxon_assoc_cmd which is used to reconfigure filter
127 * and other flags for the current radio configuration. */ 138 * and other flags for the current radio configuration. */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index f88a1cb7a12b..e0edc607e33f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1316,14 +1316,19 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
1316 struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon; 1316 struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
1317 struct iwl_csa_notification *csa = &(pkt->u.csa_notif); 1317 struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
1318 1318
1319 if (!le32_to_cpu(csa->status)) { 1319 if (priv->switch_rxon.switch_in_progress) {
1320 rxon->channel = csa->channel; 1320 if (!le32_to_cpu(csa->status) &&
1321 priv->staging_rxon.channel = csa->channel; 1321 (csa->channel == priv->switch_rxon.channel)) {
1322 IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", 1322 rxon->channel = csa->channel;
1323 le16_to_cpu(csa->channel)); 1323 priv->staging_rxon.channel = csa->channel;
1324 } else 1324 IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
1325 IWL_ERR(priv, "CSA notif (fail) : channel %d\n", 1325 le16_to_cpu(csa->channel));
1326 le16_to_cpu(csa->channel)); 1326 } else
1327 IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
1328 le16_to_cpu(csa->channel));
1329
1330 priv->switch_rxon.switch_in_progress = false;
1331 }
1327} 1332}
1328EXPORT_SYMBOL(iwl_rx_csa); 1333EXPORT_SYMBOL(iwl_rx_csa);
1329 1334
@@ -2690,14 +2695,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
2690 goto set_ch_out; 2695 goto set_ch_out;
2691 } 2696 }
2692 2697
2693 if (iwl_is_associated(priv) &&
2694 (le16_to_cpu(priv->active_rxon.channel) != ch) &&
2695 priv->cfg->ops->lib->set_channel_switch) {
2696 ret = priv->cfg->ops->lib->set_channel_switch(priv,
2697 ch);
2698 goto out;
2699 }
2700
2701 spin_lock_irqsave(&priv->lock, flags); 2698 spin_lock_irqsave(&priv->lock, flags);
2702 2699
2703 /* Configure HT40 channels */ 2700 /* Configure HT40 channels */
@@ -2732,6 +2729,22 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
2732 2729
2733 iwl_set_flags_for_band(priv, conf->channel->band); 2730 iwl_set_flags_for_band(priv, conf->channel->band);
2734 spin_unlock_irqrestore(&priv->lock, flags); 2731 spin_unlock_irqrestore(&priv->lock, flags);
2732 if (iwl_is_associated(priv) &&
2733 (le16_to_cpu(priv->active_rxon.channel) != ch) &&
2734 priv->cfg->ops->lib->set_channel_switch) {
2735 iwl_set_rate(priv);
2736 /*
2737 * at this point, staging_rxon has the
2738 * configuration for channel switch
2739 */
2740 ret = priv->cfg->ops->lib->set_channel_switch(priv,
2741 ch);
2742 if (!ret) {
2743 iwl_print_rx_config_cmd(priv);
2744 goto out;
2745 }
2746 priv->switch_rxon.switch_in_progress = false;
2747 }
2735 set_ch_out: 2748 set_ch_out:
2736 /* The list of supported rates and rate mask can be different 2749 /* The list of supported rates and rate mask can be different
2737 * for each band; since the band may have changed, reset 2750 * for each band; since the band may have changed, reset
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 997564584c71..9a19a3d1f704 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -994,6 +994,17 @@ struct traffic_stats {
994}; 994};
995#endif 995#endif
996 996
997/*
998 * iwl_switch_rxon: "channel switch" structure
999 *
1000 * @ switch_in_progress: channel switch in progress
1001 * @ channel: new channel
1002 */
1003struct iwl_switch_rxon {
1004 bool switch_in_progress;
1005 __le16 channel;
1006};
1007
997struct iwl_priv { 1008struct iwl_priv {
998 1009
999 /* ieee device used by generic ieee processing code */ 1010 /* ieee device used by generic ieee processing code */
@@ -1087,6 +1098,8 @@ struct iwl_priv {
1087 const struct iwl_rxon_cmd active_rxon; 1098 const struct iwl_rxon_cmd active_rxon;
1088 struct iwl_rxon_cmd staging_rxon; 1099 struct iwl_rxon_cmd staging_rxon;
1089 1100
1101 struct iwl_switch_rxon switch_rxon;
1102
1090 /* 1st responses from initialize and runtime uCode images. 1103 /* 1st responses from initialize and runtime uCode images.
1091 * 4965's initialize alive response contains some calibration data. */ 1104 * 4965's initialize alive response contains some calibration data. */
1092 struct iwl_init_alive_resp card_alive_init; 1105 struct iwl_init_alive_resp card_alive_init;