wifi: iwlwifi: mvm: SAR table alignment
authorAnjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
Thu, 10 Oct 2024 11:05:04 +0000 (14:05 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 25 Oct 2024 15:53:31 +0000 (17:53 +0200)
SAR table format in ACPI and local data base are different,
So modified code to read data properly.

Signed-off-by: Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20241010140328.f077aced4dee.I4dc618f12d01f7ad19f9f8881f6e09eea77e9a14@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/fw/acpi.c

index a7cea0a..0bc3229 100644 (file)
@@ -429,38 +429,28 @@ out_free:
        return ret;
 }
 
-static int iwl_acpi_sar_set_profile(union acpi_object *table,
-                                   struct iwl_sar_profile *profile,
-                                   bool enabled, u8 num_chains,
-                                   u8 num_sub_bands)
+static int
+iwl_acpi_parse_chains_table(union acpi_object *table,
+                           struct iwl_sar_profile_chain *chains,
+                           u8 num_chains, u8 num_sub_bands)
 {
-       int i, j, idx = 0;
-
-       /*
-        * The table from ACPI is flat, but we store it in a
-        * structured array.
-        */
-       for (i = 0; i < BIOS_SAR_MAX_CHAINS_PER_PROFILE; i++) {
-               for (j = 0; j < BIOS_SAR_MAX_SUB_BANDS_NUM; j++) {
+       for (u8 chain = 0; chain < num_chains; chain++) {
+               for (u8 subband = 0; subband < BIOS_SAR_MAX_SUB_BANDS_NUM;
+                    subband++) {
                        /* if we don't have the values, use the default */
-                       if (i >= num_chains || j >= num_sub_bands) {
-                               profile->chains[i].subbands[j] = 0;
+                       if (subband >= num_sub_bands) {
+                               chains[chain].subbands[subband] = 0;
+                       } else if (table->type != ACPI_TYPE_INTEGER ||
+                                  table->integer.value > U8_MAX) {
+                               return -EINVAL;
                        } else {
-                               if (table[idx].type != ACPI_TYPE_INTEGER ||
-                                   table[idx].integer.value > U8_MAX)
-                                       return -EINVAL;
-
-                               profile->chains[i].subbands[j] =
-                                       table[idx].integer.value;
-
-                               idx++;
+                               chains[chain].subbands[subband] =
+                                       table->integer.value;
+                               table++;
                        }
                }
        }
 
-       /* Only if all values were valid can the profile be enabled */
-       profile->enabled = enabled;
-
        return 0;
 }
 
@@ -543,9 +533,11 @@ read_table:
        /* The profile from WRDS is officially profile 1, but goes
         * into sar_profiles[0] (because we don't have a profile 0).
         */
-       ret = iwl_acpi_sar_set_profile(table, &fwrt->sar_profiles[0],
-                                      flags & IWL_SAR_ENABLE_MSK,
-                                      num_chains, num_sub_bands);
+       ret = iwl_acpi_parse_chains_table(table, fwrt->sar_profiles[0].chains,
+                                         num_chains, num_sub_bands);
+       if (!ret && flags & IWL_SAR_ENABLE_MSK)
+               fwrt->sar_profiles[0].enabled = true;
+
 out_free:
        kfree(data);
        return ret;
@@ -557,7 +549,7 @@ int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
        bool enabled;
        int i, n_profiles, tbl_rev, pos;
        int ret = 0;
-       u8 num_chains, num_sub_bands;
+       u8 num_sub_bands;
 
        data = iwl_acpi_get_object(fwrt->dev, ACPI_EWRD_METHOD);
        if (IS_ERR(data))
@@ -573,7 +565,6 @@ int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
                        goto out_free;
                }
 
-               num_chains = ACPI_SAR_NUM_CHAINS_REV2;
                num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV2;
 
                goto read_table;
@@ -589,7 +580,6 @@ int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
                        goto out_free;
                }
 
-               num_chains = ACPI_SAR_NUM_CHAINS_REV1;
                num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV1;
 
                goto read_table;
@@ -605,7 +595,6 @@ int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
                        goto out_free;
                }
 
-               num_chains = ACPI_SAR_NUM_CHAINS_REV0;
                num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV0;
 
                goto read_table;
@@ -637,23 +626,54 @@ read_table:
        /* the tables start at element 3 */
        pos = 3;
 
+       BUILD_BUG_ON(ACPI_SAR_NUM_CHAINS_REV0 != ACPI_SAR_NUM_CHAINS_REV1);
+       BUILD_BUG_ON(ACPI_SAR_NUM_CHAINS_REV2 != 2 * ACPI_SAR_NUM_CHAINS_REV0);
+
+       /* parse non-cdb chains for all profiles */
        for (i = 0; i < n_profiles; i++) {
                union acpi_object *table = &wifi_pkg->package.elements[pos];
+
                /* The EWRD profiles officially go from 2 to 4, but we
                 * save them in sar_profiles[1-3] (because we don't
                 * have profile 0).  So in the array we start from 1.
                 */
-               ret = iwl_acpi_sar_set_profile(table,
-                                              &fwrt->sar_profiles[i + 1],
-                                              enabled, num_chains,
-                                              num_sub_bands);
+               ret = iwl_acpi_parse_chains_table(table,
+                                                 fwrt->sar_profiles[i + 1].chains,
+                                                 ACPI_SAR_NUM_CHAINS_REV0,
+                                                 num_sub_bands);
                if (ret < 0)
-                       break;
+                       goto out_free;
 
                /* go to the next table */
-               pos += num_chains * num_sub_bands;
+               pos += ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands;
        }
 
+       /* non-cdb table revisions */
+       if (tbl_rev < 2)
+               goto set_enabled;
+
+       /* parse cdb chains for all profiles */
+       for (i = 0; i < n_profiles; i++) {
+               struct iwl_sar_profile_chain *chains;
+               union acpi_object *table;
+
+               table = &wifi_pkg->package.elements[pos];
+               chains = &fwrt->sar_profiles[i + 1].chains[ACPI_SAR_NUM_CHAINS_REV0];
+               ret = iwl_acpi_parse_chains_table(table,
+                                                 chains,
+                                                 ACPI_SAR_NUM_CHAINS_REV0,
+                                                 num_sub_bands);
+               if (ret < 0)
+                       goto out_free;
+
+               /* go to the next table */
+               pos += ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands;
+       }
+
+set_enabled:
+       for (i = 0; i < n_profiles; i++)
+               fwrt->sar_profiles[i + 1].enabled = enabled;
+
 out_free:
        kfree(data);
        return ret;