aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c48
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c5
6 files changed, 52 insertions, 10 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 2f841a8576e0..a4a8b5e2f411 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -490,6 +490,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
490 .supports_idle = true, 490 .supports_idle = true,
491 .adv_thermal_throttle = true, 491 .adv_thermal_throttle = true,
492 .support_ct_kill_exit = true, 492 .support_ct_kill_exit = true,
493 .support_sm_ps = true,
493}; 494};
494 495
495struct iwl_cfg iwl6050_2abg_cfg = { 496struct iwl_cfg iwl6050_2abg_cfg = {
@@ -579,6 +580,7 @@ struct iwl_cfg iwl6050_3agn_cfg = {
579 .supports_idle = true, 580 .supports_idle = true,
580 .adv_thermal_throttle = true, 581 .adv_thermal_throttle = true,
581 .support_ct_kill_exit = true, 582 .support_ct_kill_exit = true,
583 .support_sm_ps = true,
582}; 584};
583 585
584MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); 586MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 4a13f7e21d63..b5fe8f87aa7e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3011,6 +3011,10 @@ static int iwl_init_drv(struct iwl_priv *priv)
3011 priv->band = IEEE80211_BAND_2GHZ; 3011 priv->band = IEEE80211_BAND_2GHZ;
3012 3012
3013 priv->iw_mode = NL80211_IFTYPE_STATION; 3013 priv->iw_mode = NL80211_IFTYPE_STATION;
3014 if (priv->cfg->support_sm_ps)
3015 priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DYNAMIC;
3016 else
3017 priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED;
3014 3018
3015 /* Choose which receivers/antennas to use */ 3019 /* Choose which receivers/antennas to use */
3016 if (priv->cfg->ops->hcmd->set_rxon_chain) 3020 if (priv->cfg->ops->hcmd->set_rxon_chain)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 256c9a49fa3b..c4ff381e440e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -414,8 +414,12 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
414 if (priv->cfg->ht_greenfield_support) 414 if (priv->cfg->ht_greenfield_support)
415 ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; 415 ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
416 ht_info->cap |= IEEE80211_HT_CAP_SGI_20; 416 ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
417 ht_info->cap |= (IEEE80211_HT_CAP_SM_PS & 417 if (priv->cfg->support_sm_ps)
418 (WLAN_HT_CAP_SM_PS_DISABLED << 2)); 418 ht_info->cap |= (IEEE80211_HT_CAP_SM_PS &
419 (WLAN_HT_CAP_SM_PS_DYNAMIC << 2));
420 else
421 ht_info->cap |= (IEEE80211_HT_CAP_SM_PS &
422 (WLAN_HT_CAP_SM_PS_DISABLED << 2));
419 423
420 max_bit_rate = MAX_BIT_RATE_20_MHZ; 424 max_bit_rate = MAX_BIT_RATE_20_MHZ;
421 if (priv->hw_params.ht40_channel & BIT(band)) { 425 if (priv->hw_params.ht40_channel & BIT(band)) {
@@ -963,17 +967,35 @@ static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
963} 967}
964 968
965/* 969/*
966 * When we are in power saving, there's no difference between 970 * When we are in power saving mode, unless device support spatial
967 * using multiple chains or just a single chain, but due to the 971 * multiplexing power save, use the active count for rx chain count.
968 * lack of SM PS we lose a lot of throughput if we use just a
969 * single chain.
970 *
971 * Therefore, use the active count here (which will use multiple
972 * chains unless connected to a legacy AP).
973 */ 972 */
974static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) 973static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
975{ 974{
976 return active_cnt; 975 int idle_cnt = active_cnt;
976 bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
977
978 if (priv->cfg->support_sm_ps) {
979 /* # Rx chains when idling and maybe trying to save power */
980 switch (priv->current_ht_config.sm_ps) {
981 case WLAN_HT_CAP_SM_PS_STATIC:
982 case WLAN_HT_CAP_SM_PS_DYNAMIC:
983 idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL :
984 IWL_NUM_IDLE_CHAINS_SINGLE;
985 break;
986 case WLAN_HT_CAP_SM_PS_DISABLED:
987 idle_cnt = (is_cam) ? active_cnt :
988 IWL_NUM_IDLE_CHAINS_SINGLE;
989 break;
990 case WLAN_HT_CAP_SM_PS_INVALID:
991 default:
992 IWL_ERR(priv, "invalid sm_ps mode %d\n",
993 priv->current_ht_config.sm_ps);
994 WARN_ON(1);
995 break;
996 }
997 }
998 return idle_cnt;
977} 999}
978 1000
979/* up to 4 chains */ 1001/* up to 4 chains */
@@ -2257,6 +2279,12 @@ static void iwl_ht_conf(struct iwl_priv *priv,
2257 >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; 2279 >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
2258 maxstreams += 1; 2280 maxstreams += 1;
2259 2281
2282 ht_conf->sm_ps =
2283 (u8)((ht_cap->cap & IEEE80211_HT_CAP_SM_PS)
2284 >> 2);
2285 IWL_DEBUG_MAC80211(priv, "sm_ps: 0x%x\n",
2286 ht_conf->sm_ps);
2287
2260 if ((ht_cap->mcs.rx_mask[1] == 0) && 2288 if ((ht_cap->mcs.rx_mask[1] == 0) &&
2261 (ht_cap->mcs.rx_mask[2] == 0)) 2289 (ht_cap->mcs.rx_mask[2] == 0))
2262 ht_conf->single_chain_sufficient = true; 2290 ht_conf->single_chain_sufficient = true;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index ddf0998fb752..d2e47dab38d4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -228,6 +228,7 @@ struct iwl_mod_params {
228 * @chain_noise_num_beacons: number of beacons used to compute chain noise 228 * @chain_noise_num_beacons: number of beacons used to compute chain noise
229 * @adv_thermal_throttle: support advance thermal throttle 229 * @adv_thermal_throttle: support advance thermal throttle
230 * @support_ct_kill_exit: support ct kill exit condition 230 * @support_ct_kill_exit: support ct kill exit condition
231 * @support_sm_ps: support spatial multiplexing power save
231 * 232 *
232 * We enable the driver to be backward compatible wrt API version. The 233 * We enable the driver to be backward compatible wrt API version. The
233 * driver specifies which APIs it supports (with @ucode_api_max being the 234 * driver specifies which APIs it supports (with @ucode_api_max being the
@@ -283,6 +284,7 @@ struct iwl_cfg {
283 const bool supports_idle; 284 const bool supports_idle;
284 bool adv_thermal_throttle; 285 bool adv_thermal_throttle;
285 bool support_ct_kill_exit; 286 bool support_ct_kill_exit;
287 bool support_sm_ps;
286}; 288};
287 289
288/*************************** 290/***************************
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index e7ce67387662..cb2642c18da4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -517,6 +517,7 @@ struct iwl_ht_config {
517 bool is_ht; 517 bool is_ht;
518 bool is_40mhz; 518 bool is_40mhz;
519 bool single_chain_sufficient; 519 bool single_chain_sufficient;
520 u8 sm_ps;
520 /* BSS related data */ 521 /* BSS related data */
521 u8 extension_chan_offset; 522 u8 extension_chan_offset;
522 u8 ht_protection; 523 u8 ht_protection;
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index ce1ceac19c7d..74cc8dbe9359 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -182,6 +182,11 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
182 goto done; 182 goto done;
183 183
184 mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; 184 mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
185 IWL_DEBUG_ASSOC(priv, "spatial multiplexing power save mode: %s\n",
186 (mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ?
187 "static" :
188 (mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ?
189 "dynamic" : "disabled");
185 190
186 sta_flags = priv->stations[index].sta.station_flags; 191 sta_flags = priv->stations[index].sta.station_flags;
187 192