Skip to content

Commit

Permalink
iwlwifi: move BIOS MCC retrieval to common code
Browse files Browse the repository at this point in the history
This will be used by more than MVM, so move it to iwlwifi

While at it, rename WRD_METHOD to the more appropriate
WRDD_METHOD and add some documentation.

Signed-off-by: Arik Nemtsov <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
  • Loading branch information
ariknem authored and lucacoelho committed Sep 19, 2016
1 parent 4857d6c commit 671bed3
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 93 deletions.
89 changes: 89 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
#include <linux/export.h>
#include <linux/etherdevice.h>
#include <linux/pci.h>
#include <linux/acpi.h>
#include "iwl-drv.h"
#include "iwl-modparams.h"
#include "iwl-nvm-parse.h"
Expand Down Expand Up @@ -904,3 +905,91 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
return regd;
}
IWL_EXPORT_SYMBOL(iwl_parse_nvm_mcc_info);

#ifdef CONFIG_ACPI
#define WRDD_METHOD "WRDD"
#define WRDD_WIFI (0x07)
#define WRDD_WIGIG (0x10)

static u32 iwl_wrdd_get_mcc(struct device *dev, union acpi_object *wrdd)
{
union acpi_object *mcc_pkg, *domain_type, *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) {
IWL_DEBUG_EEPROM(dev, "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 ||
mcc_pkg->package.count < 2 ||
mcc_pkg->package.elements[0].type != ACPI_TYPE_INTEGER ||
mcc_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) {
mcc_pkg = NULL;
continue;
}

domain_type = &mcc_pkg->package.elements[0];
if (domain_type->integer.value == WRDD_WIFI)
break;

mcc_pkg = NULL;
}

if (mcc_pkg) {
mcc_value = &mcc_pkg->package.elements[1];
return mcc_value->integer.value;
}

return 0;
}

int iwl_get_bios_mcc(struct device *dev, char *mcc)
{
acpi_handle root_handle;
acpi_handle handle;
struct acpi_buffer wrdd = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_status status;
u32 mcc_val;

root_handle = ACPI_HANDLE(dev);
if (!root_handle) {
IWL_DEBUG_EEPROM(dev,
"Could not retrieve root port ACPI handle\n");
return -ENOENT;
}

/* Get the method's handle */
status = acpi_get_handle(root_handle, (acpi_string)WRDD_METHOD,
&handle);
if (ACPI_FAILURE(status)) {
IWL_DEBUG_EEPROM(dev, "WRD method not found\n");
return -ENOENT;
}

/* Call WRDD with no arguments */
status = acpi_evaluate_object(handle, NULL, NULL, &wrdd);
if (ACPI_FAILURE(status)) {
IWL_DEBUG_EEPROM(dev, "WRDC invocation failed (0x%x)\n",
status);
return -ENOENT;
}

mcc_val = iwl_wrdd_get_mcc(dev, wrdd.pointer);
kfree(wrdd.pointer);
if (!mcc_val)
return -ENOENT;

mcc[0] = (mcc_val >> 8) & 0xff;
mcc[1] = mcc_val & 0xff;
mcc[2] = '\0';
return 0;
}
IWL_EXPORT_SYMBOL(iwl_get_bios_mcc);
#endif
20 changes: 19 additions & 1 deletion drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2008 - 2015 Intel Corporation. All rights reserved.
* Copyright(c) 2016 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
Expand Down Expand Up @@ -93,4 +94,21 @@ struct ieee80211_regdomain *
iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int num_of_ch, __le32 *channels, u16 fw_mcc);

#ifdef CONFIG_ACPI
/**
* iwl_get_bios_mcc - read MCC from BIOS, if available
*
* @dev: the struct device
* @mcc: output buffer (3 bytes) that will get the MCC
*
* This function tries to read the current MCC from ACPI if available.
*/
int iwl_get_bios_mcc(struct device *dev, char *mcc);
#else
static inline int iwl_get_bios_mcc(struct device *dev, char *mcc)
{
return -ENOENT;
}
#endif

#endif /* __iwl_nvm_parse_h__ */
93 changes: 1 addition & 92 deletions drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@
*****************************************************************************/
#include <linux/firmware.h>
#include <linux/rtnetlink.h>
#include <linux/acpi.h>
#include "iwl-trans.h"
#include "iwl-csr.h"
#include "mvm.h"
Expand Down Expand Up @@ -751,96 +750,6 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
return resp_cp;
}

#ifdef CONFIG_ACPI
#define WRD_METHOD "WRDD"
#define WRDD_WIFI (0x07)
#define WRDD_WIGIG (0x10)

static u32 iwl_mvm_wrdd_get_mcc(struct iwl_mvm *mvm, union acpi_object *wrdd)
{
union acpi_object *mcc_pkg, *domain_type, *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) {
IWL_DEBUG_LAR(mvm, "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 ||
mcc_pkg->package.count < 2 ||
mcc_pkg->package.elements[0].type != ACPI_TYPE_INTEGER ||
mcc_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) {
mcc_pkg = NULL;
continue;
}

domain_type = &mcc_pkg->package.elements[0];
if (domain_type->integer.value == WRDD_WIFI)
break;

mcc_pkg = NULL;
}

if (mcc_pkg) {
mcc_value = &mcc_pkg->package.elements[1];
return mcc_value->integer.value;
}

return 0;
}

static int iwl_mvm_get_bios_mcc(struct iwl_mvm *mvm, char *mcc)
{
acpi_handle root_handle;
acpi_handle handle;
struct acpi_buffer wrdd = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_status status;
u32 mcc_val;

root_handle = ACPI_HANDLE(mvm->dev);
if (!root_handle) {
IWL_DEBUG_LAR(mvm,
"Could not retrieve root port ACPI handle\n");
return -ENOENT;
}

/* Get the method's handle */
status = acpi_get_handle(root_handle, (acpi_string)WRD_METHOD, &handle);
if (ACPI_FAILURE(status)) {
IWL_DEBUG_LAR(mvm, "WRD method not found\n");
return -ENOENT;
}

/* Call WRDD with no arguments */
status = acpi_evaluate_object(handle, NULL, NULL, &wrdd);
if (ACPI_FAILURE(status)) {
IWL_DEBUG_LAR(mvm, "WRDC invocation failed (0x%x)\n", status);
return -ENOENT;
}

mcc_val = iwl_mvm_wrdd_get_mcc(mvm, wrdd.pointer);
kfree(wrdd.pointer);
if (!mcc_val)
return -ENOENT;

mcc[0] = (mcc_val >> 8) & 0xff;
mcc[1] = mcc_val & 0xff;
mcc[2] = '\0';
return 0;
}
#else /* CONFIG_ACPI */
static int iwl_mvm_get_bios_mcc(struct iwl_mvm *mvm, char *mcc)
{
return -ENOENT;
}
#endif

int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
{
bool tlv_lar;
Expand Down Expand Up @@ -884,7 +793,7 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
return -EIO;

if (iwl_mvm_is_wifi_mcc_supported(mvm) &&
!iwl_mvm_get_bios_mcc(mvm, mcc)) {
!iwl_get_bios_mcc(mvm->dev, mcc)) {
kfree(regd);
regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, mcc,
MCC_SOURCE_BIOS, NULL);
Expand Down

0 comments on commit 671bed3

Please sign in to comment.