diff options
author | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2015-04-02 13:55:25 +0200 |
---|---|---|
committer | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2016-06-29 16:48:15 +0200 |
commit | 70efa60d96c9f05d91d8875eee97446df7f9e877 (patch) | |
tree | 8ddca6eaf75cdac3d450abc682de19aad0b10a2a | |
parent | 783780c43fd4e1473fb64790c8b9e0adb2be04a3 (diff) |
apalis_t30/tk1: igb: no nvm and Ethernet MAC address handling
Springville/i211 with a blank Flash/iNVM use different PCI IDs. Extend
the driver to load despite i210/i211 data sheets claiming tools only,
not for driver.
Only warn rather than fail on NVM validation failures on Apalis T30.
Revise Ethernet MAC address assignment: should now handle up to two
instances of custom user MACs (2nd one with a 0x100000 offset). This
way customer does not have to worry about NVM on a secondary Ethernet
on the carrier board and still gets a valid official MAC address from
us (e.g. analogous to how we did it on our Protea carrier board).
Use the Toradex OUI as default MAC address if no valid one is
encountered.
Tested on samples of Apalis T30 2GB V1.0B, V1.0C, V1.1A, Apalis T30 1GB
V1.0A, V1.1A and Apalis T30 1GB IT V1.1A both with blank NVMs as well
as iNVMs programmed with Intel's defaults.
Tested on samples of Apalis TK1 2GB V1.0A and V1.0B both with blank
NVMs as well as iNVMs programmed with Intel's defaults.
Signed-off-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
Acked-by: Dominik Sliwa <dominik.sliwa@toradex.com>
(cherry picked from commit c4c3c7449bdb15c53bfebb0a29c73b24ea810d23)
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_main.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 3264e73007e9..69fd5387d846 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -48,6 +48,7 @@ #endif /* CONFIG_PM_RUNTIME */ #include <linux/if_bridge.h> +#include <linux/ctype.h> #include "igb.h" #include "igb_vmdq.h" @@ -73,6 +74,9 @@ static const char igb_driver_string[] = static const char igb_copyright[] = "Copyright (c) 2007-2015 Intel Corporation."; +static char g_mac_addr[ETH_ALEN]; +static int g_usr_mac = 0; + static const struct pci_device_id igb_pci_tbl[] = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_1GBPS) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_SGMII) }, @@ -289,6 +293,40 @@ MODULE_DESCRIPTION("Intel(R) Gigabit Ethernet Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); +/* Retrieve user set MAC address */ +static int __init setup_igb_mac(char *macstr) +{ + int i, j; + unsigned char result, value; + + for (i = 0; i < ETH_ALEN; i++) { + result = 0; + + if (i != 5 && *(macstr + 2) != ':') + return -1; + + for (j = 0; j < 2; j++) { + if (isxdigit(*macstr) + && (value = + isdigit(*macstr) ? *macstr - + '0' : toupper(*macstr) - 'A' + 10) < 16) { + result = result * 16 + value; + macstr++; + } else + return -1; + } + + macstr++; + g_mac_addr[i] = result; + } + + g_usr_mac = 1; + + return 0; +} + +__setup("igb_mac=", setup_igb_mac); + static void igb_vfta_set(struct igb_adapter *adapter, u32 vid, bool add) { struct e1000_hw *hw = &adapter->hw; @@ -2868,15 +2906,38 @@ static int igb_probe(struct pci_dev *pdev, /* make sure the NVM is good */ if (e1000_validate_nvm_checksum(hw) < 0) { +#if defined (CONFIG_MACH_APALIS_T30) || defined (CONFIG_MACH_APALIS_TK1) + /* only warn on NVM validation failures */ + dev_warn(pci_dev_to_dev(pdev), + "The NVM Checksum Is Not Valid\n"); +#else /* CONFIG_MACH_APALIS_T30 || CONFIG_MACH_APALIS_TK1 */ dev_err(pci_dev_to_dev(pdev), "The NVM Checksum Is Not Valid\n"); err = -EIO; goto err_eeprom; +#endif /* CONFIG_MACH_APALIS_T30 || CONFIG_MACH_APALIS_TK1 */ } /* copy the MAC address out of the NVM */ if (e1000_read_mac_addr(hw)) dev_err(pci_dev_to_dev(pdev), "NVM Read Error\n"); + +#if defined (CONFIG_MACH_APALIS_T30) || defined (CONFIG_MACH_APALIS_TK1) + if (g_usr_mac && (g_usr_mac < 3)) { + /* Get user set MAC address */ + if (g_usr_mac == 2) { + /* 0x100000 offset for 2nd Ethernet MAC */ + g_mac_addr[3] += 0x10; + if (g_mac_addr[3] < 0x10) + dev_warn(pci_dev_to_dev(pdev), "MAC address " + "byte 3 (0x%02x) wrap around", + g_mac_addr[3]); + } + memcpy(hw->mac.addr, g_mac_addr, ETH_ALEN); + g_usr_mac++; + } +#endif /* CONFIG_MACH_APALIS_T30 || CONFIG_MACH_APALIS_TK1 */ + memcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len); #ifdef ETHTOOL_GPERMADDR memcpy(netdev->perm_addr, hw->mac.addr, netdev->addr_len); @@ -2885,9 +2946,20 @@ static int igb_probe(struct pci_dev *pdev, #else if (!is_valid_ether_addr(netdev->dev_addr)) { #endif +#if defined (CONFIG_MACH_APALIS_T30) || defined (CONFIG_MACH_APALIS_TK1) + /* Use Toradex OUI as default */ + char default_mac_addr[ETH_ALEN] = {0x0, 0x14, 0x2d, 0x0, 0x0, 0x0}; + dev_warn(&pdev->dev, "using Toradex OUI as default igb MAC"); + memcpy(hw->mac.addr, default_mac_addr, ETH_ALEN); + memcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len); +#ifdef ETHTOOL_GPERMADDR + memcpy(netdev->perm_addr, hw->mac.addr, netdev->addr_len); +#endif +#else /* CONFIG_MACH_APALIS_T30 || CONFIG_MACH_APALIS_TK1 */ dev_err(pci_dev_to_dev(pdev), "Invalid MAC Address\n"); err = -EIO; goto err_eeprom; +#endif /* CONFIG_MACH_APALIS_T30 || CONFIG_MACH_APALIS_TK1 */ } memcpy(&adapter->mac_table[0].addr, hw->mac.addr, netdev->addr_len); @@ -3157,7 +3229,9 @@ err_register: #ifdef HAVE_I2C_SUPPORT memset(&adapter->i2c_adap, 0, sizeof(adapter->i2c_adap)); #endif /* HAVE_I2C_SUPPORT */ +#if !defined (CONFIG_MACH_APALIS_T30) && !defined (CONFIG_MACH_APALIS_TK1) err_eeprom: +#endif if (!e1000_check_reset_block(hw)) e1000_phy_hw_reset(hw); |