summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Ziswiler <marcel.ziswiler@toradex.com>2014-03-31 17:54:25 +0200
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2014-03-31 17:54:25 +0200
commitf032a4e356a04f3ab3d14805b34d48d64ce2a8ca (patch)
treeb37dde66f9a87be4d5aa5713e5c2639c5bf21360
parent3560d23f14c26b65f89a9d6b674fc0f3196fa0f1 (diff)
apalis_t30: 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 and Apalis T30 1GB V1.0A both with blank NVMs as well as iNVMs programmed with Intel's defaults.
-rw-r--r--drivers/net/igb/igb_main.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 29237a3cddcf..325d4f2abba0 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -51,6 +51,7 @@
#endif /* CONFIG_PM_RUNTIME */
#include <linux/if_bridge.h>
+#include <linux/ctype.h>
#include "igb.h"
#include "igb_vmdq.h"
@@ -74,6 +75,9 @@ static const char igb_driver_string[] =
static const char igb_copyright[] =
"Copyright (c) 2007-2013 Intel Corporation.";
+static char g_mac_addr[ETH_ALEN];
+static int g_usr_mac = 0;
+
static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = {
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_1GBPS) },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_SGMII) },
@@ -288,6 +292,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;
@@ -2704,15 +2742,36 @@ static int __devinit igb_probe(struct pci_dev *pdev,
/* make sure the NVM is good */
if (e1000_validate_nvm_checksum(hw) < 0) {
+#ifdef CONFIG_MACH_APALIS_T30
+ /* 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 */
dev_err(pci_dev_to_dev(pdev), "The NVM Checksum Is Not"
" Valid\n");
err = -EIO;
goto err_eeprom;
+#endif /* CONFIG_MACH_APALIS_T30 */
}
/* 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");
+
+#ifdef CONFIG_MACH_APALIS_T30
+ 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(&pdev->dev, "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 */
+
memcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len);
#ifdef ETHTOOL_GPERMADDR
memcpy(netdev->perm_addr, hw->mac.addr, netdev->addr_len);
@@ -2721,9 +2780,20 @@ static int __devinit igb_probe(struct pci_dev *pdev,
#else
if (!is_valid_ether_addr(netdev->dev_addr)) {
#endif
+#ifdef CONFIG_MACH_APALIS_T30
+ /* 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 */
dev_err(pci_dev_to_dev(pdev), "Invalid MAC Address\n");
err = -EIO;
goto err_eeprom;
+#endif /* CONFIG_MACH_APALIS_T30 */
}
memcpy(&adapter->mac_table[0].addr, hw->mac.addr, netdev->addr_len);