From f4b712b840dd5fe0b984aadfe466c1886a31e906 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 24 Aug 2021 15:00:39 +0300 Subject: net: dsa: use "err" instead of "ret" in dsa_port_probe DM DSA uses "err" for error code values, so use this consistently. Signed-off-by: Vladimir Oltean Reviewed-by: Ramon Fried Tested-by: Michael Walle --- net/dsa-uclass.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net/dsa-uclass.c') diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c index 694664d81b..f279ca7d2d 100644 --- a/net/dsa-uclass.c +++ b/net/dsa-uclass.c @@ -248,7 +248,7 @@ static int dsa_port_probe(struct udevice *pdev) struct dsa_port_pdata *port_pdata; struct dsa_priv *dsa_priv; struct udevice *master; - int ret; + int err; port_pdata = dev_get_parent_plat(pdev); dsa_priv = dev_get_uclass_priv(dev); @@ -268,9 +268,9 @@ static int dsa_port_probe(struct udevice *pdev) * TODO: we assume the master device is always there and doesn't get * removed during runtime. */ - ret = device_probe(master); - if (ret) - return ret; + err = device_probe(master); + if (err) + return err; /* * Inherit port's hwaddr from the DSA master, unless the port already -- cgit v1.2.3 From 5eee5ab91638c4482dd59ff511feefd3b15a2472 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 24 Aug 2021 15:00:40 +0300 Subject: net: dsa: refactor the code to set the port MAC address into a dedicated function This snippet of code has a bothering "if (...) return 0" in it which assumes it is the last piece of code running in dsa_port_probe(). This makes it difficult to add further code at the end of dsa_port_probe() which does not depend on MAC address stuff. So move the code to a dedicated function which returns void and let the code flow through. Signed-off-by: Vladimir Oltean Reviewed-by: Ramon Fried Tested-by: Michael Walle --- net/dsa-uclass.c | 50 ++++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 22 deletions(-) (limited to 'net/dsa-uclass.c') diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c index f279ca7d2d..dbd8558b64 100644 --- a/net/dsa-uclass.c +++ b/net/dsa-uclass.c @@ -240,11 +240,36 @@ static const struct eth_ops dsa_port_ops = { .free_pkt = dsa_port_free_pkt, }; -static int dsa_port_probe(struct udevice *pdev) +/* + * Inherit port's hwaddr from the DSA master, unless the port already has a + * unique MAC address specified in the environment. + */ +static void dsa_port_set_hwaddr(struct udevice *pdev, struct udevice *master) { - struct udevice *dev = dev_get_parent(pdev); struct eth_pdata *eth_pdata, *master_pdata; unsigned char env_enetaddr[ARP_HLEN]; + + eth_env_get_enetaddr_by_index("eth", dev_seq(pdev), env_enetaddr); + if (!is_zero_ethaddr(env_enetaddr)) { + /* individual port mac addrs require master to be promisc */ + struct eth_ops *eth_ops = eth_get_ops(master); + + if (eth_ops->set_promisc) + eth_ops->set_promisc(master, 1); + + return; + } + + master_pdata = dev_get_plat(master); + eth_pdata = dev_get_plat(pdev); + memcpy(eth_pdata->enetaddr, master_pdata->enetaddr, ARP_HLEN); + eth_env_set_enetaddr_by_index("eth", dev_seq(pdev), + master_pdata->enetaddr); +} + +static int dsa_port_probe(struct udevice *pdev) +{ + struct udevice *dev = dev_get_parent(pdev); struct dsa_port_pdata *port_pdata; struct dsa_priv *dsa_priv; struct udevice *master; @@ -272,26 +297,7 @@ static int dsa_port_probe(struct udevice *pdev) if (err) return err; - /* - * Inherit port's hwaddr from the DSA master, unless the port already - * has a unique MAC address specified in the environment. - */ - eth_env_get_enetaddr_by_index("eth", dev_seq(pdev), env_enetaddr); - if (!is_zero_ethaddr(env_enetaddr)) { - /* individual port mac addrs require master to be promisc */ - struct eth_ops *eth_ops = eth_get_ops(master); - - if (eth_ops->set_promisc) - eth_ops->set_promisc(master, 1); - - return 0; - } - - master_pdata = dev_get_plat(master); - eth_pdata = dev_get_plat(pdev); - memcpy(eth_pdata->enetaddr, master_pdata->enetaddr, ARP_HLEN); - eth_env_set_enetaddr_by_index("eth", dev_seq(pdev), - master_pdata->enetaddr); + dsa_port_set_hwaddr(pdev, master); return 0; } -- cgit v1.2.3 From 4b46e8388549bd0e52ec742c7e5ed71e0edc1b9f Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 24 Aug 2021 15:00:41 +0300 Subject: net: dsa: introduce a .port_probe() method in struct dsa_ops Some drivers might want to execute code for each port at probe time, as opposed to executing code just-in-time for the port selected for networking. To cater to that use case, introduce a .port_probe() callback method into the DSA switch operations which is called for each available port, at the end of dsa_port_probe(). Signed-off-by: Vladimir Oltean Reviewed-by: Ramon Fried Tested-by: Michael Walle --- include/net/dsa.h | 5 ++++- net/dsa-uclass.c | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'net/dsa-uclass.c') diff --git a/include/net/dsa.h b/include/net/dsa.h index 0f31a908c9..ab2a9dfbea 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -57,7 +57,8 @@ /** * struct dsa_ops - DSA operations * - * @port_enable: Initialize a switch port for I/O. + * @port_probe: Initialize a switch port. + * @port_enable: Enable I/O for a port. * @port_disable: Disable I/O for a port. * @xmit: Insert the DSA tag for transmission. * DSA drivers receive a copy of the packet with headroom and @@ -69,6 +70,8 @@ * master including any additional headers. */ struct dsa_ops { + int (*port_probe)(struct udevice *dev, int port, + struct phy_device *phy); int (*port_enable)(struct udevice *dev, int port, struct phy_device *phy); void (*port_disable)(struct udevice *dev, int port, diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c index dbd8558b64..9b8ae1e82b 100644 --- a/net/dsa-uclass.c +++ b/net/dsa-uclass.c @@ -270,6 +270,7 @@ static void dsa_port_set_hwaddr(struct udevice *pdev, struct udevice *master) static int dsa_port_probe(struct udevice *pdev) { struct udevice *dev = dev_get_parent(pdev); + struct dsa_ops *ops = dsa_get_ops(dev); struct dsa_port_pdata *port_pdata; struct dsa_priv *dsa_priv; struct udevice *master; @@ -299,6 +300,13 @@ static int dsa_port_probe(struct udevice *pdev) dsa_port_set_hwaddr(pdev, master); + if (ops->port_probe) { + err = ops->port_probe(dev, port_pdata->index, + port_pdata->phy); + if (err) + return err; + } + return 0; } -- cgit v1.2.3 From 5cc283b781398a02c8a7c919cf4d5dbb5fa8add2 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sat, 18 Sep 2021 14:49:55 +0300 Subject: net: dsa: pass CPU port fixed PHY to .port_disable While adding the logic for DSA to register a fixed-link PHY for the CPU port, I forgot to pass it to the .port_disable method too, just .port_enable. Bug had no impact for felix_switch.c, due to the phy argument not being used, but ksz9477.c does use it => NULL pointer dereference. Fixes: fc054d563bfb ("net: Introduce DSA class for Ethernet switches") Signed-off-by: Vladimir Oltean Reviewed-by: Ramon Fried --- net/dsa-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/dsa-uclass.c') diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c index 9b8ae1e82b..d1c6c78acd 100644 --- a/net/dsa-uclass.c +++ b/net/dsa-uclass.c @@ -100,7 +100,7 @@ static void dsa_port_stop(struct udevice *pdev) port_pdata = dev_get_parent_plat(pdev); ops->port_disable(dev, port_pdata->index, port_pdata->phy); - ops->port_disable(dev, priv->cpu_port, NULL); + ops->port_disable(dev, priv->cpu_port, priv->cpu_port_fixed_phy); } eth_get_ops(master)->stop(master); -- cgit v1.2.3 From 5ecdf0a5a42ae3b2d04cdf0c2ad6314670839037 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sat, 18 Sep 2021 14:49:56 +0300 Subject: net: dsa: remove unused variables "dev" and "dsa_pdata" are unused inside dsa_port_of_to_pdata. "dsa_priv" is unused inside dsa_port_probe. Signed-off-by: Vladimir Oltean Reviewed-by: Ramon Fried --- net/dsa-uclass.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'net/dsa-uclass.c') diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c index d1c6c78acd..8a2918816e 100644 --- a/net/dsa-uclass.c +++ b/net/dsa-uclass.c @@ -199,9 +199,7 @@ static int dsa_port_free_pkt(struct udevice *pdev, uchar *packet, int length) static int dsa_port_of_to_pdata(struct udevice *pdev) { struct dsa_port_pdata *port_pdata; - struct dsa_pdata *dsa_pdata; struct eth_pdata *eth_pdata; - struct udevice *dev; const char *label; u32 index; int err; @@ -213,9 +211,6 @@ static int dsa_port_of_to_pdata(struct udevice *pdev) if (err) return err; - dev = dev_get_parent(pdev); - dsa_pdata = dev_get_uclass_plat(dev); - port_pdata = dev_get_parent_plat(pdev); port_pdata->index = index; @@ -272,12 +267,10 @@ static int dsa_port_probe(struct udevice *pdev) struct udevice *dev = dev_get_parent(pdev); struct dsa_ops *ops = dsa_get_ops(dev); struct dsa_port_pdata *port_pdata; - struct dsa_priv *dsa_priv; struct udevice *master; int err; port_pdata = dev_get_parent_plat(pdev); - dsa_priv = dev_get_uclass_priv(dev); port_pdata->phy = dm_eth_phy_connect(pdev); if (!port_pdata->phy) @@ -312,12 +305,7 @@ static int dsa_port_probe(struct udevice *pdev) static int dsa_port_remove(struct udevice *pdev) { - struct udevice *dev = dev_get_parent(pdev); - struct dsa_port_pdata *port_pdata; - struct dsa_priv *dsa_priv; - - port_pdata = dev_get_parent_plat(pdev); - dsa_priv = dev_get_uclass_priv(dev); + struct dsa_port_pdata *port_pdata = dev_get_parent_plat(pdev); port_pdata->phy = NULL; -- cgit v1.2.3 From 4fdc7e3530eb49dfe0aca79746b1cda30e94c591 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 27 Sep 2021 14:22:03 +0300 Subject: net: dsa: ensure port names are NULL-terminated after DSA_PORT_NAME_LENGTH truncation strncpy() simply bails out when copying a source string whose size exceeds the destination string size, potentially leaving the destination string unterminated. One possible way to address is to pass DSA_PORT_NAME_LENGTH - 1 and a previously zero-initialized destination string, but this is more difficult to maintain. The chosen alternative is to use strlcpy(), which properly limits the copy len in the (srclen >= size) case to "size - 1", and which is also more efficient than the strncpy() byte-by-byte implementation by using memcpy. The destination string returned by strlcpy() is always NULL terminated. Signed-off-by: Vladimir Oltean Reviewed-by: Ramon Fried --- net/dsa-uclass.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/dsa-uclass.c') diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c index 8a2918816e..bf762cd2a8 100644 --- a/net/dsa-uclass.c +++ b/net/dsa-uclass.c @@ -216,7 +216,7 @@ static int dsa_port_of_to_pdata(struct udevice *pdev) label = ofnode_read_string(dev_ofnode(pdev), "label"); if (label) - strncpy(port_pdata->name, label, DSA_PORT_NAME_LENGTH); + strlcpy(port_pdata->name, label, DSA_PORT_NAME_LENGTH); eth_pdata = dev_get_plat(pdev); eth_pdata->priv_pdata = port_pdata; @@ -421,7 +421,7 @@ static int dsa_post_bind(struct udevice *dev) struct dsa_port_pdata *port_pdata; port_pdata = dev_get_parent_plat(pdev); - strncpy(port_pdata->name, name, DSA_PORT_NAME_LENGTH); + strlcpy(port_pdata->name, name, DSA_PORT_NAME_LENGTH); pdev->name = port_pdata->name; } -- cgit v1.2.3