|
@@ -66,7 +66,6 @@
|
|
|
*****************************************************************************/
|
|
|
#include <net/mac80211.h>
|
|
|
#include <linux/netdevice.h>
|
|
|
-#include <linux/acpi.h>
|
|
|
|
|
|
#include "iwl-trans.h"
|
|
|
#include "iwl-op-mode.h"
|
|
@@ -75,7 +74,7 @@
|
|
|
#include "iwl-csr.h" /* for iwl_mvm_rx_card_state_notif */
|
|
|
#include "iwl-io.h" /* for iwl_mvm_rx_card_state_notif */
|
|
|
#include "iwl-prph.h"
|
|
|
-#include "iwl-eeprom-parse.h"
|
|
|
+#include "fw/acpi.h"
|
|
|
|
|
|
#include "mvm.h"
|
|
|
#include "fw/dbg.h"
|
|
@@ -579,17 +578,6 @@ static int iwl_mvm_config_ltr(struct iwl_mvm *mvm)
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_ACPI
|
|
|
-#define ACPI_WRDS_METHOD "WRDS"
|
|
|
-#define ACPI_EWRD_METHOD "EWRD"
|
|
|
-#define ACPI_WGDS_METHOD "WGDS"
|
|
|
-#define ACPI_WIFI_DOMAIN (0x07)
|
|
|
-#define ACPI_WRDS_WIFI_DATA_SIZE (IWL_MVM_SAR_TABLE_SIZE + 2)
|
|
|
-#define ACPI_EWRD_WIFI_DATA_SIZE ((IWL_MVM_SAR_PROFILE_NUM - 1) * \
|
|
|
- IWL_MVM_SAR_TABLE_SIZE + 3)
|
|
|
-#define ACPI_WGDS_WIFI_DATA_SIZE 18
|
|
|
-#define ACPI_WGDS_NUM_BANDS 2
|
|
|
-#define ACPI_WGDS_TABLE_SIZE 3
|
|
|
-
|
|
|
static int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm,
|
|
|
union acpi_object *table,
|
|
|
struct iwl_mvm_sar_profile *profile,
|
|
@@ -599,7 +587,7 @@ static int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm,
|
|
|
|
|
|
profile->enabled = enabled;
|
|
|
|
|
|
- for (i = 0; i < IWL_MVM_SAR_TABLE_SIZE; i++) {
|
|
|
+ for (i = 0; i < ACPI_SAR_TABLE_SIZE; i++) {
|
|
|
if ((table[i].type != ACPI_TYPE_INTEGER) ||
|
|
|
(table[i].integer.value > U8_MAX))
|
|
|
return -EINVAL;
|
|
@@ -610,88 +598,18 @@ static int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static union acpi_object *iwl_mvm_sar_find_wifi_pkg(struct iwl_mvm *mvm,
|
|
|
- union acpi_object *data,
|
|
|
- int data_size)
|
|
|
-{
|
|
|
- union acpi_object *wifi_pkg = NULL;
|
|
|
- int i;
|
|
|
-
|
|
|
- /*
|
|
|
- * 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).
|
|
|
- */
|
|
|
- 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) {
|
|
|
- IWL_DEBUG_RADIO(mvm, "Unsupported packages structure\n");
|
|
|
- return ERR_PTR(-EINVAL);
|
|
|
- }
|
|
|
-
|
|
|
- /* loop through all the packages to find the one for WiFi */
|
|
|
- for (i = 1; i < data->package.count; i++) {
|
|
|
- union acpi_object *domain;
|
|
|
-
|
|
|
- wifi_pkg = &data->package.elements[i];
|
|
|
-
|
|
|
- /* Skip anything that is not a package with the right
|
|
|
- * amount of elements (i.e. domain_type,
|
|
|
- * enabled/disabled plus the actual data size.
|
|
|
- */
|
|
|
- if (wifi_pkg->type != ACPI_TYPE_PACKAGE ||
|
|
|
- wifi_pkg->package.count != data_size)
|
|
|
- continue;
|
|
|
-
|
|
|
- domain = &wifi_pkg->package.elements[0];
|
|
|
- if (domain->type == ACPI_TYPE_INTEGER &&
|
|
|
- domain->integer.value == ACPI_WIFI_DOMAIN)
|
|
|
- break;
|
|
|
-
|
|
|
- wifi_pkg = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- if (!wifi_pkg)
|
|
|
- return ERR_PTR(-ENOENT);
|
|
|
-
|
|
|
- return wifi_pkg;
|
|
|
-}
|
|
|
-
|
|
|
static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm *mvm)
|
|
|
{
|
|
|
- union acpi_object *wifi_pkg, *table;
|
|
|
- acpi_handle root_handle;
|
|
|
- acpi_handle handle;
|
|
|
- struct acpi_buffer wrds = {ACPI_ALLOCATE_BUFFER, NULL};
|
|
|
- acpi_status status;
|
|
|
+ union acpi_object *wifi_pkg, *table, *data;
|
|
|
bool enabled;
|
|
|
int ret;
|
|
|
|
|
|
- root_handle = ACPI_HANDLE(mvm->dev);
|
|
|
- if (!root_handle) {
|
|
|
- IWL_DEBUG_RADIO(mvm,
|
|
|
- "Could not retrieve root port ACPI handle\n");
|
|
|
- return -ENOENT;
|
|
|
- }
|
|
|
-
|
|
|
- /* Get the method's handle */
|
|
|
- status = acpi_get_handle(root_handle, (acpi_string)ACPI_WRDS_METHOD,
|
|
|
- &handle);
|
|
|
- if (ACPI_FAILURE(status)) {
|
|
|
- IWL_DEBUG_RADIO(mvm, "WRDS method not found\n");
|
|
|
- return -ENOENT;
|
|
|
- }
|
|
|
-
|
|
|
- /* Call WRDS with no arguments */
|
|
|
- status = acpi_evaluate_object(handle, NULL, NULL, &wrds);
|
|
|
- if (ACPI_FAILURE(status)) {
|
|
|
- IWL_DEBUG_RADIO(mvm, "WRDS invocation failed (0x%x)\n", status);
|
|
|
- return -ENOENT;
|
|
|
- }
|
|
|
+ data = iwl_acpi_get_object(mvm->dev, ACPI_WRDS_METHOD);
|
|
|
+ if (IS_ERR(data))
|
|
|
+ return PTR_ERR(data);
|
|
|
|
|
|
- wifi_pkg = iwl_mvm_sar_find_wifi_pkg(mvm, wrds.pointer,
|
|
|
- ACPI_WRDS_WIFI_DATA_SIZE);
|
|
|
+ wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
|
|
|
+ ACPI_WRDS_WIFI_DATA_SIZE);
|
|
|
if (IS_ERR(wifi_pkg)) {
|
|
|
ret = PTR_ERR(wifi_pkg);
|
|
|
goto out_free;
|
|
@@ -712,46 +630,23 @@ static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm *mvm)
|
|
|
*/
|
|
|
ret = iwl_mvm_sar_set_profile(mvm, table, &mvm->sar_profiles[0],
|
|
|
enabled);
|
|
|
-
|
|
|
out_free:
|
|
|
- kfree(wrds.pointer);
|
|
|
+ kfree(data);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
|
|
|
{
|
|
|
- union acpi_object *wifi_pkg;
|
|
|
- acpi_handle root_handle;
|
|
|
- acpi_handle handle;
|
|
|
- struct acpi_buffer ewrd = {ACPI_ALLOCATE_BUFFER, NULL};
|
|
|
- acpi_status status;
|
|
|
+ union acpi_object *wifi_pkg, *data;
|
|
|
bool enabled;
|
|
|
int i, n_profiles, ret;
|
|
|
|
|
|
- root_handle = ACPI_HANDLE(mvm->dev);
|
|
|
- if (!root_handle) {
|
|
|
- IWL_DEBUG_RADIO(mvm,
|
|
|
- "Could not retrieve root port ACPI handle\n");
|
|
|
- return -ENOENT;
|
|
|
- }
|
|
|
-
|
|
|
- /* Get the method's handle */
|
|
|
- status = acpi_get_handle(root_handle, (acpi_string)ACPI_EWRD_METHOD,
|
|
|
- &handle);
|
|
|
- if (ACPI_FAILURE(status)) {
|
|
|
- IWL_DEBUG_RADIO(mvm, "EWRD method not found\n");
|
|
|
- return -ENOENT;
|
|
|
- }
|
|
|
+ data = iwl_acpi_get_object(mvm->dev, ACPI_EWRD_METHOD);
|
|
|
+ if (IS_ERR(data))
|
|
|
+ return PTR_ERR(data);
|
|
|
|
|
|
- /* Call EWRD with no arguments */
|
|
|
- status = acpi_evaluate_object(handle, NULL, NULL, &ewrd);
|
|
|
- if (ACPI_FAILURE(status)) {
|
|
|
- IWL_DEBUG_RADIO(mvm, "EWRD invocation failed (0x%x)\n", status);
|
|
|
- return -ENOENT;
|
|
|
- }
|
|
|
-
|
|
|
- wifi_pkg = iwl_mvm_sar_find_wifi_pkg(mvm, ewrd.pointer,
|
|
|
- ACPI_EWRD_WIFI_DATA_SIZE);
|
|
|
+ wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
|
|
|
+ ACPI_EWRD_WIFI_DATA_SIZE);
|
|
|
if (IS_ERR(wifi_pkg)) {
|
|
|
ret = PTR_ERR(wifi_pkg);
|
|
|
goto out_free;
|
|
@@ -788,55 +683,33 @@ static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
|
|
|
break;
|
|
|
|
|
|
/* go to the next table */
|
|
|
- pos += IWL_MVM_SAR_TABLE_SIZE;
|
|
|
+ pos += ACPI_SAR_TABLE_SIZE;
|
|
|
}
|
|
|
|
|
|
out_free:
|
|
|
- kfree(ewrd.pointer);
|
|
|
+ kfree(data);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
|
|
|
{
|
|
|
- union acpi_object *wifi_pkg;
|
|
|
- acpi_handle root_handle;
|
|
|
- acpi_handle handle;
|
|
|
- struct acpi_buffer wgds = {ACPI_ALLOCATE_BUFFER, NULL};
|
|
|
- acpi_status status;
|
|
|
+ union acpi_object *wifi_pkg, *data;
|
|
|
int i, j, ret;
|
|
|
int idx = 1;
|
|
|
|
|
|
- root_handle = ACPI_HANDLE(mvm->dev);
|
|
|
- if (!root_handle) {
|
|
|
- IWL_DEBUG_RADIO(mvm,
|
|
|
- "Could not retrieve root port ACPI handle\n");
|
|
|
- return -ENOENT;
|
|
|
- }
|
|
|
+ data = iwl_acpi_get_object(mvm->dev, ACPI_WGDS_METHOD);
|
|
|
+ if (IS_ERR(data))
|
|
|
+ return PTR_ERR(data);
|
|
|
|
|
|
- /* Get the method's handle */
|
|
|
- status = acpi_get_handle(root_handle, (acpi_string)ACPI_WGDS_METHOD,
|
|
|
- &handle);
|
|
|
- if (ACPI_FAILURE(status)) {
|
|
|
- IWL_DEBUG_RADIO(mvm, "WGDS method not found\n");
|
|
|
- return -ENOENT;
|
|
|
- }
|
|
|
-
|
|
|
- /* Call WGDS with no arguments */
|
|
|
- status = acpi_evaluate_object(handle, NULL, NULL, &wgds);
|
|
|
- if (ACPI_FAILURE(status)) {
|
|
|
- IWL_DEBUG_RADIO(mvm, "WGDS invocation failed (0x%x)\n", status);
|
|
|
- return -ENOENT;
|
|
|
- }
|
|
|
-
|
|
|
- wifi_pkg = iwl_mvm_sar_find_wifi_pkg(mvm, wgds.pointer,
|
|
|
- ACPI_WGDS_WIFI_DATA_SIZE);
|
|
|
+ wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
|
|
|
+ ACPI_WGDS_WIFI_DATA_SIZE);
|
|
|
if (IS_ERR(wifi_pkg)) {
|
|
|
ret = PTR_ERR(wifi_pkg);
|
|
|
goto out_free;
|
|
|
}
|
|
|
|
|
|
- for (i = 0; i < IWL_NUM_GEO_PROFILES; i++) {
|
|
|
- for (j = 0; j < IWL_MVM_GEO_TABLE_SIZE; j++) {
|
|
|
+ for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
|
|
|
+ for (j = 0; j < ACPI_GEO_TABLE_SIZE; j++) {
|
|
|
union acpi_object *entry;
|
|
|
|
|
|
entry = &wifi_pkg->package.elements[idx++];
|
|
@@ -851,7 +724,7 @@ static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
|
|
|
}
|
|
|
ret = 0;
|
|
|
out_free:
|
|
|
- kfree(wgds.pointer);
|
|
|
+ kfree(data);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -861,25 +734,25 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
|
|
|
.v3.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS),
|
|
|
};
|
|
|
int i, j, idx;
|
|
|
- int profs[IWL_NUM_CHAIN_LIMITS] = { prof_a, prof_b };
|
|
|
+ int profs[ACPI_SAR_NUM_CHAIN_LIMITS] = { prof_a, prof_b };
|
|
|
int len = sizeof(cmd);
|
|
|
|
|
|
- BUILD_BUG_ON(IWL_NUM_CHAIN_LIMITS < 2);
|
|
|
- BUILD_BUG_ON(IWL_NUM_CHAIN_LIMITS * IWL_NUM_SUB_BANDS !=
|
|
|
- IWL_MVM_SAR_TABLE_SIZE);
|
|
|
+ BUILD_BUG_ON(ACPI_SAR_NUM_CHAIN_LIMITS < 2);
|
|
|
+ BUILD_BUG_ON(ACPI_SAR_NUM_CHAIN_LIMITS * ACPI_SAR_NUM_SUB_BANDS !=
|
|
|
+ ACPI_SAR_TABLE_SIZE);
|
|
|
|
|
|
if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TX_POWER_ACK))
|
|
|
len = sizeof(cmd.v3);
|
|
|
|
|
|
- for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
|
|
|
+ for (i = 0; i < ACPI_SAR_NUM_CHAIN_LIMITS; i++) {
|
|
|
struct iwl_mvm_sar_profile *prof;
|
|
|
|
|
|
/* don't allow SAR to be disabled (profile 0 means disable) */
|
|
|
if (profs[i] == 0)
|
|
|
return -EPERM;
|
|
|
|
|
|
- /* we are off by one, so allow up to IWL_MVM_SAR_PROFILE_NUM */
|
|
|
- if (profs[i] > IWL_MVM_SAR_PROFILE_NUM)
|
|
|
+ /* we are off by one, so allow up to ACPI_SAR_PROFILE_NUM */
|
|
|
+ if (profs[i] > ACPI_SAR_PROFILE_NUM)
|
|
|
return -EINVAL;
|
|
|
|
|
|
/* profiles go from 1 to 4, so decrement to access the array */
|
|
@@ -894,8 +767,8 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
|
|
|
}
|
|
|
|
|
|
IWL_DEBUG_RADIO(mvm, " Chain[%d]:\n", i);
|
|
|
- for (j = 0; j < IWL_NUM_SUB_BANDS; j++) {
|
|
|
- idx = (i * IWL_NUM_SUB_BANDS) + j;
|
|
|
+ for (j = 0; j < ACPI_SAR_NUM_SUB_BANDS; j++) {
|
|
|
+ idx = (i * ACPI_SAR_NUM_SUB_BANDS) + j;
|
|
|
cmd.v3.per_chain_restriction[i][j] =
|
|
|
cpu_to_le16(prof->table[idx]);
|
|
|
IWL_DEBUG_RADIO(mvm, " Band[%d] = %d * .125dBm\n",
|
|
@@ -931,7 +804,7 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
|
|
|
|
|
|
resp = (void *)cmd.resp_pkt->data;
|
|
|
ret = le32_to_cpu(resp->profile_idx);
|
|
|
- if (WARN_ON(ret > IWL_NUM_GEO_PROFILES)) {
|
|
|
+ if (WARN_ON(ret > ACPI_NUM_GEO_PROFILES)) {
|
|
|
ret = -EIO;
|
|
|
IWL_WARN(mvm, "Invalid geographic profile idx (%d)\n", ret);
|
|
|
}
|
|
@@ -959,10 +832,12 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
|
|
|
|
|
|
IWL_DEBUG_RADIO(mvm, "Sending GEO_TX_POWER_LIMIT\n");
|
|
|
|
|
|
- BUILD_BUG_ON(IWL_NUM_GEO_PROFILES * ACPI_WGDS_NUM_BANDS *
|
|
|
+ BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES * ACPI_WGDS_NUM_BANDS *
|
|
|
ACPI_WGDS_TABLE_SIZE != ACPI_WGDS_WIFI_DATA_SIZE);
|
|
|
|
|
|
- for (i = 0; i < IWL_NUM_GEO_PROFILES; i++) {
|
|
|
+ BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES > IWL_NUM_GEO_PROFILES);
|
|
|
+
|
|
|
+ for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
|
|
|
struct iwl_per_chain_offset *chain =
|
|
|
(struct iwl_per_chain_offset *)&cmd.table[i];
|
|
|
|
|
@@ -970,7 +845,7 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
|
|
|
u8 *value;
|
|
|
|
|
|
value = &mvm->geo_profiles[i].values[j *
|
|
|
- IWL_GEO_PER_CHAIN_SIZE];
|
|
|
+ ACPI_GEO_PER_CHAIN_SIZE];
|
|
|
chain[j].max_tx_power = cpu_to_le16(value[0]);
|
|
|
chain[j].chain_a = value[1];
|
|
|
chain[j].chain_b = value[2];
|