diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 179 |
1 files changed, 92 insertions, 87 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 0db3bc011ac2..663dc83be501 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -1567,9 +1567,8 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
1567 | if (iwl_is_associated(priv)) { | 1567 | if (iwl_is_associated(priv)) { |
1568 | struct iwl_rxon_cmd *active_rxon = | 1568 | struct iwl_rxon_cmd *active_rxon = |
1569 | (struct iwl_rxon_cmd *)&priv->active_rxon; | 1569 | (struct iwl_rxon_cmd *)&priv->active_rxon; |
1570 | 1570 | /* apply any changes in staging */ | |
1571 | memcpy(&priv->staging_rxon, &priv->active_rxon, | 1571 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
1572 | sizeof(priv->staging_rxon)); | ||
1573 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 1572 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
1574 | } else { | 1573 | } else { |
1575 | /* Initialize our rx_config data */ | 1574 | /* Initialize our rx_config data */ |
@@ -2184,110 +2183,112 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2184 | struct iwl_priv *priv = hw->priv; | 2183 | struct iwl_priv *priv = hw->priv; |
2185 | const struct iwl_channel_info *ch_info; | 2184 | const struct iwl_channel_info *ch_info; |
2186 | struct ieee80211_conf *conf = &hw->conf; | 2185 | struct ieee80211_conf *conf = &hw->conf; |
2187 | unsigned long flags; | 2186 | unsigned long flags = 0; |
2188 | int ret = 0; | 2187 | int ret = 0; |
2189 | u16 channel; | 2188 | u16 ch; |
2189 | int scan_active = 0; | ||
2190 | 2190 | ||
2191 | mutex_lock(&priv->mutex); | 2191 | mutex_lock(&priv->mutex); |
2192 | IWL_DEBUG_MAC80211(priv, "enter to channel %d\n", conf->channel->hw_value); | 2192 | IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", |
2193 | conf->channel->hw_value, changed); | ||
2193 | 2194 | ||
2194 | priv->current_ht_config.is_ht = conf_is_ht(conf); | 2195 | if (unlikely(!priv->cfg->mod_params->disable_hw_scan && |
2195 | 2196 | test_bit(STATUS_SCANNING, &priv->status))) { | |
2196 | if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) { | 2197 | scan_active = 1; |
2197 | IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - waiting for uCode\n"); | 2198 | IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); |
2198 | goto out; | ||
2199 | } | 2199 | } |
2200 | 2200 | ||
2201 | if (!conf->radio_enabled) | ||
2202 | iwl_radio_kill_sw_disable_radio(priv); | ||
2203 | 2201 | ||
2204 | if (!iwl_is_ready(priv)) { | 2202 | /* during scanning mac80211 will delay channel setting until |
2205 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); | 2203 | * scan finish with changed = 0 |
2206 | ret = -EIO; | 2204 | */ |
2207 | goto out; | 2205 | if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) { |
2208 | } | 2206 | if (scan_active) |
2207 | goto set_ch_out; | ||
2208 | |||
2209 | ch = ieee80211_frequency_to_channel(conf->channel->center_freq); | ||
2210 | ch_info = iwl_get_channel_info(priv, conf->channel->band, ch); | ||
2211 | if (!is_channel_valid(ch_info)) { | ||
2212 | IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); | ||
2213 | ret = -EINVAL; | ||
2214 | goto set_ch_out; | ||
2215 | } | ||
2209 | 2216 | ||
2210 | if (unlikely(!priv->cfg->mod_params->disable_hw_scan && | 2217 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC && |
2211 | test_bit(STATUS_SCANNING, &priv->status))) { | 2218 | !is_channel_ibss(ch_info)) { |
2212 | IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); | 2219 | IWL_ERR(priv, "channel %d in band %d not " |
2213 | mutex_unlock(&priv->mutex); | 2220 | "IBSS channel\n", |
2214 | return 0; | 2221 | conf->channel->hw_value, conf->channel->band); |
2215 | } | 2222 | ret = -EINVAL; |
2223 | goto set_ch_out; | ||
2224 | } | ||
2216 | 2225 | ||
2217 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); | 2226 | priv->current_ht_config.is_ht = conf_is_ht(conf); |
2218 | ch_info = iwl_get_channel_info(priv, conf->channel->band, channel); | ||
2219 | if (!is_channel_valid(ch_info)) { | ||
2220 | IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); | ||
2221 | ret = -EINVAL; | ||
2222 | goto out; | ||
2223 | } | ||
2224 | 2227 | ||
2225 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC && | 2228 | spin_lock_irqsave(&priv->lock, flags); |
2226 | !is_channel_ibss(ch_info)) { | ||
2227 | IWL_ERR(priv, "channel %d in band %d not IBSS channel\n", | ||
2228 | conf->channel->hw_value, conf->channel->band); | ||
2229 | ret = -EINVAL; | ||
2230 | goto out; | ||
2231 | } | ||
2232 | 2229 | ||
2233 | spin_lock_irqsave(&priv->lock, flags); | ||
2234 | 2230 | ||
2231 | /* if we are switching from ht to 2.4 clear flags | ||
2232 | * from any ht related info since 2.4 does not | ||
2233 | * support ht */ | ||
2234 | if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) | ||
2235 | priv->staging_rxon.flags = 0; | ||
2235 | 2236 | ||
2236 | /* if we are switching from ht to 2.4 clear flags | 2237 | iwl_set_rxon_channel(priv, conf->channel); |
2237 | * from any ht related info since 2.4 does not | ||
2238 | * support ht */ | ||
2239 | if ((le16_to_cpu(priv->staging_rxon.channel) != channel) | ||
2240 | #ifdef IEEE80211_CONF_CHANNEL_SWITCH | ||
2241 | && !(conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) | ||
2242 | #endif | ||
2243 | ) | ||
2244 | priv->staging_rxon.flags = 0; | ||
2245 | 2238 | ||
2246 | iwl_set_rxon_channel(priv, conf->channel); | 2239 | iwl_set_flags_for_band(priv, conf->channel->band); |
2240 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2241 | set_ch_out: | ||
2242 | /* The list of supported rates and rate mask can be different | ||
2243 | * for each band; since the band may have changed, reset | ||
2244 | * the rate mask to what mac80211 lists */ | ||
2245 | iwl_set_rate(priv); | ||
2246 | } | ||
2247 | 2247 | ||
2248 | iwl_set_flags_for_band(priv, conf->channel->band); | 2248 | if (changed & IEEE80211_CONF_CHANGE_PS) { |
2249 | if (conf->flags & IEEE80211_CONF_PS) | ||
2250 | ret = iwl_power_set_user_mode(priv, IWL_POWER_INDEX_3); | ||
2251 | else | ||
2252 | ret = iwl_power_set_user_mode(priv, IWL_POWER_MODE_CAM); | ||
2253 | if (ret) | ||
2254 | IWL_DEBUG_MAC80211(priv, "Error setting power level\n"); | ||
2249 | 2255 | ||
2250 | /* The list of supported rates and rate mask can be different | 2256 | } |
2251 | * for each band; since the band may have changed, reset | ||
2252 | * the rate mask to what mac80211 lists */ | ||
2253 | iwl_set_rate(priv); | ||
2254 | 2257 | ||
2255 | spin_unlock_irqrestore(&priv->lock, flags); | 2258 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
2259 | IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", | ||
2260 | priv->tx_power_user_lmt, conf->power_level); | ||
2256 | 2261 | ||
2257 | #ifdef IEEE80211_CONF_CHANNEL_SWITCH | 2262 | iwl_set_tx_power(priv, conf->power_level, false); |
2258 | if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) { | 2263 | } |
2259 | iwl_hw_channel_switch(priv, conf->channel); | 2264 | |
2260 | goto out; | 2265 | /* call to ensure that 4965 rx_chain is set properly in monitor mode */ |
2266 | iwl_set_rxon_chain(priv); | ||
2267 | |||
2268 | if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) { | ||
2269 | if (conf->radio_enabled && | ||
2270 | iwl_radio_kill_sw_enable_radio(priv)) { | ||
2271 | IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - " | ||
2272 | "waiting for uCode\n"); | ||
2273 | goto out; | ||
2274 | } | ||
2275 | |||
2276 | if (!conf->radio_enabled) | ||
2277 | iwl_radio_kill_sw_disable_radio(priv); | ||
2261 | } | 2278 | } |
2262 | #endif | ||
2263 | 2279 | ||
2264 | if (!conf->radio_enabled) { | 2280 | if (!conf->radio_enabled) { |
2265 | IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n"); | 2281 | IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n"); |
2266 | goto out; | 2282 | goto out; |
2267 | } | 2283 | } |
2268 | 2284 | ||
2269 | if (iwl_is_rfkill(priv)) { | 2285 | if (!iwl_is_ready(priv)) { |
2270 | IWL_DEBUG_MAC80211(priv, "leave - RF kill\n"); | 2286 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); |
2271 | ret = -EIO; | ||
2272 | goto out; | 2287 | goto out; |
2273 | } | 2288 | } |
2274 | 2289 | ||
2275 | if (conf->flags & IEEE80211_CONF_PS) | 2290 | if (scan_active) |
2276 | ret = iwl_power_set_user_mode(priv, IWL_POWER_INDEX_3); | 2291 | goto out; |
2277 | else | ||
2278 | ret = iwl_power_set_user_mode(priv, IWL_POWER_MODE_CAM); | ||
2279 | if (ret) | ||
2280 | IWL_DEBUG_MAC80211(priv, "Error setting power level\n"); | ||
2281 | |||
2282 | IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", | ||
2283 | priv->tx_power_user_lmt, conf->power_level); | ||
2284 | |||
2285 | iwl_set_tx_power(priv, conf->power_level, false); | ||
2286 | |||
2287 | iwl_set_rate(priv); | ||
2288 | |||
2289 | /* call to ensure that 4965 rx_chain is set properly in monitor mode */ | ||
2290 | iwl_set_rxon_chain(priv); | ||
2291 | 2292 | ||
2292 | if (memcmp(&priv->active_rxon, | 2293 | if (memcmp(&priv->active_rxon, |
2293 | &priv->staging_rxon, sizeof(priv->staging_rxon))) | 2294 | &priv->staging_rxon, sizeof(priv->staging_rxon))) |
@@ -2295,9 +2296,9 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2295 | else | 2296 | else |
2296 | IWL_DEBUG_INFO(priv, "No re-sending same RXON configuration.\n"); | 2297 | IWL_DEBUG_INFO(priv, "No re-sending same RXON configuration.\n"); |
2297 | 2298 | ||
2298 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
2299 | 2299 | ||
2300 | out: | 2300 | out: |
2301 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
2301 | mutex_unlock(&priv->mutex); | 2302 | mutex_unlock(&priv->mutex); |
2302 | return ret; | 2303 | return ret; |
2303 | } | 2304 | } |
@@ -2682,6 +2683,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
2682 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 2683 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) |
2683 | { | 2684 | { |
2684 | struct iwl_priv *priv = hw->priv; | 2685 | struct iwl_priv *priv = hw->priv; |
2686 | int ret; | ||
2685 | 2687 | ||
2686 | IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", | 2688 | IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", |
2687 | sta->addr, tid); | 2689 | sta->addr, tid); |
@@ -2695,13 +2697,21 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
2695 | return iwl_sta_rx_agg_start(priv, sta->addr, tid, *ssn); | 2697 | return iwl_sta_rx_agg_start(priv, sta->addr, tid, *ssn); |
2696 | case IEEE80211_AMPDU_RX_STOP: | 2698 | case IEEE80211_AMPDU_RX_STOP: |
2697 | IWL_DEBUG_HT(priv, "stop Rx\n"); | 2699 | IWL_DEBUG_HT(priv, "stop Rx\n"); |
2698 | return iwl_sta_rx_agg_stop(priv, sta->addr, tid); | 2700 | ret = iwl_sta_rx_agg_stop(priv, sta->addr, tid); |
2701 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
2702 | return 0; | ||
2703 | else | ||
2704 | return ret; | ||
2699 | case IEEE80211_AMPDU_TX_START: | 2705 | case IEEE80211_AMPDU_TX_START: |
2700 | IWL_DEBUG_HT(priv, "start Tx\n"); | 2706 | IWL_DEBUG_HT(priv, "start Tx\n"); |
2701 | return iwl_tx_agg_start(priv, sta->addr, tid, ssn); | 2707 | return iwl_tx_agg_start(priv, sta->addr, tid, ssn); |
2702 | case IEEE80211_AMPDU_TX_STOP: | 2708 | case IEEE80211_AMPDU_TX_STOP: |
2703 | IWL_DEBUG_HT(priv, "stop Tx\n"); | 2709 | IWL_DEBUG_HT(priv, "stop Tx\n"); |
2704 | return iwl_tx_agg_stop(priv, sta->addr, tid); | 2710 | ret = iwl_tx_agg_stop(priv, sta->addr, tid); |
2711 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
2712 | return 0; | ||
2713 | else | ||
2714 | return ret; | ||
2705 | default: | 2715 | default: |
2706 | IWL_DEBUG_HT(priv, "unknown\n"); | 2716 | IWL_DEBUG_HT(priv, "unknown\n"); |
2707 | return -EINVAL; | 2717 | return -EINVAL; |
@@ -3083,11 +3093,6 @@ static ssize_t store_power_level(struct device *d, | |||
3083 | 3093 | ||
3084 | mutex_lock(&priv->mutex); | 3094 | mutex_lock(&priv->mutex); |
3085 | 3095 | ||
3086 | if (!iwl_is_ready(priv)) { | ||
3087 | ret = -EAGAIN; | ||
3088 | goto out; | ||
3089 | } | ||
3090 | |||
3091 | ret = strict_strtoul(buf, 10, &mode); | 3096 | ret = strict_strtoul(buf, 10, &mode); |
3092 | if (ret) | 3097 | if (ret) |
3093 | goto out; | 3098 | goto out; |