diff mbox

[2/2] ath10k: add platform regulatory domain support

Message ID 1470140454-3899-3-git-send-email-bartosz.markowski@tieto.com (mailing list archive)
State Not Applicable
Delegated to: Kalle Valo
Headers show

Commit Message

Bartosz Markowski Aug. 2, 2016, 12:20 p.m. UTC
This overrides whatever regulatory the device
EEPROM contains and uses what the platform says
instead - in this implementation the ACPI driver.

In case the hint is not programmed or corrupted (0xffff)
the device falls back to the eeprom programmed settings.

Signed-off-by: Bartosz Markowski <bartosz.markowski@tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.h |   1 +
 drivers/net/wireless/ath/ath10k/mac.c  | 117 +++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/wmi.c  |   2 +-
 3 files changed, 119 insertions(+), 1 deletion(-)

Comments

Kalle Valo Sept. 12, 2016, 3:35 p.m. UTC | #1
Bartosz Markowski <bartosz.markowski@tieto.com> writes:

> This overrides whatever regulatory the device
> EEPROM contains and uses what the platform says
> instead - in this implementation the ACPI driver.
>
> In case the hint is not programmed or corrupted (0xffff)
> the device falls back to the eeprom programmed settings.
>
> Signed-off-by: Bartosz Markowski <bartosz.markowski@tieto.com>

[...]

