diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-core.c')
| -rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 87 |
1 files changed, 63 insertions, 24 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 885167f8168d..4653deada05b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include "iwl-power.h" | 41 | #include "iwl-power.h" |
| 42 | #include "iwl-sta.h" | 42 | #include "iwl-sta.h" |
| 43 | #include "iwl-helpers.h" | 43 | #include "iwl-helpers.h" |
| 44 | #include "iwl-agn.h" | ||
| 44 | 45 | ||
| 45 | 46 | ||
| 46 | /* | 47 | /* |
| @@ -94,7 +95,7 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, | |||
| 94 | max_bit_rate = MAX_BIT_RATE_40_MHZ; | 95 | max_bit_rate = MAX_BIT_RATE_40_MHZ; |
| 95 | } | 96 | } |
| 96 | 97 | ||
| 97 | if (priv->cfg->mod_params->amsdu_size_8K) | 98 | if (iwlagn_mod_params.amsdu_size_8K) |
| 98 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; | 99 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; |
| 99 | 100 | ||
| 100 | ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; | 101 | ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; |
| @@ -135,6 +136,7 @@ int iwlcore_init_geos(struct iwl_priv *priv) | |||
| 135 | struct ieee80211_channel *geo_ch; | 136 | struct ieee80211_channel *geo_ch; |
| 136 | struct ieee80211_rate *rates; | 137 | struct ieee80211_rate *rates; |
| 137 | int i = 0; | 138 | int i = 0; |
| 139 | s8 max_tx_power = IWLAGN_TX_POWER_TARGET_POWER_MIN; | ||
| 138 | 140 | ||
| 139 | if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || | 141 | if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || |
| 140 | priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { | 142 | priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { |
| @@ -208,8 +210,8 @@ int iwlcore_init_geos(struct iwl_priv *priv) | |||
| 208 | 210 | ||
| 209 | geo_ch->flags |= ch->ht40_extension_channel; | 211 | geo_ch->flags |= ch->ht40_extension_channel; |
| 210 | 212 | ||
| 211 | if (ch->max_power_avg > priv->tx_power_device_lmt) | 213 | if (ch->max_power_avg > max_tx_power) |
| 212 | priv->tx_power_device_lmt = ch->max_power_avg; | 214 | max_tx_power = ch->max_power_avg; |
| 213 | } else { | 215 | } else { |
| 214 | geo_ch->flags |= IEEE80211_CHAN_DISABLED; | 216 | geo_ch->flags |= IEEE80211_CHAN_DISABLED; |
| 215 | } | 217 | } |
| @@ -222,6 +224,10 @@ int iwlcore_init_geos(struct iwl_priv *priv) | |||
| 222 | geo_ch->flags); | 224 | geo_ch->flags); |
| 223 | } | 225 | } |
| 224 | 226 | ||
| 227 | priv->tx_power_device_lmt = max_tx_power; | ||
| 228 | priv->tx_power_user_lmt = max_tx_power; | ||
| 229 | priv->tx_power_next = max_tx_power; | ||
| 230 | |||
| 225 | if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && | 231 | if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && |
| 226 | priv->cfg->sku & IWL_SKU_A) { | 232 | priv->cfg->sku & IWL_SKU_A) { |
| 227 | IWL_INFO(priv, "Incorrectly detected BG card as ABG. " | 233 | IWL_INFO(priv, "Incorrectly detected BG card as ABG. " |
| @@ -410,72 +416,72 @@ void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | |||
| 410 | int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | 416 | int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx) |
| 411 | { | 417 | { |
| 412 | struct iwl_rxon_cmd *rxon = &ctx->staging; | 418 | struct iwl_rxon_cmd *rxon = &ctx->staging; |
| 413 | bool error = false; | 419 | u32 errors = 0; |
| 414 | 420 | ||
| 415 | if (rxon->flags & RXON_FLG_BAND_24G_MSK) { | 421 | if (rxon->flags & RXON_FLG_BAND_24G_MSK) { |
| 416 | if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) { | 422 | if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) { |
| 417 | IWL_WARN(priv, "check 2.4G: wrong narrow\n"); | 423 | IWL_WARN(priv, "check 2.4G: wrong narrow\n"); |
| 418 | error = true; | 424 | errors |= BIT(0); |
| 419 | } | 425 | } |
| 420 | if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) { | 426 | if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) { |
| 421 | IWL_WARN(priv, "check 2.4G: wrong radar\n"); | 427 | IWL_WARN(priv, "check 2.4G: wrong radar\n"); |
| 422 | error = true; | 428 | errors |= BIT(1); |
| 423 | } | 429 | } |
| 424 | } else { | 430 | } else { |
| 425 | if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) { | 431 | if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) { |
| 426 | IWL_WARN(priv, "check 5.2G: not short slot!\n"); | 432 | IWL_WARN(priv, "check 5.2G: not short slot!\n"); |
| 427 | error = true; | 433 | errors |= BIT(2); |
| 428 | } | 434 | } |
| 429 | if (rxon->flags & RXON_FLG_CCK_MSK) { | 435 | if (rxon->flags & RXON_FLG_CCK_MSK) { |
| 430 | IWL_WARN(priv, "check 5.2G: CCK!\n"); | 436 | IWL_WARN(priv, "check 5.2G: CCK!\n"); |
| 431 | error = true; | 437 | errors |= BIT(3); |
| 432 | } | 438 | } |
| 433 | } | 439 | } |
| 434 | if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) { | 440 | if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) { |
| 435 | IWL_WARN(priv, "mac/bssid mcast!\n"); | 441 | IWL_WARN(priv, "mac/bssid mcast!\n"); |
| 436 | error = true; | 442 | errors |= BIT(4); |
| 437 | } | 443 | } |
| 438 | 444 | ||
| 439 | /* make sure basic rates 6Mbps and 1Mbps are supported */ | 445 | /* make sure basic rates 6Mbps and 1Mbps are supported */ |
| 440 | if ((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0 && | 446 | if ((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0 && |
| 441 | (rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0) { | 447 | (rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0) { |
| 442 | IWL_WARN(priv, "neither 1 nor 6 are basic\n"); | 448 | IWL_WARN(priv, "neither 1 nor 6 are basic\n"); |
| 443 | error = true; | 449 | errors |= BIT(5); |
| 444 | } | 450 | } |
| 445 | 451 | ||
| 446 | if (le16_to_cpu(rxon->assoc_id) > 2007) { | 452 | if (le16_to_cpu(rxon->assoc_id) > 2007) { |
| 447 | IWL_WARN(priv, "aid > 2007\n"); | 453 | IWL_WARN(priv, "aid > 2007\n"); |
| 448 | error = true; | 454 | errors |= BIT(6); |
| 449 | } | 455 | } |
| 450 | 456 | ||
| 451 | if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) | 457 | if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) |
| 452 | == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) { | 458 | == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) { |
| 453 | IWL_WARN(priv, "CCK and short slot\n"); | 459 | IWL_WARN(priv, "CCK and short slot\n"); |
| 454 | error = true; | 460 | errors |= BIT(7); |
| 455 | } | 461 | } |
| 456 | 462 | ||
| 457 | if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) | 463 | if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) |
| 458 | == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) { | 464 | == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) { |
| 459 | IWL_WARN(priv, "CCK and auto detect"); | 465 | IWL_WARN(priv, "CCK and auto detect"); |
| 460 | error = true; | 466 | errors |= BIT(8); |
| 461 | } | 467 | } |
| 462 | 468 | ||
| 463 | if ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK | | 469 | if ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK | |
| 464 | RXON_FLG_TGG_PROTECT_MSK)) == | 470 | RXON_FLG_TGG_PROTECT_MSK)) == |
| 465 | RXON_FLG_TGG_PROTECT_MSK) { | 471 | RXON_FLG_TGG_PROTECT_MSK) { |
| 466 | IWL_WARN(priv, "TGg but no auto-detect\n"); | 472 | IWL_WARN(priv, "TGg but no auto-detect\n"); |
| 467 | error = true; | 473 | errors |= BIT(9); |
| 468 | } | 474 | } |
| 469 | 475 | ||
| 470 | if (error) | 476 | if (rxon->channel == 0) { |
| 471 | IWL_WARN(priv, "Tuning to channel %d\n", | 477 | IWL_WARN(priv, "zero channel is invalid\n"); |
| 472 | le16_to_cpu(rxon->channel)); | 478 | errors |= BIT(10); |
| 473 | |||
| 474 | if (error) { | ||
| 475 | IWL_ERR(priv, "Invalid RXON\n"); | ||
| 476 | return -EINVAL; | ||
| 477 | } | 479 | } |
| 478 | return 0; | 480 | |
| 481 | WARN(errors, "Invalid RXON (%#x), channel %d", | ||
| 482 | errors, le16_to_cpu(rxon->channel)); | ||
| 483 | |||
| 484 | return errors ? -EINVAL : 0; | ||
| 479 | } | 485 | } |
| 480 | 486 | ||
| 481 | /** | 487 | /** |
| @@ -867,6 +873,19 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv, | |||
| 867 | } | 873 | } |
| 868 | #endif | 874 | #endif |
| 869 | 875 | ||
| 876 | static void iwlagn_abort_notification_waits(struct iwl_priv *priv) | ||
| 877 | { | ||
| 878 | unsigned long flags; | ||
| 879 | struct iwl_notification_wait *wait_entry; | ||
| 880 | |||
| 881 | spin_lock_irqsave(&priv->_agn.notif_wait_lock, flags); | ||
| 882 | list_for_each_entry(wait_entry, &priv->_agn.notif_waits, list) | ||
| 883 | wait_entry->aborted = true; | ||
| 884 | spin_unlock_irqrestore(&priv->_agn.notif_wait_lock, flags); | ||
| 885 | |||
| 886 | wake_up_all(&priv->_agn.notif_waitq); | ||
| 887 | } | ||
| 888 | |||
| 870 | void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) | 889 | void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) |
| 871 | { | 890 | { |
| 872 | unsigned int reload_msec; | 891 | unsigned int reload_msec; |
| @@ -878,6 +897,8 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) | |||
| 878 | /* Cancel currently queued command. */ | 897 | /* Cancel currently queued command. */ |
| 879 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 898 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
| 880 | 899 | ||
| 900 | iwlagn_abort_notification_waits(priv); | ||
| 901 | |||
| 881 | /* Keep the restart process from trying to send host | 902 | /* Keep the restart process from trying to send host |
| 882 | * commands by clearing the ready bit */ | 903 | * commands by clearing the ready bit */ |
| 883 | clear_bit(STATUS_READY, &priv->status); | 904 | clear_bit(STATUS_READY, &priv->status); |
| @@ -906,7 +927,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) | |||
| 906 | } | 927 | } |
| 907 | 928 | ||
| 908 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { | 929 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { |
| 909 | if (priv->cfg->mod_params->restart_fw) { | 930 | if (iwlagn_mod_params.restart_fw) { |
| 910 | IWL_DEBUG(priv, IWL_DL_FW_ERRORS, | 931 | IWL_DEBUG(priv, IWL_DL_FW_ERRORS, |
| 911 | "Restarting adapter due to uCode error.\n"); | 932 | "Restarting adapter due to uCode error.\n"); |
| 912 | queue_work(priv->workqueue, &priv->restart); | 933 | queue_work(priv->workqueue, &priv->restart); |
| @@ -975,6 +996,8 @@ void iwl_apm_stop(struct iwl_priv *priv) | |||
| 975 | { | 996 | { |
| 976 | IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n"); | 997 | IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n"); |
| 977 | 998 | ||
| 999 | clear_bit(STATUS_DEVICE_ENABLED, &priv->status); | ||
| 1000 | |||
| 978 | /* Stop device's DMA activity */ | 1001 | /* Stop device's DMA activity */ |
| 979 | iwl_apm_stop_master(priv); | 1002 | iwl_apm_stop_master(priv); |
| 980 | 1003 | ||
| @@ -1089,6 +1112,8 @@ int iwl_apm_init(struct iwl_priv *priv) | |||
| 1089 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | 1112 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, |
| 1090 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | 1113 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); |
| 1091 | 1114 | ||
| 1115 | set_bit(STATUS_DEVICE_ENABLED, &priv->status); | ||
| 1116 | |||
| 1092 | out: | 1117 | out: |
| 1093 | return ret; | 1118 | return ret; |
| 1094 | } | 1119 | } |
| @@ -1723,7 +1748,7 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) | |||
| 1723 | * detect failure), then fw_restart module parameter | 1748 | * detect failure), then fw_restart module parameter |
| 1724 | * need to be check before performing firmware reload | 1749 | * need to be check before performing firmware reload |
| 1725 | */ | 1750 | */ |
| 1726 | if (!external && !priv->cfg->mod_params->restart_fw) { | 1751 | if (!external && !iwlagn_mod_params.restart_fw) { |
| 1727 | IWL_DEBUG_INFO(priv, "Cancel firmware reload based on " | 1752 | IWL_DEBUG_INFO(priv, "Cancel firmware reload based on " |
| 1728 | "module parameter setting\n"); | 1753 | "module parameter setting\n"); |
| 1729 | break; | 1754 | break; |
| @@ -1740,6 +1765,7 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
| 1740 | { | 1765 | { |
| 1741 | struct iwl_priv *priv = hw->priv; | 1766 | struct iwl_priv *priv = hw->priv; |
| 1742 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | 1767 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); |
| 1768 | struct iwl_rxon_context *bss_ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
| 1743 | struct iwl_rxon_context *tmp; | 1769 | struct iwl_rxon_context *tmp; |
| 1744 | u32 interface_modes; | 1770 | u32 interface_modes; |
| 1745 | int err; | 1771 | int err; |
| @@ -1764,6 +1790,19 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
| 1764 | goto out; | 1790 | goto out; |
| 1765 | } | 1791 | } |
| 1766 | 1792 | ||
| 1793 | /* | ||
| 1794 | * Refuse a change that should be done by moving from the PAN | ||
| 1795 | * context to the BSS context instead, if the BSS context is | ||
| 1796 | * available and can support the new interface type. | ||
| 1797 | */ | ||
| 1798 | if (ctx->ctxid == IWL_RXON_CTX_PAN && !bss_ctx->vif && | ||
| 1799 | (bss_ctx->interface_modes & BIT(newtype) || | ||
| 1800 | bss_ctx->exclusive_interface_modes & BIT(newtype))) { | ||
| 1801 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | ||
| 1802 | err = -EBUSY; | ||
| 1803 | goto out; | ||
| 1804 | } | ||
| 1805 | |||
| 1767 | if (ctx->exclusive_interface_modes & BIT(newtype)) { | 1806 | if (ctx->exclusive_interface_modes & BIT(newtype)) { |
| 1768 | for_each_context(priv, tmp) { | 1807 | for_each_context(priv, tmp) { |
| 1769 | if (ctx == tmp) | 1808 | if (ctx == tmp) |
