net: tftp: use IS_ENABLED(CONFIG_NET_TFTP_VARS) instead of #if
[platform/kernel/u-boot.git] / net / dsa-uclass.c
index 88a8ea9..5b70464 100644 (file)
@@ -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;
 }