summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2022-11-14 16:54:38 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2022-11-14 16:54:38 +0100
commitaf3ab6492459a70f9fe572c3a42e6cdb6cbc44c4 (patch)
tree5d02d19f76ea5ac1b2502fb8311983ad220a52e3
parent66544641b2dd00c37e16d8e1ac39a34ec4e57cb8 (diff)
parentff9c801b9e807fd3b429849e654725591a3d1eb8 (diff)
downloadbarebox-af3ab6492459a70f9fe572c3a42e6cdb6cbc44c4.tar.gz
barebox-af3ab6492459a70f9fe572c3a42e6cdb6cbc44c4.tar.xz
Merge branch 'for-next/promisc'
-rw-r--r--arch/arm/boards/skov-imx6/board.c105
-rw-r--r--commands/ethlog.c21
-rw-r--r--drivers/net/dsa.c24
-rw-r--r--drivers/net/fec_imx.c26
-rw-r--r--drivers/net/fec_imx.h1
-rw-r--r--drivers/net/usb/asix.c20
-rw-r--r--include/dsa.h2
-rw-r--r--include/net.h3
-rw-r--r--net/eth.c8
9 files changed, 159 insertions, 51 deletions
diff --git a/arch/arm/boards/skov-imx6/board.c b/arch/arm/boards/skov-imx6/board.c
index 3c51b76735..19f91ab481 100644
--- a/arch/arm/boards/skov-imx6/board.c
+++ b/arch/arm/boards/skov-imx6/board.c
@@ -17,6 +17,12 @@
#include "version.h"
+struct skov_imx6_priv {
+ struct device_d *dev;
+};
+
+static struct skov_imx6_priv *skov_priv;
+
static int eth_of_fixup_node(struct device_node *root, const char *node_path,
const u8 *ethaddr)
{
@@ -27,21 +33,21 @@ static int eth_of_fixup_node(struct device_node *root, const char *node_path,
unsigned char ethaddr_str[sizeof("xx:xx:xx:xx:xx:xx")];
ethaddr_to_string(ethaddr, ethaddr_str);
- pr_err("The mac-address %s is invalid.\n", ethaddr_str);
+ dev_err(skov_priv->dev, "The mac-address %s is invalid.\n", ethaddr_str);
return -EINVAL;
}
node = of_find_node_by_path_from(root, node_path);
if (!node) {
- pr_err("Did not find node %s to fix up with stored mac-address.\n",
- node_path);
+ dev_err(skov_priv->dev, "Did not find node %s to fix up with stored mac-address.\n",
+ node_path);
return -ENOENT;
}
ret = of_set_property(node, "mac-address", ethaddr, ETH_ALEN, 1);
if (ret)
- pr_err("Setting mac-address property of %s failed with: %s.\n",
- node->full_name, strerror(-ret));
+ dev_err(skov_priv->dev, "Setting mac-address property of %s failed with: %s.\n",
+ node->full_name, strerror(-ret));
return ret;
}
@@ -54,7 +60,7 @@ static int eth_of_fixup_node_from_eth_device(struct device_node *root,
edev = eth_get_byname(ethname);
if (!edev) {
- pr_err("Did not find eth device \"%s\" to copy mac-address from.\n", ethname);
+ dev_err(skov_priv->dev, "Did not find eth device \"%s\" to copy mac-address from.\n", ethname);
return -ENOENT;
}
@@ -68,14 +74,14 @@ static int get_mac_address_from_env_variable(const char *env, u8 ethaddr[ETH_ALE
ethaddr_str = getenv(env);
if (!ethaddr_str) {
- pr_err("State variable %s storing the mac-address not found.\n", env);
+ dev_err(skov_priv->dev, "State variable %s storing the mac-address not found.\n", env);
return -ENOENT;
}
ret = string_to_ethaddr(ethaddr_str, ethaddr);
if (ret < 0) {
- pr_err("Could not convert \"%s\" in state variable %s into mac-address.\n",
- ethaddr_str, env);
+ dev_err(skov_priv->dev, "Could not convert \"%s\" in state variable %s into mac-address.\n",
+ ethaddr_str, env);
return -EINVAL;
}
@@ -90,13 +96,13 @@ static int get_default_mac_address_from_state_node(const char *state_node_path,
node = of_find_node_by_path(state_node_path);
if (!node) {
- pr_err("Node %s defining the state variable not found.\n", state_node_path);
+ dev_err(skov_priv->dev, "Node %s defining the state variable not found.\n", state_node_path);
return -ENOENT;
}
ret = of_property_read_u8_array(node, "default", ethaddr, ETH_ALEN);
if (ret) {
- pr_err("Node %s has no property \"default\" of proper type.\n", state_node_path);
+ dev_err(skov_priv->dev, "Node %s has no property \"default\" of proper type.\n", state_node_path);
return -ENOENT;
}
@@ -340,18 +346,18 @@ static void skov_imx6_no_switch(struct device_node *root)
if (node) {
ret = of_device_disable(node);
if (ret)
- pr_warn("Can't disable %s\n", fec_alias);
+ dev_warn(skov_priv->dev, "Can't disable %s\n", fec_alias);
} else {
- pr_warn("Can't find node by alias: %s\n", fec_alias);
+ dev_warn(skov_priv->dev, "Can't find node by alias: %s\n", fec_alias);
}
node = of_find_node_by_alias(root, "mdio-gpio0");
if (node) {
ret = of_device_disable(node);
if (ret)
- pr_warn("Can't disable mdio-gpio0 node\n");
+ dev_warn(skov_priv->dev, "Can't disable mdio-gpio0 node\n");
} else {
- pr_warn("Can't find mdio-gpio0 node\n");
+ dev_warn(skov_priv->dev, "Can't find mdio-gpio0 node\n");
}
}
@@ -398,7 +404,7 @@ static void skov_imx6_switch(struct device_node *root)
if (ret) {
ret = skov_imx6_switch_port(root, old);
if (ret)
- pr_err("Filed to set mac address\n");
+ dev_err(skov_priv->dev, "Filed to set mac address\n");
}
}
@@ -423,7 +429,7 @@ static int skov_imx6_fixup(struct device_node *root, void *unused)
default:
val = getenv("state.display.brightness");
if (!val) {
- pr_err("could not get default display brightness\n");
+ dev_err(skov_priv->dev, "could not get default display brightness\n");
return 0;
}
@@ -434,7 +440,7 @@ static int skov_imx6_fixup(struct device_node *root, void *unused)
for_each_compatible_node_from(node, root, NULL, "pwm-backlight") {
ret = of_property_write_u32(node, "default-brightness-level", brightness);
if (ret)
- pr_err("error %d while setting default-brightness-level property on node %s to %d\n",
+ dev_err(skov_priv->dev, "error %d while setting default-brightness-level property on node %s to %d\n",
ret, node->name, brightness);
}
@@ -463,9 +469,9 @@ static void skov_init_board(const struct board_description *variant)
if (gpio_np) {
ret = of_device_ensure_probed(gpio_np);
if (ret)
- pr_warn("Can't probe GPIO node\n");
+ dev_warn(skov_priv->dev, "Can't probe GPIO node\n");
} else {
- pr_warn("Can't get GPIO node\n");
+ dev_warn(skov_priv->dev, "Can't get GPIO node\n");
}
imx6_bbu_internal_spi_i2c_register_handler("spiflash", "/dev/m25p0.barebox",
@@ -484,12 +490,12 @@ static void skov_init_board(const struct board_description *variant)
break;
}
- pr_notice("Using environment in %s\n", envdev);
+ dev_notice(skov_priv->dev, "Using environment in %s\n", envdev);
ret = of_device_enable_path(environment_path);
if (ret < 0)
- pr_warn("Failed to enable environment partition '%s' (%d)\n",
- environment_path, ret);
+ dev_warn(skov_priv->dev, "Failed to enable environment partition '%s' (%d)\n",
+ environment_path, ret);
if (variant->flags & SKOV_NEED_ENABLE_RMII) {
/*
@@ -523,7 +529,7 @@ static void skov_init_board(const struct board_description *variant)
if (np)
of_device_enable_and_register(np);
else
- pr_err("Cannot find \"fsl,imx-parallel-display\" node\n");
+ dev_err(skov_priv->dev, "Cannot find \"fsl,imx-parallel-display\" node\n");
}
if (variant->flags & SKOV_DISPLAY_LVDS) {
@@ -531,17 +537,44 @@ static void skov_init_board(const struct board_description *variant)
if (np)
of_device_enable_and_register(np);
else
- pr_err("Cannot find \"fsl,imx6q-ldb\" node\n");
+ dev_err(skov_priv->dev, "Cannot find \"fsl,imx6q-ldb\" node\n");
/* ... as well as its channel 0 */
np = of_find_node_by_name_address(np, "lvds-channel@0");
if (np)
of_device_enable(np);
else
- pr_err("Cannot find \"lvds-channel@0\" node\n");
+ dev_err(skov_priv->dev, "Cannot find \"lvds-channel@0\" node\n");
}
}
+static int skov_set_switch_lan2_mac(struct skov_imx6_priv *priv)
+{
+ const char *state = "/state/ethaddr/eth2";
+ struct device_node *lan2_np;
+ u8 ethaddr[ETH_ALEN];
+ int ret;
+
+ ret = get_mac_address_from_env_variable("state.ethaddr.eth2", ethaddr);
+ if (ret || !is_valid_ether_addr(ethaddr)) {
+ ret = get_default_mac_address_from_state_node(state, ethaddr);
+ if (ret || !is_valid_ether_addr(ethaddr)) {
+ dev_err(priv->dev, "can't get MAC for LAN2\n");
+ return -ENODEV;
+ }
+ }
+
+ lan2_np = of_find_node_by_path("/mdio/switch@0/ports/ports@1");
+ if (!lan2_np) {
+ dev_err(priv->dev, "LAN2 node not found\n");
+ return -ENODEV;
+ }
+
+ of_eth_register_ethaddr(lan2_np, ethaddr);
+
+ return 0;
+}
+
static int skov_switch_test(void)
{
struct device_d *sw_dev;
@@ -557,25 +590,28 @@ static int skov_switch_test(void)
*/
sw_dev = of_find_device_by_node_path("/mdio/switch@0");
if (!sw_dev) {
- pr_err("switch@0 device was not created!\n");
+ dev_err(skov_priv->dev, "switch@0 device was not created!\n");
goto no_switch;
}
- if (dev_is_probed(sw_dev))
+ if (dev_is_probed(sw_dev)) {
+ skov_set_switch_lan2_mac(skov_priv);
+ /* even if we fail, continue to boot as good as possible */
return 0;
+ }
no_switch:
skov_have_switch = false;
- pr_notice("No-switch variant is detected\n");
+ dev_notice(skov_priv->dev, "No-switch variant is detected\n");
eth0 = get_device_by_name("eth0");
if (eth0) {
ret = dev_set_param(eth0, "mode", "disabled");
if (ret)
- pr_warn("Can't set eth0 mode\n");
+ dev_warn(skov_priv->dev, "Can't set eth0 mode\n");
} else {
- pr_warn("Can't disable eth0\n");
+ dev_warn(skov_priv->dev, "Can't disable eth0\n");
}
return 0;
@@ -584,6 +620,7 @@ late_initcall(skov_switch_test);
static int skov_imx6_probe(struct device_d *dev)
{
+ struct skov_imx6_priv *priv;
unsigned v = 0;
const struct board_description *variant;
@@ -603,6 +640,10 @@ static int skov_imx6_probe(struct device_d *dev)
skov_board_no = v;
+ priv = xzalloc(sizeof(*priv));
+ priv->dev = dev;
+ skov_priv = priv;
+
globalvar_add_simple_int("board.no", &skov_board_no, "%u");
globalvar_add_simple("board.variant", variant->variant);
globalvar_add_simple("board.revision",variant->revision);
@@ -644,7 +685,7 @@ static void skov_imx6_devices_shutdown(void)
external = getenv("state.display.external");
if (!external) {
- pr_err("could not get state variable display.external\n");
+ dev_err(skov_priv->dev, "could not get state variable display.external\n");
return;
}
diff --git a/commands/ethlog.c b/commands/ethlog.c
index 0cc93ba808..7885d32c6b 100644
--- a/commands/ethlog.c
+++ b/commands/ethlog.c
@@ -29,11 +29,14 @@ static int do_ethlog(int argc, char *argv[])
{
struct eth_device *edev;
const char *edevname;
- bool remove = false;
- int opt;
+ bool remove = false, promisc = false;
+ int opt, ret;
- while ((opt = getopt(argc, argv, "r")) > 0) {
+ while ((opt = getopt(argc, argv, "pr")) > 0) {
switch (opt) {
+ case 'p':
+ promisc = true;
+ break;
case 'r':
remove = true;
break;
@@ -56,10 +59,19 @@ static int do_ethlog(int argc, char *argv[])
if (remove) {
edev->tx_monitor = NULL;
edev->rx_monitor = NULL;
+ if (promisc)
+ eth_set_promisc(edev, false);
return 0;
}
+ if (promisc) {
+ ret = eth_set_promisc(edev, true);
+ if (ret)
+ dev_warn(&edev->dev, "Failed to set promisc mode: %pe\n",
+ ERR_PTR(ret));
+ }
+
edev->tx_monitor = ethlog_tx_monitor;
edev->rx_monitor = ethlog_rx_monitor;
@@ -69,12 +81,13 @@ static int do_ethlog(int argc, char *argv[])
BAREBOX_CMD_HELP_START(ethlog)
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT("-r", "remove log handler from Ethernet interface")
+BAREBOX_CMD_HELP_OPT("-p", "Enable promisc mode, or disable if -r is used")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(ethlog)
.cmd = do_ethlog,
BAREBOX_CMD_DESC("ETHLOG - tool to get dump of Ethernet packets")
- BAREBOX_CMD_OPTS("[-r] [device]")
+ BAREBOX_CMD_OPTS("[-rp] [device]")
BAREBOX_CMD_GROUP(CMD_GRP_NET)
BAREBOX_CMD_COMPLETE(eth_complete)
BAREBOX_CMD_END
diff --git a/drivers/net/dsa.c b/drivers/net/dsa.c
index 040ba897e2..bc33892f39 100644
--- a/drivers/net/dsa.c
+++ b/drivers/net/dsa.c
@@ -59,7 +59,7 @@ static int dsa_port_probe(struct eth_device *edev)
int ret;
if (ops->port_probe) {
- interface = of_get_phy_mode(dp->dev.device_node);
+ interface = of_get_phy_mode(dp->dev->device_node);
ret = ops->port_probe(dp, dp->index, interface);
if (ret)
return ret;
@@ -93,7 +93,7 @@ static int dsa_port_start(struct eth_device *edev)
if (dp->enabled)
return -EBUSY;
- interface = of_get_phy_mode(dp->dev.device_node);
+ interface = of_get_phy_mode(dp->dev->device_node);
if (ops->port_pre_enable) {
/* In case of RMII interface we need to enable RMII clock
@@ -129,6 +129,11 @@ static int dsa_port_start(struct eth_device *edev)
return ret;
}
+ ret = eth_set_promisc(ds->edev_master, true);
+ if (ret)
+ dev_warn(ds->dev, "Failed to set promisc mode. Using different eth addresses may not work. %pe\n",
+ ERR_PTR(ret));
+
eth_open(ds->edev_master);
}
@@ -160,6 +165,7 @@ static void dsa_port_stop(struct eth_device *edev)
ops->port_disable(dpc, ds->cpu_port,
ds->cpu_port_fixed_phy);
+ eth_set_promisc(ds->edev_master, false);
eth_close(ds->edev_master);
}
}
@@ -235,21 +241,13 @@ static int dsa_switch_register_edev(struct dsa_switch *ds,
struct eth_device *edev;
struct device_d *dev;
struct dsa_port *dp;
- int ret;
ds->dp[port] = xzalloc(sizeof(*dp));
-
dp = ds->dp[port];
- dev = &dp->dev;
- dev_set_name(dev, "dsa_port");
- dev->id = DEVICE_ID_DYNAMIC;
- dev->parent = ds->dev;
- dev->device_node = dn;
-
- ret = register_device(dev);
- if (ret)
- return ret;
+ dev = of_platform_device_create(dn, ds->dev);
+ of_platform_device_dummy_drv(dev);
+ dp->dev = dev;
dp->rx_buf = xmalloc(DSA_PKTSIZE);
dp->ds = ds;
diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c
index 673555a48a..a2fc02d6f9 100644
--- a/drivers/net/fec_imx.c
+++ b/drivers/net/fec_imx.c
@@ -25,6 +25,22 @@
#include "fec_imx.h"
+static int fec_set_promisc(struct eth_device *edev, bool enable)
+{
+ struct fec_priv *fec = (struct fec_priv *)edev->priv;
+ u32 rcntl;
+
+ rcntl = readl(fec->regs + FEC_R_CNTRL);
+
+ if (enable)
+ rcntl |= FEC_R_CNTRL_PROMISC;
+ else
+ rcntl &= ~FEC_R_CNTRL_PROMISC;
+
+ writel(rcntl, fec->regs + FEC_R_CNTRL);
+
+ return 0;
+}
/*
* MII-interface related functions
@@ -257,10 +273,15 @@ static int fec_init(struct eth_device *dev)
*/
writel(0x00000000, fec->regs + FEC_IMASK);
+ rcntl = readl(fec->regs + FEC_R_CNTRL);
+
+ /* Keep promisc setting */
+ rcntl &= FEC_R_CNTRL_PROMISC;
+
/*
* Set FEC-Lite receive control register(R_CNTRL):
*/
- rcntl = FEC_R_CNTRL_MAX_FL(1518);
+ rcntl |= FEC_R_CNTRL_MAX_FL(1518);
rcntl |= FEC_R_CNTRL_MII_MODE;
/*
@@ -768,6 +789,7 @@ static int fec_probe(struct device_d *dev)
edev->halt = fec_halt;
edev->get_ethaddr = fec_get_hwaddr;
edev->set_ethaddr = fec_set_hwaddr;
+ edev->set_promisc = fec_set_promisc;
edev->parent = dev;
dma_set_mask(dev, DMA_BIT_MASK(32));
@@ -834,6 +856,8 @@ static int fec_probe(struct device_d *dev)
if (ret)
goto free_gpio;
+ fec_set_promisc(edev, false);
+
/*
* reserve memory for both buffer descriptor chains at once
* Datasheet forces the startaddress of each chain is 16 byte aligned
diff --git a/drivers/net/fec_imx.h b/drivers/net/fec_imx.h
index 316eefe48f..9bb1c64b55 100644
--- a/drivers/net/fec_imx.h
+++ b/drivers/net/fec_imx.h
@@ -58,6 +58,7 @@
#define FEC_R_CNTRL_RMII_10T (1 << 9) /* i.MX28 specific */
#define FEC_R_CNTRL_RMII_MODE (1 << 8) /* i.MX28 specific */
#define FEC_R_CNTRL_FCE (1 << 5)
+#define FEC_R_CNTRL_PROMISC (1 << 3)
#define FEC_R_CNTRL_MII_MODE (1 << 2)
#define FEC_IEVENT_HBERR 0x80000000 /* Note: Not on i.MX28 */
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index 28a3534bcf..2d7114e5b1 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -427,6 +427,25 @@ static int asix_set_ethaddr(struct eth_device *edev, const unsigned char *adr)
return 0;
}
+static int asix_set_promisc(struct eth_device *edev, bool enable)
+{
+ struct usbnet *dev = container_of(edev, struct usbnet, edev);
+ u16 rx_ctl;
+ int ret;
+
+ rx_ctl = asix_read_rx_ctl(dev);
+
+ if (enable)
+ rx_ctl |= AX_RX_CTL_PRO;
+ else
+ rx_ctl &= ~AX_RX_CTL_PRO;
+
+ if ((ret = asix_write_rx_ctl(dev, rx_ctl)) < 0)
+ return ret;
+
+ return 0;
+}
+
static int ax88172_get_ethaddr(struct eth_device *edev, unsigned char *adr)
{
struct usbnet *udev = container_of(edev, struct usbnet, edev);
@@ -664,6 +683,7 @@ static int ax88772_bind(struct usbnet *dev)
dev->edev.get_ethaddr = asix_get_ethaddr;
dev->edev.set_ethaddr = asix_set_ethaddr;
+ dev->edev.set_promisc = asix_set_promisc;
asix_init_mii(dev);
if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0)
diff --git a/include/dsa.h b/include/dsa.h
index 75a939f2cb..f428aa74a5 100644
--- a/include/dsa.h
+++ b/include/dsa.h
@@ -58,7 +58,7 @@ struct dsa_ops {
};
struct dsa_port {
- struct device_d dev;
+ struct device_d *dev;
struct dsa_switch *ds;
unsigned int index;
struct eth_device edev;
diff --git a/include/net.h b/include/net.h
index 338033d698..f9d1fbfc18 100644
--- a/include/net.h
+++ b/include/net.h
@@ -49,6 +49,8 @@ struct eth_device {
int *length);
void (*rx_monitor) (struct eth_device*, void *packet, int length);
void (*tx_monitor) (struct eth_device*, void *packet, int length);
+ /* Set promiscuous mode */
+ int (*set_promisc) (struct eth_device*, bool enable);
struct eth_device *next;
void *priv;
@@ -113,6 +115,7 @@ int eth_send(struct eth_device *edev, void *packet, int length); /* Send a pa
int eth_rx(void); /* Check for received packets */
void eth_open_all(void);
struct eth_device *of_find_eth_device_by_node(struct device_node *np);
+int eth_set_promisc(struct eth_device *edev, bool enable);
/* associate a MAC address to a ethernet device. Should be called by
* board code for boards which store their MAC address at some unusual
diff --git a/net/eth.c b/net/eth.c
index 8f6ff7db3a..19654cdd51 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -31,6 +31,14 @@ struct eth_ethaddr {
static LIST_HEAD(ethaddr_list);
+int eth_set_promisc(struct eth_device *edev, bool enable)
+{
+ if (!edev->set_promisc)
+ return -EOPNOTSUPP;
+
+ return edev->set_promisc(edev, enable);
+}
+
int eth_set_ethaddr(struct eth_device *edev, const char *ethaddr)
{
int ret;