aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Bondar <alexander.bondar@intel.com>2014-02-03 14:57:28 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-02-13 06:45:12 -0500
commit7303dd7f312f0d07a4bf45c62608d5233b5e8062 (patch)
tree54ecbc28ddb44a5f772e811d07e0b85cefd22745
parentf3c221f6ea17f4fea250ac17c7f27ecb71e62465 (diff)
iwlwifi: mvm: Enable power save on BSS and P2P client in DCM
New FW enables support for power save on BSS and P2P client MACs simultaneously when they function on different channels (DCM). Enable this case in the driver after examining new TLV flag - IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM. Still power management is not allowed on both MACs if they function on a same channel. Remove another redundant TLV flag - IWL_UCODE_TLV_FLAGS_P2P_PS that is not in use anymore. Remove bound_vif_cnt as redundant. Signed-off-by: Alexander Bondar <alexander.bondar@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw.h6
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c6
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/power.c48
5 files changed, 44 insertions, 20 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index f80ba586c253..b0d09987540d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -92,8 +92,8 @@
92 * @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API 92 * @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API
93 * @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command 93 * @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command
94 * containing CAM (Continuous Active Mode) indication. 94 * containing CAM (Continuous Active Mode) indication.
95 * @IWL_UCODE_TLV_FLAGS_P2P_PS: P2P client power save is supported (only on a 95 * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_DCM: support power save on BSS station and
96 * single bound interface). 96 * P2P client interfaces simultaneously if they are in different bindings.
97 * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save 97 * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save
98 * @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering. 98 * @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering.
99 * @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients 99 * @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients
@@ -118,7 +118,7 @@ enum iwl_ucode_tlv_flag {
118 IWL_UCODE_TLV_FLAGS_SCHED_SCAN = BIT(17), 118 IWL_UCODE_TLV_FLAGS_SCHED_SCAN = BIT(17),
119 IWL_UCODE_TLV_FLAGS_STA_KEY_CMD = BIT(19), 119 IWL_UCODE_TLV_FLAGS_STA_KEY_CMD = BIT(19),
120 IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD = BIT(20), 120 IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD = BIT(20),
121 IWL_UCODE_TLV_FLAGS_P2P_PS = BIT(21), 121 IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM = BIT(22),
122 IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24), 122 IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24),
123 IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26), 123 IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26),
124 IWL_UCODE_TLV_FLAGS_BCAST_FILTERING = BIT(29), 124 IWL_UCODE_TLV_FLAGS_BCAST_FILTERING = BIT(29),
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
index 29b4396018b1..f64e972191eb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
@@ -591,7 +591,7 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
591 iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM && 591 iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
592 ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) || 592 ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) ||
593 (vif->type == NL80211_IFTYPE_STATION && vif->p2p && 593 (vif->type == NL80211_IFTYPE_STATION && vif->p2p &&
594 mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS))) 594 mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)))
595 MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR | 595 MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR |
596 S_IRUSR); 596 S_IRUSR);
597 597
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 2a1b4b628e2f..83da68c8b4a9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -1305,7 +1305,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
1305 mvmvif->ap_ibss_active = true; 1305 mvmvif->ap_ibss_active = true;
1306 1306
1307 /* power updated needs to be done before quotas */ 1307 /* power updated needs to be done before quotas */
1308 mvm->bound_vif_cnt++;
1309 iwl_mvm_power_update_mac(mvm, vif); 1308 iwl_mvm_power_update_mac(mvm, vif);
1310 1309
1311 ret = iwl_mvm_update_quotas(mvm, vif); 1310 ret = iwl_mvm_update_quotas(mvm, vif);
@@ -1324,7 +1323,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
1324 return 0; 1323 return 0;
1325 1324
1326out_quota_failed: 1325out_quota_failed:
1327 mvm->bound_vif_cnt--;
1328 iwl_mvm_power_update_mac(mvm, vif); 1326 iwl_mvm_power_update_mac(mvm, vif);
1329 mvmvif->ap_ibss_active = false; 1327 mvmvif->ap_ibss_active = false;
1330 iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta); 1328 iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
@@ -1361,7 +1359,6 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw,
1361 iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta); 1359 iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
1362 iwl_mvm_binding_remove_vif(mvm, vif); 1360 iwl_mvm_binding_remove_vif(mvm, vif);
1363 1361
1364 mvm->bound_vif_cnt--;
1365 iwl_mvm_power_update_mac(mvm, vif); 1362 iwl_mvm_power_update_mac(mvm, vif);
1366 1363
1367 iwl_mvm_mac_ctxt_remove(mvm, vif); 1364 iwl_mvm_mac_ctxt_remove(mvm, vif);
@@ -2095,7 +2092,6 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
2095 * Power state must be updated before quotas, 2092 * Power state must be updated before quotas,
2096 * otherwise fw will complain. 2093 * otherwise fw will complain.
2097 */ 2094 */
2098 mvm->bound_vif_cnt++;
2099 iwl_mvm_power_update_mac(mvm, vif); 2095 iwl_mvm_power_update_mac(mvm, vif);
2100 2096
2101 /* Setting the quota at this stage is only required for monitor 2097 /* Setting the quota at this stage is only required for monitor
@@ -2113,7 +2109,6 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
2113 2109
2114 out_remove_binding: 2110 out_remove_binding:
2115 iwl_mvm_binding_remove_vif(mvm, vif); 2111 iwl_mvm_binding_remove_vif(mvm, vif);
2116 mvm->bound_vif_cnt--;
2117 iwl_mvm_power_update_mac(mvm, vif); 2112 iwl_mvm_power_update_mac(mvm, vif);
2118 out_unlock: 2113 out_unlock:
2119 mutex_unlock(&mvm->mutex); 2114 mutex_unlock(&mvm->mutex);
@@ -2146,7 +2141,6 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
2146 } 2141 }
2147 2142
2148 iwl_mvm_binding_remove_vif(mvm, vif); 2143 iwl_mvm_binding_remove_vif(mvm, vif);
2149 mvm->bound_vif_cnt--;
2150 iwl_mvm_power_update_mac(mvm, vif); 2144 iwl_mvm_power_update_mac(mvm, vif);
2151 2145
2152out_unlock: 2146out_unlock:
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 29d11d93441d..823765ea89a9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -587,8 +587,6 @@ struct iwl_mvm {
587 u8 first_agg_queue; 587 u8 first_agg_queue;
588 u8 last_agg_queue; 588 u8 last_agg_queue;
589 589
590 u8 bound_vif_cnt;
591
592 /* Indicate if device power save is allowed */ 590 /* Indicate if device power save is allowed */
593 bool ps_disabled; 591 bool ps_disabled;
594 /* Indicate if device power management is allowed */ 592 /* Indicate if device power management is allowed */
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index 4da1ea44f39a..def6ec5173b9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -425,7 +425,7 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
425 return 0; 425 return 0;
426 426
427 if (vif->p2p && 427 if (vif->p2p &&
428 !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS)) 428 !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM))
429 return 0; 429 return 0;
430 430
431 iwl_mvm_power_build_cmd(mvm, vif, &cmd); 431 iwl_mvm_power_build_cmd(mvm, vif, &cmd);
@@ -511,8 +511,11 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
511struct iwl_power_constraint { 511struct iwl_power_constraint {
512 struct ieee80211_vif *bf_vif; 512 struct ieee80211_vif *bf_vif;
513 struct ieee80211_vif *bss_vif; 513 struct ieee80211_vif *bss_vif;
514 u16 bss_phyctx_id;
515 u16 p2p_phyctx_id;
514 bool pm_disabled; 516 bool pm_disabled;
515 bool ps_disabled; 517 bool ps_disabled;
518 struct iwl_mvm *mvm;
516}; 519};
517 520
518static void iwl_mvm_power_iterator(void *_data, u8 *mac, 521static void iwl_mvm_power_iterator(void *_data, u8 *mac,
@@ -520,6 +523,7 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac,
520{ 523{
521 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 524 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
522 struct iwl_power_constraint *power_iterator = _data; 525 struct iwl_power_constraint *power_iterator = _data;
526 struct iwl_mvm *mvm = power_iterator->mvm;
523 527
524 switch (ieee80211_vif_type_p2p(vif)) { 528 switch (ieee80211_vif_type_p2p(vif)) {
525 case NL80211_IFTYPE_P2P_DEVICE: 529 case NL80211_IFTYPE_P2P_DEVICE:
@@ -539,11 +543,28 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac,
539 break; 543 break;
540 544
541 case NL80211_IFTYPE_P2P_CLIENT: 545 case NL80211_IFTYPE_P2P_CLIENT:
542 /* no BSS power mgmt if we have a P2P client*/ 546 if (mvmvif->phy_ctxt)
543 power_iterator->pm_disabled = true; 547 power_iterator->p2p_phyctx_id = mvmvif->phy_ctxt->id;
548
549 IWL_DEBUG_POWER(mvm, "p2p: p2p_id=%d, bss_id=%d\n",
550 power_iterator->p2p_phyctx_id,
551 power_iterator->bss_phyctx_id);
552 if (!(mvm->fw->ucode_capa.flags &
553 IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)) {
554 /* no BSS power mgmt if we have a P2P client*/
555 power_iterator->pm_disabled = true;
556 } else if (power_iterator->p2p_phyctx_id < MAX_PHYS &&
557 power_iterator->bss_phyctx_id < MAX_PHYS &&
558 power_iterator->p2p_phyctx_id ==
559 power_iterator->bss_phyctx_id) {
560 power_iterator->pm_disabled = true;
561 }
544 break; 562 break;
545 563
546 case NL80211_IFTYPE_STATION: 564 case NL80211_IFTYPE_STATION:
565 if (mvmvif->phy_ctxt)
566 power_iterator->bss_phyctx_id = mvmvif->phy_ctxt->id;
567
547 /* we should have only one BSS vif */ 568 /* we should have only one BSS vif */
548 WARN_ON(power_iterator->bss_vif); 569 WARN_ON(power_iterator->bss_vif);
549 power_iterator->bss_vif = vif; 570 power_iterator->bss_vif = vif;
@@ -551,6 +572,17 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac,
551 if (mvmvif->bf_data.bf_enabled && 572 if (mvmvif->bf_data.bf_enabled &&
552 !WARN_ON(power_iterator->bf_vif)) 573 !WARN_ON(power_iterator->bf_vif))
553 power_iterator->bf_vif = vif; 574 power_iterator->bf_vif = vif;
575
576 IWL_DEBUG_POWER(mvm, "bss: p2p_id=%d, bss_id=%d\n",
577 power_iterator->p2p_phyctx_id,
578 power_iterator->bss_phyctx_id);
579 if (mvm->fw->ucode_capa.flags &
580 IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM &&
581 (power_iterator->p2p_phyctx_id < MAX_PHYS &&
582 power_iterator->bss_phyctx_id < MAX_PHYS &&
583 power_iterator->p2p_phyctx_id ==
584 power_iterator->bss_phyctx_id))
585 power_iterator->pm_disabled = true;
554 break; 586 break;
555 587
556 default: 588 default:
@@ -572,16 +604,16 @@ iwl_mvm_power_get_global_constraint(struct iwl_mvm *mvm,
572 ieee80211_iterate_active_interfaces_atomic(mvm->hw, 604 ieee80211_iterate_active_interfaces_atomic(mvm->hw,
573 IEEE80211_IFACE_ITER_NORMAL, 605 IEEE80211_IFACE_ITER_NORMAL,
574 iwl_mvm_power_iterator, constraint); 606 iwl_mvm_power_iterator, constraint);
575
576 /* TODO: remove this and determine this variable in the iterator */
577 if (mvm->bound_vif_cnt > 1)
578 constraint->pm_disabled = true;
579} 607}
580 608
581int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif) 609int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
582{ 610{
583 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 611 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
584 struct iwl_power_constraint constraint = {}; 612 struct iwl_power_constraint constraint = {
613 .p2p_phyctx_id = MAX_PHYS,
614 .bss_phyctx_id = MAX_PHYS,
615 .mvm = mvm,
616 };
585 bool ba_enable; 617 bool ba_enable;
586 int ret; 618 int ret;
587 619