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: ...@@ -659,6 +659,10 @@ The module receives the following parameters:
The name of the LM32 program to load, if any. There is no support The name of the LM32 program to load, if any. There is no support
currently to load different LM32 programs to different cards. 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 @end table
@c ========================================================================== @c ==========================================================================
...@@ -743,6 +747,9 @@ following: ...@@ -743,6 +747,9 @@ following:
ifconfig wr0 hw ether 12:34:56:78:9a:bc ifconfig wr0 hw ether 12:34:56:78:9a:bc
@end example @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 The fiber controlled by the SPEC can carry normal data traffic in
addition to the PTP frames of @i{White Rabbit}, that remain addition to the PTP frames of @i{White Rabbit}, that remain
invisible to the host computer. The invisible to the host computer. The
......
...@@ -15,9 +15,37 @@ ...@@ -15,9 +15,37 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/moduleparam.h>
#include "wr-nic.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. * Phy access: used by link status, enable, calibration ioctl etc.
* Called with endpoint lock (you'll lock the whole sequence of r/w) * 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) ...@@ -220,10 +248,46 @@ static void __wrn_endpoint_shutdown(struct wrn_ep *ep)
int wrn_endpoint_probe(struct net_device *dev) int wrn_endpoint_probe(struct net_device *dev)
{ {
struct wrn_ep *ep = netdev_priv(dev); struct wrn_ep *ep = netdev_priv(dev);
int epnum, err; static u8 wraddr[6];
int err;
u32 val; 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 */ /* Check whether the ep has been sinthetized or not */
val = readl(&ep->ep_regs->IDCODE); val = readl(&ep->ep_regs->IDCODE);
...@@ -252,6 +316,11 @@ int wrn_endpoint_probe(struct net_device *dev) ...@@ -252,6 +316,11 @@ int wrn_endpoint_probe(struct net_device *dev)
/* Finally, register and succeed, or fail and undo */ /* Finally, register and succeed, or fail and undo */
err = register_netdev(dev); 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) { if (err) {
printk(KERN_ERR KBUILD_MODNAME ": Can't register dev %s\n", printk(KERN_ERR KBUILD_MODNAME ": Can't register dev %s\n",
dev->name); dev->name);
...@@ -260,17 +329,6 @@ int wrn_endpoint_probe(struct net_device *dev) ...@@ -260,17 +329,6 @@ int wrn_endpoint_probe(struct net_device *dev)
return err == -ENODEV ? -EIO : err; 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; 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