summaryrefslogtreecommitdiffstats
path: root/drivers/net/dsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/dsa.c')
-rw-r--r--drivers/net/dsa.c89
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;