iwlwifi: mvm: select the MAC address according to priority
authorEran Harary <eran.harary@intel.com>
Mon, 28 Apr 2014 12:22:40 +0000 (15:22 +0300)
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Tue, 6 May 2014 17:40:03 +0000 (20:40 +0300)
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 <eran.harary@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
drivers/net/wireless/iwlwifi/mvm/nvm.c

index 4049c0d626ba5dfb2f6be5754b27074175730dbc..49963e4a887ee78bdaa0a21f4958adb86abaae46 100644 (file)
@@ -62,6 +62,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/etherdevice.h>
 #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,
index 2cb6c29b0a9755644ee90ffd77714f19f141c9d2..6d0e659c3decd340d2d55318581e5ddb1024d45f 100644 (file)
@@ -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))