diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-6000.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 45 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 13 |
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 | } |
1328 | EXPORT_SYMBOL(iwl_rx_csa); | 1333 | EXPORT_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 | */ | ||
1003 | struct iwl_switch_rxon { | ||
1004 | bool switch_in_progress; | ||
1005 | __le16 channel; | ||
1006 | }; | ||
1007 | |||
997 | struct iwl_priv { | 1008 | struct 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; |