aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKalle Valo <kvalo@qca.qualcomm.com>2012-07-19 09:00:56 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2012-10-24 04:49:37 -0400
commit84841ba29b1f55fb09703408477f097c7f8952f8 (patch)
tree9bcf8de2def815dd2a4d3a0a534e76b9ccb7fdd2
parent11f0bfcf73f4a90c8c0e0b244a272379b376adb1 (diff)
ath6kl: add support for changing contry code
To make it possible to change the country code from user space via nl80211 add handler for reg_notifier. The feature is only enabled when built time option CONFIG_ATH6KL_REGDOMAIN is enabled, which again depends on CFG80211_CERTIFICATION_ONUS for certication purposes. Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r--drivers/net/wireless/ath/ath6kl/Kconfig9
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c47
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h3
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c17
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h6
5 files changed, 82 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig
index d755a5e7ed20..26c4b7220859 100644
--- a/drivers/net/wireless/ath/ath6kl/Kconfig
+++ b/drivers/net/wireless/ath/ath6kl/Kconfig
@@ -30,3 +30,12 @@ config ATH6KL_DEBUG
30 depends on ATH6KL 30 depends on ATH6KL
31 ---help--- 31 ---help---
32 Enables debug support 32 Enables debug support
33
34config ATH6KL_REGDOMAIN
35 bool "Atheros ath6kl regdomain support"
36 depends on ATH6KL
37 depends on CFG80211_CERTIFICATION_ONUS
38 ---help---
39 Enabling this makes it possible to change the regdomain in
40 the firmware. This can be only enabled if regulatory requirements
41 are taken into account.
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 4f538f0027f2..f620af5e0dbb 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -3458,6 +3458,49 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
3458 ath6kl_cfg80211_stop(vif); 3458 ath6kl_cfg80211_stop(vif);
3459} 3459}
3460 3460
3461static int ath6kl_cfg80211_reg_notify(struct wiphy *wiphy,
3462 struct regulatory_request *request)
3463{
3464 struct ath6kl *ar = wiphy_priv(wiphy);
3465 u32 rates[IEEE80211_NUM_BANDS];
3466 int ret, i;
3467
3468 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
3469 "cfg reg_notify %c%c%s%s initiator %d\n",
3470 request->alpha2[0], request->alpha2[1],
3471 request->intersect ? " intersect" : "",
3472 request->processed ? " processed" : "",
3473 request->initiator);
3474
3475 ret = ath6kl_wmi_set_regdomain_cmd(ar->wmi, request->alpha2);
3476 if (ret) {
3477 ath6kl_err("failed to set regdomain: %d\n", ret);
3478 return ret;
3479 }
3480
3481 /*
3482 * Firmware will apply the regdomain change only after a scan is
3483 * issued and it will send a WMI_REGDOMAIN_EVENTID when it has been
3484 * changed.
3485 */
3486
3487 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
3488 if (wiphy->bands[i])
3489 rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
3490
3491
3492 ret = ath6kl_wmi_beginscan_cmd(ar->wmi, 0, WMI_LONG_SCAN, false,
3493 false, 0, ATH6KL_FG_SCAN_INTERVAL,
3494 0, NULL, false, rates);
3495 if (ret) {
3496 ath6kl_err("failed to start scan for a regdomain change: %d\n",
3497 ret);
3498 return ret;
3499 }
3500
3501 return 0;
3502}
3503
3461static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif) 3504static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif)
3462{ 3505{
3463 vif->aggr_cntxt = aggr_init(vif); 3506 vif->aggr_cntxt = aggr_init(vif);
@@ -3590,6 +3633,10 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
3590 BIT(NL80211_IFTYPE_P2P_CLIENT); 3633 BIT(NL80211_IFTYPE_P2P_CLIENT);
3591 } 3634 }
3592 3635
3636 if (config_enabled(CONFIG_ATH6KL_REGDOMAIN) &&
3637 test_bit(ATH6KL_FW_CAPABILITY_REGDOMAIN, ar->fw_capabilities))
3638 wiphy->reg_notifier = ath6kl_cfg80211_reg_notify;
3639
3593 /* max num of ssids that can be probed during scanning */ 3640 /* max num of ssids that can be probed during scanning */
3594 wiphy->max_scan_ssids = MAX_PROBED_SSIDS; 3641 wiphy->max_scan_ssids = MAX_PROBED_SSIDS;
3595 3642
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index a754a153cc81..eb86b315adff 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -124,6 +124,9 @@ enum ath6kl_fw_capability {
124 /* Firmware supports TX error rate notification */ 124 /* Firmware supports TX error rate notification */
125 ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY, 125 ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY,
126 126
127 /* supports WMI_SET_REGDOMAIN_CMDID command */
128 ATH6KL_FW_CAPABILITY_REGDOMAIN,
129
127 /* this needs to be last */ 130 /* this needs to be last */
128 ATH6KL_FW_CAPABILITY_MAX, 131 ATH6KL_FW_CAPABILITY_MAX,
129}; 132};
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 05cc871f8244..cf91348fdbdb 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -3216,6 +3216,23 @@ int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enhance)
3216 return ret; 3216 return ret;
3217} 3217}
3218 3218
3219int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2)
3220{
3221 struct sk_buff *skb;
3222 struct wmi_set_regdomain_cmd *cmd;
3223
3224 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
3225 if (!skb)
3226 return -ENOMEM;
3227
3228 cmd = (struct wmi_set_regdomain_cmd *) skb->data;
3229 memcpy(cmd->iso_name, alpha2, 2);
3230
3231 return ath6kl_wmi_cmd_send(wmi, 0, skb,
3232 WMI_SET_REGDOMAIN_CMDID,
3233 NO_SYNC_WMIFLAG);
3234}
3235
3219s32 ath6kl_wmi_get_rate(s8 rate_index) 3236s32 ath6kl_wmi_get_rate(s8 rate_index)
3220{ 3237{
3221 if (rate_index == RATE_AUTO) 3238 if (rate_index == RATE_AUTO)
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index 5166a8e64927..1d510bae1558 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -1042,6 +1042,11 @@ struct wmi_sta_bmiss_enhance_cmd {
1042 u8 enable; 1042 u8 enable;
1043} __packed; 1043} __packed;
1044 1044
1045struct wmi_set_regdomain_cmd {
1046 u8 length;
1047 u8 iso_name[2];
1048} __packed;
1049
1045/* WMI_SET_POWER_MODE_CMDID */ 1050/* WMI_SET_POWER_MODE_CMDID */
1046enum wmi_power_mode { 1051enum wmi_power_mode {
1047 REC_POWER = 0x01, 1052 REC_POWER = 0x01,
@@ -2640,6 +2645,7 @@ int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
2640int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enable); 2645int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enable);
2641int ath6kl_wmi_set_txe_notify(struct wmi *wmi, u8 idx, 2646int ath6kl_wmi_set_txe_notify(struct wmi *wmi, u8 idx,
2642 u32 rate, u32 pkts, u32 intvl); 2647 u32 rate, u32 pkts, u32 intvl);
2648int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2);
2643 2649
2644/* AP mode uAPSD */ 2650/* AP mode uAPSD */
2645int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable); 2651int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable);