From 9f32e017313112d087f60e1b94bcc7872255b89f Mon Sep 17 00:00:00 2001 From: Eran Harary Date: Mon, 28 Apr 2014 15:22:40 +0300 Subject: iwlwifi: mvm: select the MAC address according to priority For family 8000 products, the driver should take the MAC address from the mac_override section and only if this section is empty it should take it from the HW section. Signed-off-by: Eran Harary Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | 46 +++++++++++++++++++++++----- drivers/net/wireless/iwlwifi/mvm/nvm.c | 9 +++++- 2 files changed, 46 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 4049c0d626ba..49963e4a887e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c @@ -62,6 +62,7 @@ #include #include #include +#include #include "iwl-drv.h" #include "iwl-modparams.h" #include "iwl-nvm-parse.h" @@ -450,13 +451,7 @@ static void iwl_set_hw_address(const struct iwl_cfg *cfg, struct iwl_nvm_data *data, const __le16 *nvm_sec) { - u8 hw_addr[ETH_ALEN]; - - if (cfg->device_family != IWL_DEVICE_FAMILY_8000) - memcpy(hw_addr, nvm_sec + HW_ADDR, ETH_ALEN); - else - memcpy(hw_addr, nvm_sec + MAC_ADDRESS_OVERRIDE_FAMILY_8000, - ETH_ALEN); + const u8 *hw_addr = (const u8 *)(nvm_sec + HW_ADDR); /* The byte order is little endian 16 bit, meaning 214365 */ data->hw_addr[0] = hw_addr[1]; @@ -467,6 +462,41 @@ static void iwl_set_hw_address(const struct iwl_cfg *cfg, data->hw_addr[5] = hw_addr[4]; } +static void iwl_set_hw_address_family_8000(const struct iwl_cfg *cfg, + struct iwl_nvm_data *data, + const __le16 *mac_override, + const __le16 *nvm_hw) +{ + const u8 *hw_addr; + + if (mac_override) { + hw_addr = (const u8 *)(mac_override + + MAC_ADDRESS_OVERRIDE_FAMILY_8000); + + /* The byte order is little endian 16 bit, meaning 214365 */ + data->hw_addr[0] = hw_addr[1]; + data->hw_addr[1] = hw_addr[0]; + data->hw_addr[2] = hw_addr[3]; + data->hw_addr[3] = hw_addr[2]; + data->hw_addr[4] = hw_addr[5]; + data->hw_addr[5] = hw_addr[4]; + + if (is_valid_ether_addr(hw_addr)) + return; + } + + /* take the MAC address from the OTP */ + hw_addr = (const u8 *)(nvm_hw + HW_ADDR0_FAMILY_8000); + data->hw_addr[0] = hw_addr[3]; + data->hw_addr[1] = hw_addr[2]; + data->hw_addr[2] = hw_addr[1]; + data->hw_addr[3] = hw_addr[0]; + + hw_addr = (const u8 *)(nvm_hw + HW_ADDR1_FAMILY_8000); + data->hw_addr[4] = hw_addr[1]; + data->hw_addr[5] = hw_addr[0]; +} + struct iwl_nvm_data * iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, const __le16 *nvm_hw, const __le16 *nvm_sw, @@ -526,7 +556,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, rx_chains); } else { /* MAC address in family 8000 */ - iwl_set_hw_address(cfg, data, mac_override); + iwl_set_hw_address_family_8000(cfg, data, mac_override, nvm_hw); iwl_init_sbands(dev, cfg, data, regulatory, sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains, diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 2cb6c29b0a97..6d0e659c3dec 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c @@ -238,13 +238,20 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) return NULL; } } else { + /* SW and REGULATORY sections are mandatory */ if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || - !mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data || !mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) { IWL_ERR(mvm, "Can't parse empty family 8000 NVM sections\n"); return NULL; } + /* MAC_OVERRIDE or at least HW section must exist */ + if (!mvm->cfg->nvm_hw_section_num && + !mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data) { + IWL_ERR(mvm, + "Can't parse mac_address, empty sections\n"); + return NULL; + } } if (WARN_ON(!mvm->cfg)) -- cgit v1.2.3