> +#ifdef CONFIG_ACPI
> +#define WRD_METHOD "WRDD"
> +#define WRDD_WIFI  (0x07)
> +
> +static u32 ath10k_mac_wrdd_get_mcc(struct ath10k *ar, union acpi_object *wrdd)
> +{

I don't think the ifdef is really necessary, acpi.h should handle that
(hopefully). Also I changed the error handling to use standard error
values and changed the info messages to dbg, they are too spammy in my
opinion. Please check carefully my changes in the pending branch:

https://git.kernel.org/cgit/linux/kernel/git/kvalo/ath.git/commit/?h=pending&id=fe91745381ec3999d8de6dedb07b396c82539717
Bartosz Markowski Sept. 13, 2016, 1:57 p.m. UTC | #2
On 12 September 2016 at 17:35, Valo, Kalle <kvalo@qca.qualcomm.com> wrote:

[...]

> > +#ifdef CONFIG_ACPI
> > +#define WRD_METHOD "WRDD"
> > +#define WRDD_WIFI  (0x07)
> > +
> > +static u32 ath10k_mac_wrdd_get_mcc(struct ath10k *ar, union acpi_object *wrdd)
> > +{
>
> I don't think the ifdef is really necessary, acpi.h should handle that
> (hopefully). Also I changed the error handling to use standard error
> values and changed the info messages to dbg, they are too spammy in my
> opinion. Please check carefully my changes in the pending branch:
>
> https://git.kernel.org/cgit/linux/kernel/git/kvalo/ath.git/commit/?h=pending&id=fe91745381ec3999d8de6dedb07b396c82539717

I'm OK with the changes, I have not tried that though, except of
reviewing and compiling it (do not have access to the chromebook for
next few days). If you want to wait with it until I test it, it's fine
too.

Bartosz
Kalle Valo Sept. 14, 2016, 7:06 a.m. UTC | #3
Bartosz Markowski <bartosz.markowski@tieto.com> writes:

> On 12 September 2016 at 17:35, Valo, Kalle <kvalo@qca.qualcomm.com> wrote:
>
>> > +#ifdef CONFIG_ACPI
>> > +#define WRD_METHOD "WRDD"
>> > +#define WRDD_WIFI  (0x07)
>> > +
>> > +static u32 ath10k_mac_wrdd_get_mcc(struct ath10k *ar, union acpi_object *wrdd)
>> > +{
>>
>> I don't think the ifdef is really necessary, acpi.h should handle that
>> (hopefully). Also I changed the error handling to use standard error
>> values and changed the info messages to dbg, they are too spammy in my
>> opinion. Please check carefully my changes in the pending branch:
>>
>> https://git.kernel.org/cgit/linux/kernel/git/kvalo/ath.git/commit/?h=pending&id=fe91745381ec3999d8de6dedb07b396c82539717
>
> I'm OK with the changes, I have not tried that though, except of
> reviewing and compiling it (do not have access to the chromebook for
> next few days). If you want to wait with it until I test it, it's fine
> too.

Ok, I'll wait for few days in case you have time to test it.
Bartosz Markowski Oct. 3, 2016, 7:43 a.m. UTC | #4
On 14 September 2016 at 09:06, Valo, Kalle <kvalo@qca.qualcomm.com> wrote:
>
> Bartosz Markowski <bartosz.markowski@tieto.com> writes:
>
> > On 12 September 2016 at 17:35, Valo, Kalle <kvalo@qca.qualcomm.com> wrote:
> >
> >> > +#ifdef CONFIG_ACPI
> >> > +#define WRD_METHOD "WRDD"
> >> > +#define WRDD_WIFI  (0x07)
> >> > +
> >> > +static u32 ath10k_mac_wrdd_get_mcc(struct ath10k *ar, union acpi_object *wrdd)
> >> > +{
> >>
> >> I don't think the ifdef is really necessary, acpi.h should handle that
> >> (hopefully). Also I changed the error handling to use standard error
> >> values and changed the info messages to dbg, they are too spammy in my
> >> opinion. Please check carefully my changes in the pending branch:
> >>
> >> https://git.kernel.org/cgit/linux/kernel/git/kvalo/ath.git/commit/?h=pending&id=fe91745381ec3999d8de6dedb07b396c82539717
> >
> > I'm OK with the changes, I have not tried that though, except of
> > reviewing and compiling it (do not have access to the chromebook for
> > next few days). If you want to wait with it until I test it, it's fine
> > too.
>
> Ok, I'll wait for few days in case you have time to test it.


Sorry, it took so long. I've final check this and can confirm the patch.

Bartosz
Kalle Valo Oct. 3, 2016, 7:52 a.m. UTC | #5
Bartosz Markowski <bartosz.markowski@tieto.com> writes:

> On 14 September 2016 at 09:06, Valo, Kalle <kvalo@qca.qualcomm.com> wrote:
>>
>> Bartosz Markowski <bartosz.markowski@tieto.com> writes:
>>
>> > On 12 September 2016 at 17:35, Valo, Kalle <kvalo@qca.qualcomm.com> wrote:
>> >
>> >> > +#ifdef CONFIG_ACPI
>> >> > +#define WRD_METHOD "WRDD"
>> >> > +#define WRDD_WIFI  (0x07)
>> >> > +
>> >> > +static u32 ath10k_mac_wrdd_get_mcc(struct ath10k *ar, union acpi_object *wrdd)
>> >> > +{
>> >>
>> >> I don't think the ifdef is really necessary, acpi.h should handle that
>> >> (hopefully). Also I changed the error handling to use standard error
>> >> values and changed the info messages to dbg, they are too spammy in my
>> >> opinion. Please check carefully my changes in the pending branch:
>> >>
>> >> https://git.kernel.org/cgit/linux/kernel/git/kvalo/ath.git/commit/?h=pending&id=fe91745381ec3999d8de6dedb07b396c82539717
>> >
>> > I'm OK with the changes, I have not tried that though, except of
>> > reviewing and compiling it (do not have access to the chromebook for
>> > next few days). If you want to wait with it until I test it, it's fine
>> > too.
>>
>> Ok, I'll wait for few days in case you have time to test it.
>
>
> Sorry, it took so long. I've final check this and can confirm the patch.

Thanks, I'll apply the patch soon. Do note that I changed more of the
warnings messages to debug level.
diff mbox

Patch

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 30ae5bf81611..1df7c600a2bb 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -692,6 +692,7 @@  struct ath10k {
 	u32 phy_capability;
 	u32 hw_min_tx_power;
 	u32 hw_max_tx_power;
+	u32 hw_eeprom_rd;
 	u32 ht_cap_info;
 	u32 vht_cap_info;
 	u32 num_rf_chains;
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index fb8e38df9446..b6b8a0b2046b 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -19,6 +19,7 @@ 
 
 #include <net/mac80211.h>
 #include <linux/etherdevice.h>
+#include <linux/acpi.h>
 
 #include "hif.h"
 #include "core.h"
@@ -7751,6 +7752,116 @@  struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id)
 	return arvif_iter.arvif;
 }
 
+#ifdef CONFIG_ACPI
+#define WRD_METHOD "WRDD"
+#define WRDD_WIFI  (0x07)
+
+static u32 ath10k_mac_wrdd_get_mcc(struct ath10k *ar, union acpi_object *wrdd)
+{
+	union acpi_object *mcc_pkg;
+	union acpi_object *domain_type;
+	union acpi_object *mcc_value;
+	u32 i;
+
+	if (wrdd->type != ACPI_TYPE_PACKAGE ||
+	    wrdd->package.count < 2 ||
+	    wrdd->package.elements[0].type != ACPI_TYPE_INTEGER ||
+	    wrdd->package.elements[0].integer.value != 0) {
+		ath10k_warn(ar, "ignoring malformed/unsupported wrdd structure\n");
+		return 0;
+	}
+
+	for (i = 1; i < wrdd->package.count; ++i) {
+		mcc_pkg = &wrdd->package.elements[i];
+
+		if (mcc_pkg->type != ACPI_TYPE_PACKAGE)
+			continue;
+		if (mcc_pkg->package.count < 2)
+			continue;
+		if (mcc_pkg->package.elements[0].type != ACPI_TYPE_INTEGER ||
+		    mcc_pkg->package.elements[1].type != ACPI_TYPE_INTEGER)
+			continue;
+
+		domain_type = &mcc_pkg->package.elements[0];
+		if (domain_type->integer.value != WRDD_WIFI)
+			continue;
+
+		mcc_value = &mcc_pkg->package.elements[1];
+		return mcc_value->integer.value;
+	}
+	return 0;
+}
+
+static u16 ath10k_mac_get_wrdd_regulatory(struct ath10k *ar)
+{
+	u16 rd;
+	acpi_handle root_handle;
+	acpi_handle handle;
+	struct acpi_buffer wrdd = {ACPI_ALLOCATE_BUFFER, NULL};
+	acpi_status status;
+	u32 alpha2_code;
+	char alpha2[3];
+	struct pci_dev *pdev = to_pci_dev(ar->dev);
+
+	root_handle = ACPI_HANDLE(&pdev->dev);
+	if (!root_handle) {
+		ath10k_warn(ar, "failed to get root port acpi handle\n");
+		return -1;
+	}
+
+	status = acpi_get_handle(root_handle, (acpi_string)WRD_METHOD, &handle);
+	if (ACPI_FAILURE(status)) {
+		ath10k_warn(ar, "failed to get wrd method %d\n", status);
+		return -1;
+	}
+
+	status = acpi_evaluate_object(handle, NULL, NULL, &wrdd);
+	if (ACPI_FAILURE(status)) {
+		ath10k_warn(ar, "failed to call wrdc %d\n", status);
+		return -1;
+	}
+
+	alpha2_code = ath10k_mac_wrdd_get_mcc(ar, wrdd.pointer);
+	kfree(wrdd.pointer);
+	if (!alpha2_code)
+		return -1;
+
+	alpha2[0] = (alpha2_code >> 8) & 0xff;
+	alpha2[1] = (alpha2_code >> 0) & 0xff;
+	alpha2[2] = '\0';
+
+	ath10k_info(ar, "regulatory hint from WRDD (alpha2-code): %s\n", alpha2);
+
+	rd = ath_regd_find_country_by_name(alpha2);
+	if (rd == 0xffff)
+		return rd;
+
+	rd |= COUNTRY_ERD_FLAG;
+	return rd;
+}
+
+#else
+static u16 ath10k_mac_get_wrdd_regulatory(struct ath10k *ar)
+{
+	/* fallback to default eeprom settings */
+	return -1;
+}
+#endif
+
+static int ath10k_mac_init_rd(struct ath10k *ar)
+{
+	u16 rd;
+
+	rd = ath10k_mac_get_wrdd_regulatory(ar);
+	if (rd == 0xffff) {
+		ath10k_info(ar, "fallback to eeprom programmed regulatory settings\n");
+		rd = ar->hw_eeprom_rd;
+	}
+
+	ar->ath_common.regulatory.current_rd = rd;
+	return 0;
+}
+
 int ath10k_mac_register(struct ath10k *ar)
 {
 	static const u32 cipher_suites[] = {
@@ -7974,6 +8085,12 @@  int ath10k_mac_register(struct ath10k *ar)
 		      ar->running_fw->fw_file.fw_features))
 		ar->ops->wake_tx_queue = NULL;
 
+	ret = ath10k_mac_init_rd(ar);
+	if (ret) {
+		ath10k_err(ar, "failed to derive regdom: %d\n", ret);
+		goto err_dfs_detector_exit;
+	}
+
 	ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy,
 			    ath10k_reg_notifier);
 	if (ret) {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 169cd2e783eb..e9aadc85ad1b 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -4635,7 +4635,7 @@  static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
 	ar->fw_version_build = (__le32_to_cpu(arg.sw_ver1) & 0x0000ffff);
 	ar->phy_capability = __le32_to_cpu(arg.phy_capab);
 	ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains);
-	ar->ath_common.regulatory.current_rd = __le32_to_cpu(arg.eeprom_rd);
+	ar->hw_eeprom_rd = __le32_to_cpu(arg.eeprom_rd);
 
 	ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
 			arg.service_map, arg.service_map_len);