Merge branch 'dsa-multi-swtich'
Andrew Lunn says: ==================== D in DSA patches The D in DSA is distributed, meaning multiple switches can be connected together. Currently no mainline system does this, and so the code is broken. This patchset contains two fixes, and a small helper. With three of more switches, the current device tree binding is not sufficient to express the routing between the switches. The first patch extends the binding, in a backwards compatible way, to allow a link between a switch to describe all the switches accessible over the link, not just the direct neighbor. The third patch fixes the port configuration on newer devices for links connecting switches. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
3f0bf60f96
|
@ -44,9 +44,10 @@ Note that a port labelled "dsa" will imply checking for the uplink phandle
|
||||||
described below.
|
described below.
|
||||||
|
|
||||||
Optionnal property:
|
Optionnal property:
|
||||||
- link : Should be a phandle to another switch's DSA port.
|
- link : Should be a list of phandles to another switch's DSA port.
|
||||||
This property is only used when switches are being
|
This property is only used when switches are being
|
||||||
chained/cascaded together.
|
chained/cascaded together. This port is used as outgoing port
|
||||||
|
towards the phandle port, which can be more than one hop away.
|
||||||
|
|
||||||
- phy-handle : Phandle to a PHY on an external MDIO bus, not the
|
- phy-handle : Phandle to a PHY on an external MDIO bus, not the
|
||||||
switch internal one. See
|
switch internal one. See
|
||||||
|
@ -100,10 +101,11 @@ Example:
|
||||||
label = "cpu";
|
label = "cpu";
|
||||||
};
|
};
|
||||||
|
|
||||||
switch0uplink: port@6 {
|
switch0port6: port@6 {
|
||||||
reg = <6>;
|
reg = <6>;
|
||||||
label = "dsa";
|
label = "dsa";
|
||||||
link = <&switch1uplink>;
|
link = <&switch1port0
|
||||||
|
&switch2port0>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -113,10 +115,29 @@ Example:
|
||||||
reg = <17 1>; /* MDIO address 17, switch 1 in tree */
|
reg = <17 1>; /* MDIO address 17, switch 1 in tree */
|
||||||
mii-bus = <&mii_bus1>;
|
mii-bus = <&mii_bus1>;
|
||||||
|
|
||||||
switch1uplink: port@0 {
|
switch1port0: port@0 {
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
label = "dsa";
|
label = "dsa";
|
||||||
link = <&switch0uplink>;
|
link = <&switch0port6>;
|
||||||
|
};
|
||||||
|
switch1port1: port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
label = "dsa";
|
||||||
|
link = <&switch2port1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
switch@2 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
reg = <18 2>; /* MDIO address 18, switch 2 in tree */
|
||||||
|
mii-bus = <&mii_bus1>;
|
||||||
|
|
||||||
|
switch2port0: port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
label = "dsa";
|
||||||
|
link = <&switch1port1
|
||||||
|
&switch0port6>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1926,8 +1926,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
|
||||||
* full duplex.
|
* full duplex.
|
||||||
*/
|
*/
|
||||||
reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_PCS_CTRL);
|
reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_PCS_CTRL);
|
||||||
if (dsa_is_cpu_port(ds, port) ||
|
if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
|
||||||
ds->dsa_port_mask & (1 << port)) {
|
|
||||||
reg |= PORT_PCS_CTRL_FORCE_LINK |
|
reg |= PORT_PCS_CTRL_FORCE_LINK |
|
||||||
PORT_PCS_CTRL_LINK_UP |
|
PORT_PCS_CTRL_LINK_UP |
|
||||||
PORT_PCS_CTRL_DUPLEX_FULL |
|
PORT_PCS_CTRL_DUPLEX_FULL |
|
||||||
|
@ -1988,12 +1987,15 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
|
||||||
reg |= PORT_CONTROL_EGRESS_ADD_TAG;
|
reg |= PORT_CONTROL_EGRESS_ADD_TAG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (dsa_is_dsa_port(ds, port)) {
|
||||||
|
if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds))
|
||||||
|
reg |= PORT_CONTROL_DSA_TAG;
|
||||||
if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
|
if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
|
||||||
mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
|
mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
|
||||||
mv88e6xxx_6095_family(ds) || mv88e6xxx_6065_family(ds) ||
|
|
||||||
mv88e6xxx_6320_family(ds)) {
|
mv88e6xxx_6320_family(ds)) {
|
||||||
if (ds->dsa_port_mask & (1 << port))
|
|
||||||
reg |= PORT_CONTROL_FRAME_MODE_DSA;
|
reg |= PORT_CONTROL_FRAME_MODE_DSA;
|
||||||
|
}
|
||||||
|
|
||||||
if (port == dsa_upstream_port(ds))
|
if (port == dsa_upstream_port(ds))
|
||||||
reg |= PORT_CONTROL_FORWARD_UNKNOWN |
|
reg |= PORT_CONTROL_FORWARD_UNKNOWN |
|
||||||
PORT_CONTROL_FORWARD_UNKNOWN_MC;
|
PORT_CONTROL_FORWARD_UNKNOWN_MC;
|
||||||
|
|
|
@ -171,6 +171,11 @@ static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p)
|
||||||
return !!(ds->index == ds->dst->cpu_switch && p == ds->dst->cpu_port);
|
return !!(ds->index == ds->dst->cpu_switch && p == ds->dst->cpu_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p)
|
||||||
|
{
|
||||||
|
return !!((ds->dsa_port_mask) & (1 << p));
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool dsa_is_port_initialized(struct dsa_switch *ds, int p)
|
static inline bool dsa_is_port_initialized(struct dsa_switch *ds, int p)
|
||||||
{
|
{
|
||||||
return ds->phys_port_mask & (1 << p) && ds->ports[p];
|
return ds->phys_port_mask & (1 << p) && ds->ports[p];
|
||||||
|
|
|
@ -554,6 +554,31 @@ static int dsa_of_setup_routing_table(struct dsa_platform_data *pd,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dsa_of_probe_links(struct dsa_platform_data *pd,
|
||||||
|
struct dsa_chip_data *cd,
|
||||||
|
int chip_index, int port_index,
|
||||||
|
struct device_node *port,
|
||||||
|
const char *port_name)
|
||||||
|
{
|
||||||
|
struct device_node *link;
|
||||||
|
int link_index;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for (link_index = 0;; link_index++) {
|
||||||
|
link = of_parse_phandle(port, "link", link_index);
|
||||||
|
if (!link)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!strcmp(port_name, "dsa") && pd->nr_chips > 1) {
|
||||||
|
ret = dsa_of_setup_routing_table(pd, cd, chip_index,
|
||||||
|
port_index, link);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void dsa_of_free_platform_data(struct dsa_platform_data *pd)
|
static void dsa_of_free_platform_data(struct dsa_platform_data *pd)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -573,7 +598,7 @@ static void dsa_of_free_platform_data(struct dsa_platform_data *pd)
|
||||||
static int dsa_of_probe(struct device *dev)
|
static int dsa_of_probe(struct device *dev)
|
||||||
{
|
{
|
||||||
struct device_node *np = dev->of_node;
|
struct device_node *np = dev->of_node;
|
||||||
struct device_node *child, *mdio, *ethernet, *port, *link;
|
struct device_node *child, *mdio, *ethernet, *port;
|
||||||
struct mii_bus *mdio_bus, *mdio_bus_switch;
|
struct mii_bus *mdio_bus, *mdio_bus_switch;
|
||||||
struct net_device *ethernet_dev;
|
struct net_device *ethernet_dev;
|
||||||
struct dsa_platform_data *pd;
|
struct dsa_platform_data *pd;
|
||||||
|
@ -668,15 +693,10 @@ static int dsa_of_probe(struct device *dev)
|
||||||
goto out_free_chip;
|
goto out_free_chip;
|
||||||
}
|
}
|
||||||
|
|
||||||
link = of_parse_phandle(port, "link", 0);
|
ret = dsa_of_probe_links(pd, cd, chip_index,
|
||||||
|
port_index, port, port_name);
|
||||||
if (!strcmp(port_name, "dsa") && link &&
|
|
||||||
pd->nr_chips > 1) {
|
|
||||||
ret = dsa_of_setup_routing_table(pd, cd,
|
|
||||||
chip_index, port_index, link);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_free_chip;
|
goto out_free_chip;
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче