aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2014-03-05 05:26:15 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2015-03-12 03:57:25 -0400
commit88931cc92872151d53f86720c848e469574ce7f0 (patch)
tree2c02c92b77dc1d3ae0ec4c4454a4134b15cd264f
parenta76f3bfe016dbda161f9d31cc5cbdd9238d13488 (diff)
iwlwifi: mvm: LAR: Add chub mcc change notify command
Chub (Communication Hub, CommsHUB) is a HW component that connects to the cellular and connectivity cores that gets updates of mcc changes, and then notifies the FW directly of any mcc change. The ucode notifies the driver (via this command) that it should ask for an mcc update, and the driver sends the ucode the update mcc command to set the updated regulatory info. Signed-off-by: Matti Gottlieb <matti.gottlieb@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api.h20
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c56
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h7
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/nvm.c26
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c1
5 files changed, 109 insertions, 1 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index 85afede5c7c4..c4b59ecb3606 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -214,6 +214,7 @@ enum {
214 214
215 /* Location Aware Regulatory */ 215 /* Location Aware Regulatory */
216 MCC_UPDATE_CMD = 0xc8, 216 MCC_UPDATE_CMD = 0xc8,
217 MCC_CHUB_UPDATE_CMD = 0xc9,
217 218
218 MARKER_CMD = 0xcb, 219 MARKER_CMD = 0xcb,
219 220
@@ -1715,6 +1716,25 @@ struct iwl_mcc_update_resp {
1715 __le32 channels[0]; 1716 __le32 channels[0];
1716} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S */ 1717} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S */
1717 1718
1719/**
1720 * struct iwl_mcc_chub_notif - chub notifies of mcc change
1721 * (MCC_CHUB_UPDATE_CMD = 0xc9)
1722 * The Chub (Communication Hub, CommsHUB) is a HW component that connects to
1723 * the cellular and connectivity cores that gets updates of the mcc, and
1724 * notifies the ucode directly of any mcc change.
1725 * The ucode requests the driver to request the device to update geographic
1726 * regulatory profile according to the given MCC (Mobile Country Code).
1727 * The MCC is two letter-code, ascii upper case[A-Z] or '00' for world domain.
1728 * 'ZZ' MCC will be used to switch to NVM default profile; in this case, the
1729 * MCC in the cmd response will be the relevant MCC in the NVM.
1730 * @mcc: given mobile country code
1731 * @reserved: reserved for alignment
1732 */
1733struct iwl_mcc_chub_notif {
1734 u16 mcc;
1735 u16 reserved1;
1736} __packed; /* LAR_MCC_NOTIFY_S */
1737
1718enum iwl_mcc_update_status { 1738enum iwl_mcc_update_status {
1719 MCC_RESP_NEW_CHAN_PROFILE, 1739 MCC_RESP_NEW_CHAN_PROFILE,
1720 MCC_RESP_SAME_CHAN_PROFILE, 1740 MCC_RESP_SAME_CHAN_PROFILE,
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 204255423d99..0da8787aa25b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -86,6 +86,7 @@
86#include "iwl-fw-error-dump.h" 86#include "iwl-fw-error-dump.h"
87#include "iwl-prph.h" 87#include "iwl-prph.h"
88#include "iwl-csr.h" 88#include "iwl-csr.h"
89#include "iwl-nvm-parse.h"
89 90
90static const struct ieee80211_iface_limit iwl_mvm_limits[] = { 91static const struct ieee80211_iface_limit iwl_mvm_limits[] = {
91 { 92 {
@@ -301,6 +302,49 @@ static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm)
301 } 302 }
302} 303}
303 304
305struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
306 const char *alpha2)
307{
308 struct ieee80211_regdomain *regd = NULL;
309 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
310 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
311 struct iwl_mcc_update_resp *resp;
312
313 IWL_DEBUG_LAR(mvm, "Getting regdomain data for %s from FW\n", alpha2);
314
315 mutex_lock(&mvm->mutex);
316
317 /* change "99" to "ZZ" for the FW */
318 if (alpha2[0] == '9' && alpha2[1] == '9')
319 alpha2 = "ZZ";
320
321 resp = iwl_mvm_update_mcc(mvm, alpha2);
322 if (IS_ERR_OR_NULL(resp)) {
323 IWL_DEBUG_LAR(mvm, "Could not get update from FW %d\n",
324 PTR_RET(resp));
325 goto out_unlock;
326 }
327
328 regd = iwl_parse_nvm_mcc_info(mvm->trans->dev,
329 __le32_to_cpu(resp->n_channels),
330 resp->channels,
331 __le16_to_cpu(resp->mcc));
332 kfree(resp);
333 if (IS_ERR_OR_NULL(regd)) {
334 IWL_DEBUG_LAR(mvm, "Could not get parse update from FW %d\n",
335 PTR_RET(resp));
336 goto out_unlock;
337 }
338
339 IWL_DEBUG_LAR(mvm, "setting alpha2 from FW to %s (0x%x, 0x%x)\n",
340 regd->alpha2, regd->alpha2[0], regd->alpha2[1]);
341 mvm->lar_regdom_set = true;
342
343out_unlock:
344 mutex_unlock(&mvm->mutex);
345 return regd;
346}
347
304int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) 348int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
305{ 349{
306 struct ieee80211_hw *hw = mvm->hw; 350 struct ieee80211_hw *hw = mvm->hw;
@@ -2245,6 +2289,12 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
2245 2289
2246 mutex_lock(&mvm->mutex); 2290 mutex_lock(&mvm->mutex);
2247 2291
2292 if (iwl_mvm_is_lar_supported(mvm) && !mvm->lar_regdom_set) {
2293 IWL_ERR(mvm, "scan while LAR regdomain is not set\n");
2294 ret = -EBUSY;
2295 goto out;
2296 }
2297
2248 if (mvm->scan_status != IWL_MVM_SCAN_NONE) { 2298 if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
2249 ret = -EBUSY; 2299 ret = -EBUSY;
2250 goto out; 2300 goto out;
@@ -2583,6 +2633,12 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
2583 2633
2584 mutex_lock(&mvm->mutex); 2634 mutex_lock(&mvm->mutex);
2585 2635
2636 if (iwl_mvm_is_lar_supported(mvm) && !mvm->lar_regdom_set) {
2637 IWL_ERR(mvm, "sched-scan while LAR regdomain is not set\n");
2638 ret = -EBUSY;
2639 goto out;
2640 }
2641
2586 if (!vif->bss_conf.idle) { 2642 if (!vif->bss_conf.idle) {
2587 ret = -EBUSY; 2643 ret = -EBUSY;
2588 goto out; 2644 goto out;
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index b31f43c7cf80..df5a2286b409 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -810,6 +810,8 @@ struct iwl_mvm {
810 /* system time of last beacon (for AP/GO interface) */ 810 /* system time of last beacon (for AP/GO interface) */
811 u32 ap_last_beacon_gp2; 811 u32 ap_last_beacon_gp2;
812 812
813 bool lar_regdom_set;
814
813 u8 low_latency_agg_frame_limit; 815 u8 low_latency_agg_frame_limit;
814 816
815 /* TDLS channel switch data */ 817 /* TDLS channel switch data */
@@ -1398,6 +1400,11 @@ int iwl_mvm_get_temp(struct iwl_mvm *mvm);
1398struct iwl_mcc_update_resp * 1400struct iwl_mcc_update_resp *
1399iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2); 1401iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2);
1400int iwl_mvm_init_mcc(struct iwl_mvm *mvm); 1402int iwl_mvm_init_mcc(struct iwl_mvm *mvm);
1403int iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm,
1404 struct iwl_rx_cmd_buffer *rxb,
1405 struct iwl_device_cmd *cmd);
1406struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
1407 const char *alpha2);
1401 1408
1402/* smart fifo */ 1409/* smart fifo */
1403int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 1410int 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 907e231f2c5c..b88b4cd07a22 100644
--- a/drivers/net/wireless/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c
@@ -689,6 +689,30 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
689 * unknown-country "99" code. This will also clear the "custom reg" 689 * unknown-country "99" code. This will also clear the "custom reg"
690 * flag and allow regdomain changes. It will happen after init since 690 * flag and allow regdomain changes. It will happen after init since
691 * RTNL is required. 691 * RTNL is required.
692 * Disallow scans that might crash the FW while the LAR regdomain
693 * is not set.
692 */ 694 */
693 return regulatory_hint(mvm->hw->wiphy, "99"); 695 mvm->lar_regdom_set = false;
696 return 0;
697}
698
699int iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm,
700 struct iwl_rx_cmd_buffer *rxb,
701 struct iwl_device_cmd *cmd)
702{
703 struct iwl_rx_packet *pkt = rxb_addr(rxb);
704 struct iwl_mcc_chub_notif *notif = (void *)pkt->data;
705 char mcc[3];
706
707 if (WARN_ON_ONCE(!iwl_mvm_is_lar_supported(mvm)))
708 return -EOPNOTSUPP;
709
710 mcc[0] = notif->mcc >> 8;
711 mcc[1] = notif->mcc & 0xff;
712 mcc[2] = '\0';
713
714 IWL_DEBUG_LAR(mvm,
715 "RX: received chub update mcc command (mcc 0x%x '%s')\n",
716 notif->mcc, mcc);
717 return 0;
694} 718}
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index 72b8e19004c4..1072f45720d6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -234,6 +234,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
234 iwl_mvm_rx_ant_coupling_notif, true), 234 iwl_mvm_rx_ant_coupling_notif, true),
235 235
236 RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false), 236 RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false),
237 RX_HANDLER(MCC_CHUB_UPDATE_CMD, iwl_mvm_rx_chub_update_mcc, false),
237 238
238 RX_HANDLER(EOSP_NOTIFICATION, iwl_mvm_rx_eosp_notif, false), 239 RX_HANDLER(EOSP_NOTIFICATION, iwl_mvm_rx_eosp_notif, false),
239 240