diff options
Diffstat (limited to 'drivers/net/dsa.c')
-rw-r--r-- | drivers/net/dsa.c | 89 |
1 files changed, 51 insertions, 38 deletions
diff --git a/drivers/net/dsa.c b/drivers/net/dsa.c index 7a64a79412..ccd7d87550 100644 --- a/drivers/net/dsa.c +++ b/drivers/net/dsa.c @@ -54,12 +54,12 @@ static int dsa_port_probe(struct eth_device *edev) { struct dsa_port *dp = edev->priv; struct dsa_switch *ds = dp->ds; - const struct dsa_ops *ops = ds->ops; + const struct dsa_switch_ops *ops = ds->ops; phy_interface_t interface; int ret; if (ops->port_probe) { - interface = of_get_phy_mode(dp->dev.device_node); + interface = of_get_phy_mode(dp->dev->of_node); ret = ops->port_probe(dp, dp->index, interface); if (ret) return ret; @@ -86,14 +86,14 @@ static int dsa_port_start(struct eth_device *edev) { struct dsa_port *dp = edev->priv; struct dsa_switch *ds = dp->ds; - const struct dsa_ops *ops = ds->ops; + const struct dsa_switch_ops *ops = ds->ops; phy_interface_t interface; int ret; if (dp->enabled) return -EBUSY; - interface = of_get_phy_mode(dp->dev.device_node); + interface = of_get_phy_mode(dp->dev->of_node); if (ops->port_pre_enable) { /* In case of RMII interface we need to enable RMII clock @@ -104,17 +104,13 @@ static int dsa_port_start(struct eth_device *edev) return ret; } - ret = phy_device_connect(edev, ds->slave_mii_bus, dp->index, NULL, 0, - interface); + ret = phy_device_connect(edev, ds->slave_mii_bus, dp->index, + ops->adjust_link, 0, interface); if (ret) return ret; dsa_port_set_ethaddr(edev); - ret = phy_wait_aneg_done(dp->edev.phydev); - if (ret) - return ret; - if (ops->port_enable) { ret = ops->port_enable(dp, dp->index, dp->edev.phydev); if (ret) @@ -126,6 +122,16 @@ static int dsa_port_start(struct eth_device *edev) if (!ds->cpu_port_users) { struct dsa_port *dpc = ds->dp[ds->cpu_port]; + if (ops->port_pre_enable) { + /* In case of RMII interface we need to enable RMII clock + * before talking to the PHY. + */ + ret = ops->port_pre_enable(dpc, ds->cpu_port, + ds->cpu_port_fixed_phy->interface); + if (ret) + return ret; + } + if (ops->port_enable) { ret = ops->port_enable(dpc, ds->cpu_port, ds->cpu_port_fixed_phy); @@ -133,6 +139,11 @@ static int dsa_port_start(struct eth_device *edev) return ret; } + ret = eth_set_promisc(ds->edev_master, true); + if (ret) + dev_warn(ds->dev, "Failed to set promisc mode. Using different eth addresses may not work. %pe\n", + ERR_PTR(ret)); + eth_open(ds->edev_master); } @@ -146,7 +157,7 @@ static void dsa_port_stop(struct eth_device *edev) { struct dsa_port *dp = edev->priv; struct dsa_switch *ds = dp->ds; - const struct dsa_ops *ops = ds->ops; + const struct dsa_switch_ops *ops = ds->ops; if (!dp->enabled) return; @@ -164,6 +175,7 @@ static void dsa_port_stop(struct eth_device *edev) ops->port_disable(dpc, ds->cpu_port, ds->cpu_port_fixed_phy); + eth_set_promisc(ds->edev_master, false); eth_close(ds->edev_master); } } @@ -172,7 +184,7 @@ static int dsa_port_send(struct eth_device *edev, void *packet, int length) { struct dsa_port *dp = edev->priv; struct dsa_switch *ds = dp->ds; - const struct dsa_ops *ops = ds->ops; + const struct dsa_switch_ops *ops = ds->ops; void *tx_buf = ds->tx_buf; size_t full_length, stuff = 0; int ret; @@ -233,35 +245,36 @@ static int dsa_ether_get_ethaddr(struct eth_device *edev, unsigned char *adr) return edev_master->get_ethaddr(edev_master, adr); } -static int dsa_switch_register_edev(struct dsa_switch *ds, - struct device_node *dn, int port) +static struct dsa_port *dsa_port_alloc(struct dsa_switch *ds, + struct device_node *dn, int port) { - struct eth_device *edev; - struct device_d *dev; + struct device *dev; struct dsa_port *dp; - int ret; ds->dp[port] = xzalloc(sizeof(*dp)); - dp = ds->dp[port]; - dev = &dp->dev; - dev_set_name(dev, "dsa_port"); - dev->id = DEVICE_ID_DYNAMIC; - dev->parent = ds->dev; - dev->device_node = dn; + dev = of_platform_device_create(dn, ds->dev); + of_platform_device_dummy_drv(dev); + dp->dev = dev; + dp->ds = ds; + dp->index = port; - ret = register_device(dev); - if (ret) - return ret; + return dp; +} +static int dsa_switch_register_edev(struct dsa_switch *ds, + struct device_node *dn, int port) +{ + struct eth_device *edev; + struct dsa_port *dp; + + dp = dsa_port_alloc(ds, dn, port); dp->rx_buf = xmalloc(DSA_PKTSIZE); - dp->ds = ds; - dp->index = port; edev = &dp->edev; edev->priv = dp; - edev->parent = dev; + edev->parent = dp->dev; edev->init = dsa_port_probe; edev->open = dsa_port_start; edev->send = dsa_port_send; @@ -277,7 +290,7 @@ static int dsa_rx_preprocessor(struct eth_device *edev, unsigned char **packet, int *length) { struct dsa_switch *ds = edev->rx_preprocessor_priv; - const struct dsa_ops *ops = ds->ops; + const struct dsa_switch_ops *ops = ds->ops; struct dsa_port *dp; int ret, port; @@ -314,7 +327,6 @@ static int dsa_switch_register_master(struct dsa_switch *ds, { struct device_node *phy_node; struct phy_device *phydev; - struct dsa_port *dp; int ret; if (ds->edev_master) { @@ -345,9 +357,7 @@ static int dsa_switch_register_master(struct dsa_switch *ds, phydev->interface = of_get_phy_mode(np); - ds->dp[port] = xzalloc(sizeof(*dp)); - dp = ds->dp[port]; - dp->ds = ds; + dsa_port_alloc(ds, np, port); ds->cpu_port = port; ds->cpu_port_fixed_phy = phydev; @@ -390,8 +400,11 @@ static int dsa_switch_parse_ports_of(struct dsa_switch *ds, } master = of_parse_phandle(port, "ethernet", 0); - if (master) - dsa_switch_register_master(ds, port, master, reg); + if (master) { + ret = dsa_switch_register_master(ds, port, master, reg); + if (ret) + return ret; + } } /* Now we can register regular switch ports */ @@ -422,7 +435,7 @@ int dsa_register_switch(struct dsa_switch *ds) return -ENODEV; } - if (!ds->dev->device_node) + if (!ds->dev->of_node) return -ENODEV; if (!ds->num_ports || ds->num_ports > DSA_MAX_PORTS) { @@ -430,7 +443,7 @@ int dsa_register_switch(struct dsa_switch *ds) return -EINVAL; } - ret = dsa_switch_parse_ports_of(ds, ds->dev->device_node); + ret = dsa_switch_parse_ports_of(ds, ds->dev->of_node); if (ret) return ret; |