Skip to content

Commit

Permalink
Staging: octeon-ethernet: Assign proper MAC addresses.
Browse files Browse the repository at this point in the history
Allocate MAC addresses using the same method as the bootloader.  This
avoids changing the MAC between bootloader and kernel operation as
well as avoiding duplicates and use of addresses outside of the
assigned range.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
David Daney authored and Ralf Baechle committed Nov 23, 2009
1 parent aabb89d commit 13c5939
Showing 1 changed file with 41 additions and 12 deletions.
53 changes: 41 additions & 12 deletions drivers/staging/octeon/ethernet.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,16 @@ MODULE_PARM_DESC(disable_core_queueing, "\n"
"\tallows packets to be sent without lock contention in the packet\n"
"\tscheduler resulting in some cases in improved throughput.\n");


/*
* The offset from mac_addr_base that should be used for the next port
* that is configured. By convention, if any mgmt ports exist on the
* chip, they get the first mac addresses, The ports controlled by
* this driver are numbered sequencially following any mgmt addresses
* that may exist.
*/
static unsigned int cvm_oct_mac_addr_offset;

/**
* Periodic timer to check auto negotiation
*/
Expand Down Expand Up @@ -474,16 +484,30 @@ static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr)
*/
int cvm_oct_common_init(struct net_device *dev)
{
static int count;
char mac[8] = { 0x00, 0x00,
octeon_bootinfo->mac_addr_base[0],
octeon_bootinfo->mac_addr_base[1],
octeon_bootinfo->mac_addr_base[2],
octeon_bootinfo->mac_addr_base[3],
octeon_bootinfo->mac_addr_base[4],
octeon_bootinfo->mac_addr_base[5] + count
};
struct octeon_ethernet *priv = netdev_priv(dev);
struct sockaddr sa;
u64 mac = ((u64)(octeon_bootinfo->mac_addr_base[0] & 0xff) << 40) |
((u64)(octeon_bootinfo->mac_addr_base[1] & 0xff) << 32) |
((u64)(octeon_bootinfo->mac_addr_base[2] & 0xff) << 24) |
((u64)(octeon_bootinfo->mac_addr_base[3] & 0xff) << 16) |
((u64)(octeon_bootinfo->mac_addr_base[4] & 0xff) << 8) |
(u64)(octeon_bootinfo->mac_addr_base[5] & 0xff);

mac += cvm_oct_mac_addr_offset;
sa.sa_data[0] = (mac >> 40) & 0xff;
sa.sa_data[1] = (mac >> 32) & 0xff;
sa.sa_data[2] = (mac >> 24) & 0xff;
sa.sa_data[3] = (mac >> 16) & 0xff;
sa.sa_data[4] = (mac >> 8) & 0xff;
sa.sa_data[5] = mac & 0xff;

if (cvm_oct_mac_addr_offset >= octeon_bootinfo->mac_addr_count)
printk(KERN_DEBUG "%s: Using MAC outside of the assigned range:"
" %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
sa.sa_data[0] & 0xff, sa.sa_data[1] & 0xff,
sa.sa_data[2] & 0xff, sa.sa_data[3] & 0xff,
sa.sa_data[4] & 0xff, sa.sa_data[5] & 0xff);
cvm_oct_mac_addr_offset++;

/*
* Force the interface to use the POW send if always_use_pow
Expand All @@ -496,14 +520,12 @@ int cvm_oct_common_init(struct net_device *dev)
if (priv->queue != -1 && USE_HW_TCPUDP_CHECKSUM)
dev->features |= NETIF_F_IP_CSUM;

count++;

/* We do our own locking, Linux doesn't need to */
dev->features |= NETIF_F_LLTX;
SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops);

cvm_oct_mdio_setup_device(dev);
dev->netdev_ops->ndo_set_mac_address(dev, mac);
dev->netdev_ops->ndo_set_mac_address(dev, &sa);
dev->netdev_ops->ndo_change_mtu(dev, dev->mtu);

/*
Expand Down Expand Up @@ -620,6 +642,13 @@ static int __init cvm_oct_init_module(void)

pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION);

if (OCTEON_IS_MODEL(OCTEON_CN52XX))
cvm_oct_mac_addr_offset = 2; /* First two are the mgmt ports. */
else if (OCTEON_IS_MODEL(OCTEON_CN56XX))
cvm_oct_mac_addr_offset = 1; /* First one is the mgmt port. */
else
cvm_oct_mac_addr_offset = 0;

cvm_oct_proc_initialize();
cvm_oct_rx_initialize();
cvm_oct_configure_common_hw();
Expand Down

0 comments on commit 13c5939

Please sign in to comment.