From a02dcbbb5a8e24a3f6cd3e7f158e1953b82d5e2e Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Wed, 24 Feb 2021 17:40:39 +0100 Subject: net: dsa: return early if there is no master It doesn't make sense to have DSA without a master port. Error out early if there is no master port. Fixes: fc054d563bfb ("net: Introduce DSA class for Ethernet switches") Signed-off-by: Michael Walle Reviewed-by: Vladimir Oltean Reviewed-by: Ramon Fried Reviewed-by: Priyanka Jain --- 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 2ce9ddb90d2..88a8ea93520 100644 --- a/net/dsa-uclass.c +++ b/net/dsa-uclass.c @@ -280,6 +280,10 @@ static int dsa_port_probe(struct udevice *pdev) if (!port_pdata->phy) return -ENODEV; + master = dsa_get_master(dev); + if (!master) + return -ENODEV; + /* * Inherit port's hwaddr from the DSA master, unless the port already * has a unique MAC address specified in the environment. @@ -288,10 +292,6 @@ static int dsa_port_probe(struct udevice *pdev) if (!is_zero_ethaddr(env_enetaddr)) return 0; - master = dsa_get_master(dev); - if (!master) - return 0; - master_pdata = dev_get_plat(master); eth_pdata = dev_get_plat(pdev); memcpy(eth_pdata->enetaddr, master_pdata->enetaddr, ARP_HLEN); -- cgit v1.2.3 From e5d7d119287ed1bc867e77225660c1ac9bb51072 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Wed, 24 Feb 2021 17:40:40 +0100 Subject: net: dsa: probe master device DSA needs to have the master device probed first for MAC inheritance. Until now, it only works by chance because the only user (LS1028A SoC) will probe the master device first. The probe order is given by the PCI device ordering, thus it works because the master device has a "smaller" BDF then the switch device. Explicitly probe the master device in dsa_port_probe(). Fixes: fc054d563bfb ("net: Introduce DSA class for Ethernet switches") Signed-off-by: Michael Walle Reviewed-by: Vladimir Oltean Reviewed-by: Ramon Fried Reviewed-by: Priyanka Jain --- net/dsa-uclass.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'net/dsa-uclass.c') diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c index 88a8ea93520..7898f30e150 100644 --- a/net/dsa-uclass.c +++ b/net/dsa-uclass.c @@ -272,6 +272,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; port_pdata = dev_get_parent_plat(pdev); dsa_priv = dev_get_uclass_priv(dev); @@ -284,6 +285,14 @@ static int dsa_port_probe(struct udevice *pdev) if (!master) return -ENODEV; + /* + * Probe the master device. We depend on the master device for proper + * operation and we also need it for MAC inheritance below. + */ + ret = device_probe(master); + if (ret) + return ret; + /* * Inherit port's hwaddr from the DSA master, unless the port already * has a unique MAC address specified in the environment. -- cgit v1.2.3 From 108157c468eed8291c866415b8708eb2a8735dc4 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Wed, 24 Feb 2021 17:40:41 +0100 Subject: net: dsa: remove NULL check for priv and platform data Because the uclass has the "*_auto" properties set, the driver model will take care of allocating the private structures for us and they can't be NULL. Drop the checks. Signed-off-by: Michael Walle Reviewed-by: Vladimir Oltean Reviewed-by: Ramon Fried Reviewed-by: Priyanka Jain --- net/dsa-uclass.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'net/dsa-uclass.c') diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c index 7898f30e150..d453cc6930e 100644 --- a/net/dsa-uclass.c +++ b/net/dsa-uclass.c @@ -28,8 +28,8 @@ int dsa_set_tagging(struct udevice *dev, ushort headroom, ushort tailroom) { struct dsa_priv *priv; - if (!dev || !dev_get_uclass_priv(dev)) - return -ENODEV; + if (!dev) + return -EINVAL; if (headroom + tailroom > DSA_MAX_OVR) return -EINVAL; @@ -47,11 +47,13 @@ int dsa_set_tagging(struct udevice *dev, ushort headroom, ushort tailroom) /* returns the DSA master Ethernet device */ struct udevice *dsa_get_master(struct udevice *dev) { - struct dsa_priv *priv = dev_get_uclass_priv(dev); + struct dsa_priv *priv; - if (!priv) + if (!dev) return NULL; + priv = dev_get_uclass_priv(dev); + return priv->master_dev; } @@ -67,9 +69,6 @@ static int dsa_port_start(struct udevice *pdev) struct dsa_ops *ops = dsa_get_ops(dev); int err; - if (!priv) - return -ENODEV; - if (!master) { dev_err(pdev, "DSA master Ethernet device not found!\n"); return -EINVAL; @@ -101,9 +100,6 @@ static void dsa_port_stop(struct udevice *pdev) struct udevice *master = dsa_get_master(dev); struct dsa_ops *ops = dsa_get_ops(dev); - if (!priv) - return; - if (ops->port_disable) { struct dsa_port_pdata *port_pdata; @@ -347,7 +343,7 @@ static int dsa_post_bind(struct udevice *dev) ofnode node = dev_ofnode(dev), pnode; int i, err, first_err = 0; - if (!pdata || !ofnode_valid(node)) + if (!ofnode_valid(node)) return -ENODEV; pdata->master_node = ofnode_null(); @@ -459,9 +455,6 @@ static int dsa_pre_probe(struct udevice *dev) struct dsa_pdata *pdata = dev_get_uclass_plat(dev); struct dsa_priv *priv = dev_get_uclass_priv(dev); - if (!pdata || !priv) - return -ENODEV; - priv->num_ports = pdata->num_ports; priv->cpu_port = pdata->cpu_port; priv->cpu_port_fixed_phy = fixed_phy_create(pdata->cpu_port_node); -- cgit v1.2.3 From 714555374f2ff889cecbde62938a17e9678a0f09 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Wed, 24 Feb 2021 17:40:42 +0100 Subject: net: dsa: remove master santiy check Because we probe the master ourselves (and fail if there is no master), it is not possible that we don't have a master device. There is one catch though: device removal. We don't support that. It wasn't supported neither before this patch. Because the master device was only set in .pre_probe(), if a device was removed master_dev was a dangling pointer and transmitting a frame cause a panic. I don't see a good solution without having some sort of notify machanism when a udevice is removed. Signed-off-by: Michael Walle Reviewed-by: Vladimir Oltean Tested-by: Michael Walle [DSA unit tests] Reviewed-by: Priyanka Jain --- net/dsa-uclass.c | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) (limited to 'net/dsa-uclass.c') diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c index d453cc6930e..7ea1cb6949c 100644 --- a/net/dsa-uclass.c +++ b/net/dsa-uclass.c @@ -69,11 +69,6 @@ static int dsa_port_start(struct udevice *pdev) struct dsa_ops *ops = dsa_get_ops(dev); int err; - if (!master) { - dev_err(pdev, "DSA master Ethernet device not found!\n"); - return -EINVAL; - } - if (ops->port_enable) { struct dsa_port_pdata *port_pdata; @@ -108,13 +103,7 @@ static void dsa_port_stop(struct udevice *pdev) ops->port_disable(dev, priv->cpu_port, NULL); } - /* - * stop master only if it's active, don't probe it otherwise. - * Under normal usage it would be active because we're using it, but - * during tear-down it may have been removed ahead of us. - */ - if (master && device_active(master)) - eth_get_ops(master)->stop(master); + eth_get_ops(master)->stop(master); } /* @@ -133,9 +122,6 @@ static int dsa_port_send(struct udevice *pdev, void *packet, int length) struct dsa_port_pdata *port_pdata; int err; - if (!master) - return -EINVAL; - if (length + head + tail > PKTSIZE_ALIGN) return -EINVAL; @@ -165,9 +151,6 @@ static int dsa_port_recv(struct udevice *pdev, int flags, uchar **packetp) struct dsa_port_pdata *port_pdata; int length, port_index, err; - if (!master) - return -EINVAL; - length = eth_get_ops(master)->recv(master, flags, packetp); if (length <= 0) return length; @@ -201,9 +184,6 @@ static int dsa_port_free_pkt(struct udevice *pdev, uchar *packet, int length) struct udevice *master = dsa_get_master(dev); struct dsa_priv *priv; - if (!master) - return -EINVAL; - priv = dev_get_uclass_priv(dev); if (eth_get_ops(master)->free_pkt) { /* return the original pointer and length to master Eth */ @@ -284,6 +264,9 @@ static int dsa_port_probe(struct udevice *pdev) /* * Probe the master device. We depend on the master device for proper * operation and we also need it for MAC inheritance below. + * + * TODO: we assume the master device is always there and doesn't get + * removed during runtime. */ ret = device_probe(master); if (ret) -- cgit v1.2.3