]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.2-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 20 Aug 2019 16:47:39 +0000 (09:47 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 20 Aug 2019 16:47:39 +0000 (09:47 -0700)
added patches:
iwlwifi-add-support-for-sar-south-korea-limitation.patch

queue-5.2/iwlwifi-add-support-for-sar-south-korea-limitation.patch [new file with mode: 0644]
queue-5.2/series

diff --git a/queue-5.2/iwlwifi-add-support-for-sar-south-korea-limitation.patch b/queue-5.2/iwlwifi-add-support-for-sar-south-korea-limitation.patch
new file mode 100644 (file)
index 0000000..11d8c57
--- /dev/null
@@ -0,0 +1,318 @@
+From 0c3d7282233c7b02c74400b49981d6fff1d683a8 Mon Sep 17 00:00:00 2001
+From: Haim Dreyfuss <haim.dreyfuss@intel.com>
+Date: Wed, 27 Feb 2019 16:43:45 +0200
+Subject: iwlwifi: Add support for SAR South Korea limitation
+
+From: Haim Dreyfuss <haim.dreyfuss@intel.com>
+
+commit 0c3d7282233c7b02c74400b49981d6fff1d683a8 upstream.
+
+South Korea is adding a more strict SAR limit called "Limb SAR".
+Currently, WGDS SAR offset group 3 is not used (not mapped to any country).
+In order to be able to comply with South Korea new restriction:
+- OEM will use WGDS SAR offset group 3 to South Korea limitation.
+- OEM will change WGDS revision to 1 (currently latest revision is 0)
+       to notify that Korea Limb SAR applied.
+- Driver will read the WGDS table and pass the values to FW (as usual)
+- Driver will pass to FW an indication that Korea Limb SAR is applied
+       in case table revision is 1.
+
+Signed-off-by: Haim Dreyfuss <haim.dreyfuss@intel.com>
+Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/intel/iwlwifi/fw/acpi.c      |   28 ++++++-----
+ drivers/net/wireless/intel/iwlwifi/fw/acpi.h      |    5 +-
+ drivers/net/wireless/intel/iwlwifi/fw/api/power.h |   12 ++++
+ drivers/net/wireless/intel/iwlwifi/fw/file.h      |    3 +
+ drivers/net/wireless/intel/iwlwifi/mvm/fw.c       |   55 ++++++++++++++++------
+ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h      |    1 
+ 6 files changed, 76 insertions(+), 28 deletions(-)
+
+--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
++++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+@@ -97,7 +97,7 @@ IWL_EXPORT_SYMBOL(iwl_acpi_get_object);
+ union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
+                                        union acpi_object *data,
+-                                       int data_size)
++                                       int data_size, int *tbl_rev)
+ {
+       int i;
+       union acpi_object *wifi_pkg;
+@@ -113,16 +113,19 @@ union acpi_object *iwl_acpi_get_wifi_pkg
+       /*
+        * We need at least two packages, one for the revision and one
+        * for the data itself.  Also check that the revision is valid
+-       * (i.e. it is an integer set to 0).
++       * (i.e. it is an integer smaller than 2, as we currently support only
++       * 2 revisions).
+        */
+       if (data->type != ACPI_TYPE_PACKAGE ||
+           data->package.count < 2 ||
+           data->package.elements[0].type != ACPI_TYPE_INTEGER ||
+-          data->package.elements[0].integer.value != 0) {
++          data->package.elements[0].integer.value > 1) {
+               IWL_DEBUG_DEV_RADIO(dev, "Unsupported packages structure\n");
+               return ERR_PTR(-EINVAL);
+       }
++      *tbl_rev = data->package.elements[0].integer.value;
++
+       /* loop through all the packages to find the one for WiFi */
+       for (i = 1; i < data->package.count; i++) {
+               union acpi_object *domain;
+@@ -151,14 +154,15 @@ int iwl_acpi_get_mcc(struct device *dev,
+ {
+       union acpi_object *wifi_pkg, *data;
+       u32 mcc_val;
+-      int ret;
++      int ret, tbl_rev;
+       data = iwl_acpi_get_object(dev, ACPI_WRDD_METHOD);
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+-      wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_WRDD_WIFI_DATA_SIZE);
+-      if (IS_ERR(wifi_pkg)) {
++      wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_WRDD_WIFI_DATA_SIZE,
++                                       &tbl_rev);
++      if (IS_ERR(wifi_pkg) || tbl_rev != 0) {
+               ret = PTR_ERR(wifi_pkg);
+               goto out_free;
+       }
+@@ -185,6 +189,7 @@ u64 iwl_acpi_get_pwr_limit(struct device
+ {
+       union acpi_object *data, *wifi_pkg;
+       u64 dflt_pwr_limit;
++      int tbl_rev;
+       data = iwl_acpi_get_object(dev, ACPI_SPLC_METHOD);
+       if (IS_ERR(data)) {
+@@ -193,8 +198,8 @@ u64 iwl_acpi_get_pwr_limit(struct device
+       }
+       wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data,
+-                                       ACPI_SPLC_WIFI_DATA_SIZE);
+-      if (IS_ERR(wifi_pkg) ||
++                                       ACPI_SPLC_WIFI_DATA_SIZE, &tbl_rev);
++      if (IS_ERR(wifi_pkg) || tbl_rev != 0 ||
+           wifi_pkg->package.elements[1].integer.value != ACPI_TYPE_INTEGER) {
+               dflt_pwr_limit = 0;
+               goto out_free;
+@@ -211,14 +216,15 @@ IWL_EXPORT_SYMBOL(iwl_acpi_get_pwr_limit
+ int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk)
+ {
+       union acpi_object *wifi_pkg, *data;
+-      int ret;
++      int ret, tbl_rev;
+       data = iwl_acpi_get_object(dev, ACPI_ECKV_METHOD);
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+-      wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_ECKV_WIFI_DATA_SIZE);
+-      if (IS_ERR(wifi_pkg)) {
++      wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_ECKV_WIFI_DATA_SIZE,
++                                       &tbl_rev);
++      if (IS_ERR(wifi_pkg) || tbl_rev != 0) {
+               ret = PTR_ERR(wifi_pkg);
+               goto out_free;
+       }
+--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
++++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
+@@ -97,7 +97,7 @@
+ void *iwl_acpi_get_object(struct device *dev, acpi_string method);
+ union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
+                                        union acpi_object *data,
+-                                       int data_size);
++                                       int data_size, int *tbl_rev);
+ /**
+  * iwl_acpi_get_mcc - read MCC from ACPI, if available
+@@ -131,7 +131,8 @@ static inline void *iwl_acpi_get_object(
+ static inline union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
+                                                      union acpi_object *data,
+-                                                     int data_size)
++                                                     int data_size,
++                                                     int *tbl_rev)
+ {
+       return ERR_PTR(-ENOENT);
+ }
+--- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
++++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
+@@ -420,13 +420,25 @@ struct iwl_per_chain_offset_group {
+ } __packed; /* PER_CHAIN_LIMIT_OFFSET_GROUP_S_VER_1 */
+ /**
++ * struct iwl_geo_tx_power_profile_cmd_v1 - struct for GEO_TX_POWER_LIMIT cmd.
++ * @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
++ * @table: offset profile per band.
++ */
++struct iwl_geo_tx_power_profiles_cmd_v1 {
++      __le32 ops;
++      struct iwl_per_chain_offset_group table[IWL_NUM_GEO_PROFILES];
++} __packed; /* GEO_TX_POWER_LIMIT_VER_1 */
++
++/**
+  * struct iwl_geo_tx_power_profile_cmd - struct for GEO_TX_POWER_LIMIT cmd.
+  * @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
+  * @table: offset profile per band.
++ * @table_revision: BIOS table revision.
+  */
+ struct iwl_geo_tx_power_profiles_cmd {
+       __le32 ops;
+       struct iwl_per_chain_offset_group table[IWL_NUM_GEO_PROFILES];
++      __le32 table_revision;
+ } __packed; /* GEO_TX_POWER_LIMIT */
+ /**
+--- a/drivers/net/wireless/intel/iwlwifi/fw/file.h
++++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h
+@@ -286,6 +286,8 @@ typedef unsigned int __bitwise iwl_ucode
+  *    SCAN_OFFLOAD_PROFILES_QUERY_RSP_S.
+  * @IWL_UCODE_TLV_API_MBSSID_HE: This ucode supports v2 of
+  *    STA_CONTEXT_DOT11AX_API_S
++ * @IWL_UCODE_TLV_CAPA_SAR_TABLE_VER: This ucode supports different sar
++ *    version tables.
+  *
+  * @NUM_IWL_UCODE_TLV_API: number of bits used
+  */
+@@ -318,6 +320,7 @@ enum iwl_ucode_tlv_api {
+       IWL_UCODE_TLV_API_MBSSID_HE             = (__force iwl_ucode_tlv_api_t)52,
+       IWL_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE   = (__force iwl_ucode_tlv_api_t)53,
+       IWL_UCODE_TLV_API_FTM_RTT_ACCURACY      = (__force iwl_ucode_tlv_api_t)54,
++      IWL_UCODE_TLV_API_SAR_TABLE_VER         = (__force iwl_ucode_tlv_api_t)55,
+       NUM_IWL_UCODE_TLV_API
+ #ifdef __CHECKER__
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+@@ -682,15 +682,15 @@ static int iwl_mvm_sar_get_wrds_table(st
+ {
+       union acpi_object *wifi_pkg, *table, *data;
+       bool enabled;
+-      int ret;
++      int ret, tbl_rev;
+       data = iwl_acpi_get_object(mvm->dev, ACPI_WRDS_METHOD);
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+       wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
+-                                       ACPI_WRDS_WIFI_DATA_SIZE);
+-      if (IS_ERR(wifi_pkg)) {
++                                       ACPI_WRDS_WIFI_DATA_SIZE, &tbl_rev);
++      if (IS_ERR(wifi_pkg) || tbl_rev != 0) {
+               ret = PTR_ERR(wifi_pkg);
+               goto out_free;
+       }
+@@ -719,15 +719,15 @@ static int iwl_mvm_sar_get_ewrd_table(st
+ {
+       union acpi_object *wifi_pkg, *data;
+       bool enabled;
+-      int i, n_profiles, ret;
++      int i, n_profiles, ret, tbl_rev;
+       data = iwl_acpi_get_object(mvm->dev, ACPI_EWRD_METHOD);
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+       wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
+-                                       ACPI_EWRD_WIFI_DATA_SIZE);
+-      if (IS_ERR(wifi_pkg)) {
++                                       ACPI_EWRD_WIFI_DATA_SIZE, &tbl_rev);
++      if (IS_ERR(wifi_pkg) || tbl_rev != 0) {
+               ret = PTR_ERR(wifi_pkg);
+               goto out_free;
+       }
+@@ -778,7 +778,7 @@ out_free:
+ static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
+ {
+       union acpi_object *wifi_pkg, *data;
+-      int i, j, ret;
++      int i, j, ret, tbl_rev;
+       int idx = 1;
+       data = iwl_acpi_get_object(mvm->dev, ACPI_WGDS_METHOD);
+@@ -786,12 +786,13 @@ static int iwl_mvm_sar_get_wgds_table(st
+               return PTR_ERR(data);
+       wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
+-                                       ACPI_WGDS_WIFI_DATA_SIZE);
+-      if (IS_ERR(wifi_pkg)) {
++                                       ACPI_WGDS_WIFI_DATA_SIZE, &tbl_rev);
++      if (IS_ERR(wifi_pkg) || tbl_rev > 1) {
+               ret = PTR_ERR(wifi_pkg);
+               goto out_free;
+       }
++      mvm->geo_rev = tbl_rev;
+       for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
+               for (j = 0; j < ACPI_GEO_TABLE_SIZE; j++) {
+                       union acpi_object *entry;
+@@ -894,15 +895,29 @@ int iwl_mvm_get_sar_geo_profile(struct i
+ {
+       struct iwl_geo_tx_power_profiles_resp *resp;
+       int ret;
++      u16 len;
++      void *data;
++      struct iwl_geo_tx_power_profiles_cmd geo_cmd;
++      struct iwl_geo_tx_power_profiles_cmd_v1 geo_cmd_v1;
++      struct iwl_host_cmd cmd;
++
++      if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
++              geo_cmd.ops =
++                      cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE);
++              len = sizeof(geo_cmd);
++              data = &geo_cmd;
++      } else {
++              geo_cmd_v1.ops =
++                      cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE);
++              len = sizeof(geo_cmd_v1);
++              data = &geo_cmd_v1;
++      }
+-      struct iwl_geo_tx_power_profiles_cmd geo_cmd = {
+-              .ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE),
+-      };
+-      struct iwl_host_cmd cmd = {
++      cmd = (struct iwl_host_cmd){
+               .id =  WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT),
+-              .len = { sizeof(geo_cmd), },
++              .len = { len, },
+               .flags = CMD_WANT_SKB,
+-              .data = { &geo_cmd },
++              .data = { data },
+       };
+       if (!iwl_mvm_sar_geo_support(mvm))
+@@ -969,6 +984,16 @@ static int iwl_mvm_sar_geo_init(struct i
+                                       i, j, value[1], value[2], value[0]);
+               }
+       }
++
++      cmd.table_revision = cpu_to_le32(mvm->geo_rev);
++
++      if (!fw_has_api(&mvm->fw->ucode_capa,
++                     IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
++              return iwl_mvm_send_cmd_pdu(mvm, cmd_wide_id, 0,
++                              sizeof(struct iwl_geo_tx_power_profiles_cmd_v1),
++                              &cmd);
++      }
++
+       return iwl_mvm_send_cmd_pdu(mvm, cmd_wide_id, 0, sizeof(cmd), &cmd);
+ }
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+@@ -1184,6 +1184,7 @@ struct iwl_mvm {
+ #ifdef CONFIG_ACPI
+       struct iwl_mvm_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM];
+       struct iwl_mvm_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES];
++      u32 geo_rev;
+ #endif
+ };
index 88d084f85a020eb499e6f32bdc17913f71dc3188..b71a4ab067a83d10515d21e8718ce1c8ff9e36be 100644 (file)
@@ -103,3 +103,4 @@ usb-serial-option-add-the-broadmobi-bm818-card.patch
 usb-serial-option-add-motorola-modem-uarts.patch
 usb-setup-authorized_default-attributes-using-usb_bus_notify.patch
 netfilter-conntrack-use-consistent-ct-id-hash-calculation.patch
+iwlwifi-add-support-for-sar-south-korea-limitation.patch