net: dsa: Ensure that port array elements are initialized before being used
[linux-drm-fsl-dcu.git] / net / dsa / slave.c
index 589aafd01fc5256a0fac138bac3240ab191b507e..5be4c928c9c994cfae7bd47a2a025d43335633d1 100644 (file)
@@ -521,10 +521,13 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
        struct device_node *phy_dn, *port_dn;
        bool phy_is_fixed = false;
        u32 phy_flags = 0;
-       int ret;
+       int mode, ret;
 
        port_dn = cd->port_dn[p->port];
-       p->phy_interface = of_get_phy_mode(port_dn);
+       mode = of_get_phy_mode(port_dn);
+       if (mode < 0)
+               mode = PHY_INTERFACE_MODE_NA;
+       p->phy_interface = mode;
 
        phy_dn = of_parse_phandle(port_dn, "phy-handle", 0);
        if (of_phy_is_fixed_link(port_dn)) {
@@ -559,6 +562,8 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
                if (!p->phy)
                        return -ENODEV;
 
+               /* Use already configured phy mode */
+               p->phy_interface = p->phy->interface;
                phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
                                   p->phy_interface);
        } else {
@@ -600,9 +605,8 @@ int dsa_slave_resume(struct net_device *slave_dev)
        return 0;
 }
 
-struct net_device *
-dsa_slave_create(struct dsa_switch *ds, struct device *parent,
-                int port, char *name)
+int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
+                    int port, char *name)
 {
        struct net_device *master = ds->dst->master_netdev;
        struct net_device *slave_dev;
@@ -612,7 +616,7 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent,
        slave_dev = alloc_netdev(sizeof(struct dsa_slave_priv), name,
                                 NET_NAME_UNKNOWN, ether_setup);
        if (slave_dev == NULL)
-               return slave_dev;
+               return -ENOMEM;
 
        slave_dev->features = master->vlan_features;
        slave_dev->ethtool_ops = &dsa_slave_ethtool_ops;
@@ -662,32 +666,21 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent,
        ret = dsa_slave_phy_setup(p, slave_dev);
        if (ret) {
                free_netdev(slave_dev);
-               return NULL;
+               return ret;
        }
 
+       ds->ports[port] = slave_dev;
        ret = register_netdev(slave_dev);
        if (ret) {
                netdev_err(master, "error %d registering interface %s\n",
                           ret, slave_dev->name);
                phy_disconnect(p->phy);
+               ds->ports[port] = NULL;
                free_netdev(slave_dev);
-               return NULL;
+               return ret;
        }
 
        netif_carrier_off(slave_dev);
 
-       if (p->phy != NULL) {
-               if (ds->drv->get_phy_flags)
-                       p->phy->dev_flags |= ds->drv->get_phy_flags(ds, port);
-
-               phy_attach(slave_dev, dev_name(&p->phy->dev),
-                          PHY_INTERFACE_MODE_GMII);
-
-               p->phy->autoneg = AUTONEG_ENABLE;
-               p->phy->speed = 0;
-               p->phy->duplex = 0;
-               p->phy->advertising = p->phy->supported | ADVERTISED_Autoneg;
-       }
-
-       return slave_dev;
+       return 0;
 }