Commit 6f7d5d72 authored by Adam Wujek's avatar Adam Wujek 💬 Committed by Alessandro Rubini

wr_nic: unify MAC initialisation

Add posibility to setup MAC address at load time for SPEC.
Update documentation.
Signed-off-by: Adam Wujek's avatarAdam Wujek <adam.wujek@cern.ch>
parent bc940832
......@@ -659,6 +659,10 @@ The module receives the following parameters:
The name of the LM32 program to load, if any. There is no support
currently to load different LM32 programs to different cards.
@item macaddr=
Use given MAC address. If not provided or 0 read MAC from LM32.
@end table
@c ==========================================================================
......@@ -743,6 +747,9 @@ following:
ifconfig wr0 hw ether 12:34:56:78:9a:bc
@end example
MAC address can also be set by using @code{macaddr=} parameter
at load of @i{wr-nic} kernel module.
The fiber controlled by the SPEC can carry normal data traffic in
addition to the PTP frames of @i{White Rabbit}, that remain
invisible to the host computer. The
......
......@@ -15,9 +15,37 @@
#include <linux/errno.h>
#include <linux/etherdevice.h>
#include <linux/io.h>
#include <linux/moduleparam.h>
#include "wr-nic.h"
static char *macaddr = "00:00:00:00:00:00";
module_param(macaddr, charp, 0444);
/* Copied from kernel 3.6 net/utils.c, it converts from MAC string to u8 array */
__weak int mac_pton(const char *s, u8 *mac)
{
int i;
/* XX:XX:XX:XX:XX:XX */
if (strlen(s) < 3 * ETH_ALEN - 1)
return 0;
/* Don't dirty result unless string is valid MAC. */
for (i = 0; i < ETH_ALEN; i++) {
if (!strchr("0123456789abcdefABCDEF", s[i * 3]))
return 0;
if (!strchr("0123456789abcdefABCDEF", s[i * 3 + 1]))
return 0;
if (i != ETH_ALEN - 1 && s[i * 3 + 2] != ':')
return 0;
}
for (i = 0; i < ETH_ALEN; i++) {
mac[i] = (hex_to_bin(s[i * 3]) << 4) | hex_to_bin(s[i * 3 + 1]);
}
return 1;
}
/*
* Phy access: used by link status, enable, calibration ioctl etc.
* Called with endpoint lock (you'll lock the whole sequence of r/w)
......@@ -220,10 +248,46 @@ static void __wrn_endpoint_shutdown(struct wrn_ep *ep)
int wrn_endpoint_probe(struct net_device *dev)
{
struct wrn_ep *ep = netdev_priv(dev);
int epnum, err;
static u8 wraddr[6];
int err;
u32 val;
epnum = ep->ep_number;
if (is_zero_ether_addr(wraddr)) {
err = mac_pton(macaddr, wraddr);
if (!err)
pr_err("wr_nic: probably invalid MAC address \"%s\".\n"
"Use format XX:XX:XX:XX:XX:XX\n", macaddr);
}
if (WR_IS_NODE) {
/* If address is not provided as parameter read from lm32 */
if (is_zero_ether_addr(wraddr)) {
/* on the SPEC the lm32 already configured the mac address */
val = readl(&ep->ep_regs->MACH);
put_unaligned_be16(val, wraddr);
val = readl(&ep->ep_regs->MACL);
put_unaligned_be32(val, wraddr+2);
}
}
if (WR_IS_SWITCH) {
/* If the MAC address is 0, then randomize the first MAC */
/* Do not randomize for SPEC */
if (is_zero_ether_addr(wraddr)) {
pr_warn("wr_nic: missing MAC address, randomize\n");
/* randomize a MAC address, so lazy users can avoid ifconfig */
random_ether_addr(wraddr);
/* Clear the MSB on fourth octect to prevent bit overflow on OUI */
wraddr[3] &= 0x7F;
}
}
if (ep->ep_number == 0)
pr_info("WR-nic: Using address %pM\n", wraddr);
/* Use wraddr as MAC */
memcpy(dev->dev_addr, wraddr, ETH_ALEN);
pr_debug("wr_nic: assign MAC %pM to wr%d\n", dev->dev_addr, ep->ep_number);
/* Check whether the ep has been sinthetized or not */
val = readl(&ep->ep_regs->IDCODE);
......@@ -252,6 +316,11 @@ int wrn_endpoint_probe(struct net_device *dev)
/* Finally, register and succeed, or fail and undo */
err = register_netdev(dev);
/* Increment MAC address for next endpoint */
val = get_unaligned_be32(wraddr + 2);
put_unaligned_be32(val + 1, wraddr + 2);
if (err) {
printk(KERN_ERR KBUILD_MODNAME ": Can't register dev %s\n",
dev->name);
......@@ -260,17 +329,6 @@ int wrn_endpoint_probe(struct net_device *dev)
return err == -ENODEV ? -EIO : err;
}
if (0) {
/* randomize a MAC address, so lazy users can avoid ifconfig */
random_ether_addr(dev->dev_addr);
} else {
/* on the SPEC the lm32 already configured the mac address */
val = readl(&ep->ep_regs->MACH);
put_unaligned_be16(val, dev->dev_addr);
val = readl(&ep->ep_regs->MACL);
put_unaligned_be32(val, dev->dev_addr+2);
}
return 0;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment