diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2022-11-14 16:54:38 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2022-11-14 16:54:38 +0100 |
commit | af3ab6492459a70f9fe572c3a42e6cdb6cbc44c4 (patch) | |
tree | 5d02d19f76ea5ac1b2502fb8311983ad220a52e3 | |
parent | 66544641b2dd00c37e16d8e1ac39a34ec4e57cb8 (diff) | |
parent | ff9c801b9e807fd3b429849e654725591a3d1eb8 (diff) | |
download | barebox-af3ab6492459a70f9fe572c3a42e6cdb6cbc44c4.tar.gz barebox-af3ab6492459a70f9fe572c3a42e6cdb6cbc44c4.tar.xz |
Merge branch 'for-next/promisc'
-rw-r--r-- | arch/arm/boards/skov-imx6/board.c | 105 | ||||
-rw-r--r-- | commands/ethlog.c | 21 | ||||
-rw-r--r-- | drivers/net/dsa.c | 24 | ||||
-rw-r--r-- | drivers/net/fec_imx.c | 26 | ||||
-rw-r--r-- | drivers/net/fec_imx.h | 1 | ||||
-rw-r--r-- | drivers/net/usb/asix.c | 20 | ||||
-rw-r--r-- | include/dsa.h | 2 | ||||
-rw-r--r-- | include/net.h | 3 | ||||
-rw-r--r-- | net/eth.c | 8 |
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 @@ -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; |