aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Doron <jonathanx.doron@intel.com>2014-11-27 09:55:25 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2015-03-12 03:57:31 -0400
commit47c8b154a7d080626dfd148397782a49d5212a88 (patch)
treeffb92d251900e07840b42658e9f788dbf092f472
parent7f0344c218a6110cbdb7d0974984838e35a24b30 (diff)
iwlwifi: mvm: set LAR MCC on D3/D0 transitions
When moving to the D3 FW give it the valid MCC from the D0 FW. When returning from D3 to D0, query the D3 FW for the latest MCC, as it might have changed internally. This MCC will be replayed to the D0 FW when it boots. Signed-off-by: Jonathan Doron <jonathanx.doron@intel.com> Reviewed-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/d3.c9
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c33
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h7
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/nvm.c8
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c4
6 files changed, 51 insertions, 12 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index 9bdfa95d6ce7..486fd4c259c3 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -694,6 +694,9 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
694 if (ret) 694 if (ret)
695 IWL_ERR(mvm, "Failed to send quota: %d\n", ret); 695 IWL_ERR(mvm, "Failed to send quota: %d\n", ret);
696 696
697 if (iwl_mvm_is_lar_supported(mvm) && iwl_mvm_init_fw_regd(mvm))
698 IWL_ERR(mvm, "Failed to initialize D3 LAR information\n");
699
697 return 0; 700 return 0;
698} 701}
699 702
@@ -1874,6 +1877,12 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
1874 /* query SRAM first in case we want event logging */ 1877 /* query SRAM first in case we want event logging */
1875 iwl_mvm_read_d3_sram(mvm); 1878 iwl_mvm_read_d3_sram(mvm);
1876 1879
1880 /*
1881 * Query the current location and source from the D3 firmware so we
1882 * can play it back when we re-intiailize the D0 firmware
1883 */
1884 iwl_mvm_update_changed_regdom(mvm);
1885
1877 if (mvm->net_detect) { 1886 if (mvm->net_detect) {
1878 iwl_mvm_query_netdetect_reasons(mvm, vif); 1887 iwl_mvm_query_netdetect_reasons(mvm, vif);
1879 /* has unlocked the mutex, so skip that */ 1888 /* has unlocked the mutex, so skip that */
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index 7e4936585544..d89b0dd9e728 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -1503,7 +1503,7 @@ struct iwl_mcc_update_cmd {
1503 * Contains the new channel control profile map, if changed, and the new MCC 1503 * Contains the new channel control profile map, if changed, and the new MCC
1504 * (mobile country code). 1504 * (mobile country code).
1505 * The new MCC may be different than what was requested in MCC_UPDATE_CMD. 1505 * The new MCC may be different than what was requested in MCC_UPDATE_CMD.
1506 * @status: 0 for success, 1 no change in channel profile, 2 invalid input. 1506 * @status: see &enum iwl_mcc_update_status
1507 * @mcc: the new applied MCC 1507 * @mcc: the new applied MCC
1508 * @cap: capabilities for all channels which matches the MCC 1508 * @cap: capabilities for all channels which matches the MCC
1509 * @source_id: the MCC source, see iwl_mcc_source 1509 * @source_id: the MCC source, see iwl_mcc_source
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 303a7a0c6498..74847244c833 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -304,7 +304,8 @@ static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm)
304 304
305struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy, 305struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
306 const char *alpha2, 306 const char *alpha2,
307 enum iwl_mcc_source src_id) 307 enum iwl_mcc_source src_id,
308 bool *changed)
308{ 309{
309 struct ieee80211_regdomain *regd = NULL; 310 struct ieee80211_regdomain *regd = NULL;
310 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); 311 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
@@ -322,6 +323,9 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
322 goto out; 323 goto out;
323 } 324 }
324 325
326 if (changed)
327 *changed = (resp->status == MCC_RESP_NEW_CHAN_PROFILE);
328
325 regd = iwl_parse_nvm_mcc_info(mvm->trans->dev, mvm->cfg, 329 regd = iwl_parse_nvm_mcc_info(mvm->trans->dev, mvm->cfg,
326 __le32_to_cpu(resp->n_channels), 330 __le32_to_cpu(resp->n_channels),
327 resp->channels, 331 resp->channels,
@@ -344,12 +348,31 @@ out:
344 return regd; 348 return regd;
345} 349}
346 350
347struct ieee80211_regdomain *iwl_mvm_get_current_regdomain(struct iwl_mvm *mvm) 351void iwl_mvm_update_changed_regdom(struct iwl_mvm *mvm)
352{
353 bool changed;
354 struct ieee80211_regdomain *regd;
355
356 if (!iwl_mvm_is_lar_supported(mvm))
357 return;
358
359 regd = iwl_mvm_get_current_regdomain(mvm, &changed);
360 if (!IS_ERR_OR_NULL(regd)) {
361 /* only update the regulatory core if changed */
362 if (changed)
363 regulatory_set_wiphy_regd(mvm->hw->wiphy, regd);
364
365 kfree(regd);
366 }
367}
368
369struct ieee80211_regdomain *iwl_mvm_get_current_regdomain(struct iwl_mvm *mvm,
370 bool *changed)
348{ 371{
349 return iwl_mvm_get_regdomain(mvm->hw->wiphy, "ZZ", 372 return iwl_mvm_get_regdomain(mvm->hw->wiphy, "ZZ",
350 iwl_mvm_is_wifi_mcc_supported(mvm) ? 373 iwl_mvm_is_wifi_mcc_supported(mvm) ?
351 MCC_SOURCE_GET_CURRENT : 374 MCC_SOURCE_GET_CURRENT :
352 MCC_SOURCE_OLD_FW); 375 MCC_SOURCE_OLD_FW, changed);
353} 376}
354 377
355int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm) 378int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm)
@@ -366,13 +389,13 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm)
366 used_src = mvm->mcc_src; 389 used_src = mvm->mcc_src;
367 if (iwl_mvm_is_wifi_mcc_supported(mvm)) { 390 if (iwl_mvm_is_wifi_mcc_supported(mvm)) {
368 /* Notify the firmware we support wifi location updates */ 391 /* Notify the firmware we support wifi location updates */
369 regd = iwl_mvm_get_current_regdomain(mvm); 392 regd = iwl_mvm_get_current_regdomain(mvm, NULL);
370 if (!IS_ERR_OR_NULL(regd)) 393 if (!IS_ERR_OR_NULL(regd))
371 kfree(regd); 394 kfree(regd);
372 } 395 }
373 396
374 /* Now set our last stored MCC and source */ 397 /* Now set our last stored MCC and source */
375 regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, r->alpha2, used_src); 398 regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, r->alpha2, used_src, NULL);
376 if (IS_ERR_OR_NULL(regd)) 399 if (IS_ERR_OR_NULL(regd))
377 return -EIO; 400 return -EIO;
378 401
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 5d5be372593a..9a8868e31ddf 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -1426,9 +1426,12 @@ int iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm,
1426 struct iwl_device_cmd *cmd); 1426 struct iwl_device_cmd *cmd);
1427struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy, 1427struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
1428 const char *alpha2, 1428 const char *alpha2,
1429 enum iwl_mcc_source src_id); 1429 enum iwl_mcc_source src_id,
1430struct ieee80211_regdomain *iwl_mvm_get_current_regdomain(struct iwl_mvm *mvm); 1430 bool *changed);
1431struct ieee80211_regdomain *iwl_mvm_get_current_regdomain(struct iwl_mvm *mvm,
1432 bool *changed);
1431int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm); 1433int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm);
1434void iwl_mvm_update_changed_regdom(struct iwl_mvm *mvm);
1432 1435
1433/* smart fifo */ 1436/* smart fifo */
1434int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 1437int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c
index d08ea695685f..123e0a16aea8 100644
--- a/drivers/net/wireless/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c
@@ -655,7 +655,7 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
655 IWL_DEBUG_LAR(mvm, 655 IWL_DEBUG_LAR(mvm,
656 "MCC response status: 0x%x. new MCC: 0x%x ('%c%c') change: %d n_chans: %d\n", 656 "MCC response status: 0x%x. new MCC: 0x%x ('%c%c') change: %d n_chans: %d\n",
657 status, mcc, mcc >> 8, mcc & 0xff, 657 status, mcc, mcc >> 8, mcc & 0xff,
658 !!(status == MCC_RESP_SAME_CHAN_PROFILE), n_channels); 658 !!(status == MCC_RESP_NEW_CHAN_PROFILE), n_channels);
659 659
660 resp_len = sizeof(*mcc_resp) + n_channels * sizeof(__le32); 660 resp_len = sizeof(*mcc_resp) + n_channels * sizeof(__le32);
661 resp_cp = kmemdup(mcc_resp, resp_len, GFP_KERNEL); 661 resp_cp = kmemdup(mcc_resp, resp_len, GFP_KERNEL);
@@ -802,7 +802,7 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
802 */ 802 */
803 mvm->lar_regdom_set = false; 803 mvm->lar_regdom_set = false;
804 804
805 regd = iwl_mvm_get_current_regdomain(mvm); 805 regd = iwl_mvm_get_current_regdomain(mvm, NULL);
806 if (IS_ERR_OR_NULL(regd)) 806 if (IS_ERR_OR_NULL(regd))
807 return -EIO; 807 return -EIO;
808 808
@@ -810,7 +810,7 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
810 !iwl_mvm_get_bios_mcc(mvm, mcc)) { 810 !iwl_mvm_get_bios_mcc(mvm, mcc)) {
811 kfree(regd); 811 kfree(regd);
812 regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, mcc, 812 regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, mcc,
813 MCC_SOURCE_BIOS); 813 MCC_SOURCE_BIOS, NULL);
814 if (IS_ERR_OR_NULL(regd)) 814 if (IS_ERR_OR_NULL(regd))
815 return -EIO; 815 return -EIO;
816 } 816 }
@@ -843,7 +843,7 @@ int iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm,
843 IWL_DEBUG_LAR(mvm, 843 IWL_DEBUG_LAR(mvm,
844 "RX: received chub update mcc cmd (mcc '%s' src %d)\n", 844 "RX: received chub update mcc cmd (mcc '%s' src %d)\n",
845 mcc, src); 845 mcc, src);
846 regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, mcc, src); 846 regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, mcc, src, NULL);
847 if (IS_ERR_OR_NULL(regd)) 847 if (IS_ERR_OR_NULL(regd))
848 return 0; 848 return 0;
849 849
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index c1de23cc07fd..7b555f6cc580 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -1272,6 +1272,10 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk)
1272 iwl_free_resp(&get_status_cmd); 1272 iwl_free_resp(&get_status_cmd);
1273out: 1273out:
1274 iwl_mvm_d0i3_enable_tx(mvm, qos_seq); 1274 iwl_mvm_d0i3_enable_tx(mvm, qos_seq);
1275
1276 /* the FW might have updated the regdomain */
1277 iwl_mvm_update_changed_regdom(mvm);
1278
1275 iwl_mvm_unref(mvm, IWL_MVM_REF_EXIT_WORK); 1279 iwl_mvm_unref(mvm, IWL_MVM_REF_EXIT_WORK);
1276 mutex_unlock(&mvm->mutex); 1280 mutex_unlock(&mvm->mutex);
1277} 1281}