X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=net%2Fdsa-uclass.c;h=5b7046432ff3980aba1098fba9ca501745723728;hb=4b8c44e39c9eb1717831e3b3f31c33e0932b0767;hp=88a8ea93520247d861b9dad5f7a4d1f00da1999c;hpb=a02dcbbb5a8e24a3f6cd3e7f158e1953b82d5e2e;p=platform%2Fkernel%2Fu-boot.git diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c index 88a8ea9..5b70464 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; @@ -44,14 +44,36 @@ int dsa_set_tagging(struct udevice *dev, ushort headroom, ushort tailroom) return 0; } +ofnode dsa_port_get_ofnode(struct udevice *dev, int port) +{ + struct dsa_pdata *pdata = dev_get_uclass_plat(dev); + struct dsa_port_pdata *port_pdata; + struct udevice *pdev; + + if (port == pdata->cpu_port) + return pdata->cpu_port_node; + + for (device_find_first_child(dev, &pdev); + pdev; + device_find_next_child(&pdev)) { + port_pdata = dev_get_parent_plat(pdev); + if (port_pdata->index == port) + return dev_ofnode(pdev); + } + + return ofnode_null(); +} + /* 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,14 +89,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; - } - if (ops->port_enable) { struct dsa_port_pdata *port_pdata; @@ -101,24 +115,15 @@ 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; 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); } - /* - * 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); } /* @@ -137,9 +142,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; @@ -169,9 +171,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; @@ -205,9 +204,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 */ @@ -223,9 +219,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; @@ -237,15 +231,12 @@ 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; 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; @@ -264,17 +255,42 @@ 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, true); + + 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_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) @@ -285,30 +301,31 @@ static int dsa_port_probe(struct udevice *pdev) return -ENODEV; /* - * Inherit port's hwaddr from the DSA master, unless the port already - * has a unique MAC address specified in the environment. + * 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. */ - eth_env_get_enetaddr_by_index("eth", dev_seq(pdev), env_enetaddr); - if (!is_zero_ethaddr(env_enetaddr)) - return 0; + err = device_probe(master); + if (err) + return err; - 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); + + if (ops->port_probe) { + err = ops->port_probe(dev, port_pdata->index, + port_pdata->phy); + if (err) + return err; + } return 0; } 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; @@ -338,7 +355,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(); @@ -415,7 +432,7 @@ static int dsa_post_bind(struct udevice *dev) * skip registration if port id not found or if the port * is explicitly disabled in DT */ - if (!ofnode_valid(pnode) || !ofnode_is_available(pnode)) + if (!ofnode_valid(pnode) || !ofnode_is_enabled(pnode)) continue; err = device_bind_driver_to_node(dev, DSA_PORT_CHILD_DRV_NAME, @@ -424,7 +441,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; } @@ -449,9 +466,8 @@ 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; + struct dsa_ops *ops = dsa_get_ops(dev); + int err; priv->num_ports = pdata->num_ports; priv->cpu_port = pdata->cpu_port; @@ -461,8 +477,19 @@ static int dsa_pre_probe(struct udevice *dev) return -ENODEV; } - uclass_find_device_by_ofnode(UCLASS_ETH, pdata->master_node, - &priv->master_dev); + err = uclass_get_device_by_ofnode(UCLASS_ETH, pdata->master_node, + &priv->master_dev); + if (err) + return err; + + /* Simulate a probing event for the CPU port */ + if (ops->port_probe) { + err = ops->port_probe(dev, priv->cpu_port, + priv->cpu_port_fixed_phy); + if (err) + return err; + } + return 0; }