mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-18 01:34:14 +08:00
Merge branch 'dsa-master-and-slave-helpers'
Vivien Didelot says: ==================== net: dsa: master and slave helpers This patch series adds a few helpers to DSA core for clarity and readability but brings no functional changes. A dsa_slave_notify helper calls the DSA notifiers when (un)registering a slave device. Most of the DSA slave code only needs to access the dsa_port structure, not the dsa_slave_priv (which only contains a few PHY-specific members). Thus a dsa_slave_to_port helper returns a dsa_port structure of a slave device. A dsa_slave_to_master returns the master device of a slave device. After that the netdev member of the dsa_port structure is split into two explicit master and slave members to avoid confusion, and a dsa_to_port helper is added for switch drivers to get a const reference to a port. Changes in v2: - prefer dsa_slave_to_master instead of dsa_slave_get_master - rename dsa_master_get_slave to dsa_master_find_slave - pack master and slave net devices into an anonymous union - add dsa_to_port public helper for switch drivers - add Reviewed-by tags from Florian ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
1bbc728988
@ -1354,7 +1354,7 @@ int b53_br_join(struct dsa_switch *ds, int port, struct net_device *br)
|
|||||||
b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), &pvlan);
|
b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), &pvlan);
|
||||||
|
|
||||||
b53_for_each_port(dev, i) {
|
b53_for_each_port(dev, i) {
|
||||||
if (ds->ports[i].bridge_dev != br)
|
if (dsa_to_port(ds, i)->bridge_dev != br)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Add this local port to the remote port VLAN control
|
/* Add this local port to the remote port VLAN control
|
||||||
@ -1390,7 +1390,7 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *br)
|
|||||||
|
|
||||||
b53_for_each_port(dev, i) {
|
b53_for_each_port(dev, i) {
|
||||||
/* Don't touch the remaining ports */
|
/* Don't touch the remaining ports */
|
||||||
if (ds->ports[i].bridge_dev != br)
|
if (dsa_to_port(ds, i)->bridge_dev != br)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(i), ®);
|
b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(i), ®);
|
||||||
|
@ -601,7 +601,7 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
|
|||||||
* state machine and make it go in PHY_FORCING state instead.
|
* state machine and make it go in PHY_FORCING state instead.
|
||||||
*/
|
*/
|
||||||
if (!status->link)
|
if (!status->link)
|
||||||
netif_carrier_off(ds->ports[port].netdev);
|
netif_carrier_off(ds->ports[port].slave);
|
||||||
status->duplex = 1;
|
status->duplex = 1;
|
||||||
} else {
|
} else {
|
||||||
status->link = 1;
|
status->link = 1;
|
||||||
@ -690,7 +690,7 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds)
|
|||||||
static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port,
|
static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port,
|
||||||
struct ethtool_wolinfo *wol)
|
struct ethtool_wolinfo *wol)
|
||||||
{
|
{
|
||||||
struct net_device *p = ds->ports[port].cpu_dp->netdev;
|
struct net_device *p = ds->ports[port].cpu_dp->master;
|
||||||
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
|
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
|
||||||
struct ethtool_wolinfo pwol;
|
struct ethtool_wolinfo pwol;
|
||||||
|
|
||||||
@ -713,7 +713,7 @@ static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port,
|
|||||||
static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port,
|
static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port,
|
||||||
struct ethtool_wolinfo *wol)
|
struct ethtool_wolinfo *wol)
|
||||||
{
|
{
|
||||||
struct net_device *p = ds->ports[port].cpu_dp->netdev;
|
struct net_device *p = ds->ports[port].cpu_dp->master;
|
||||||
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
|
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
|
||||||
s8 cpu_port = ds->ports[port].cpu_dp->index;
|
s8 cpu_port = ds->ports[port].cpu_dp->index;
|
||||||
struct ethtool_wolinfo pwol;
|
struct ethtool_wolinfo pwol;
|
||||||
|
@ -863,7 +863,7 @@ static int lan9303_port_bridge_join(struct dsa_switch *ds, int port,
|
|||||||
struct lan9303 *chip = ds->priv;
|
struct lan9303 *chip = ds->priv;
|
||||||
|
|
||||||
dev_dbg(chip->dev, "%s(port %d)\n", __func__, port);
|
dev_dbg(chip->dev, "%s(port %d)\n", __func__, port);
|
||||||
if (ds->ports[1].bridge_dev == ds->ports[2].bridge_dev) {
|
if (dsa_to_port(ds, 1)->bridge_dev == dsa_to_port(ds, 2)->bridge_dev) {
|
||||||
lan9303_bridge_ports(chip);
|
lan9303_bridge_ports(chip);
|
||||||
chip->is_bridged = true; /* unleash stp_state_set() */
|
chip->is_bridged = true; /* unleash stp_state_set() */
|
||||||
}
|
}
|
||||||
|
@ -782,7 +782,7 @@ mt7530_port_bridge_join(struct dsa_switch *ds, int port,
|
|||||||
* and not being setup until the port becomes enabled.
|
* and not being setup until the port becomes enabled.
|
||||||
*/
|
*/
|
||||||
if (ds->enabled_port_mask & BIT(i) && i != port) {
|
if (ds->enabled_port_mask & BIT(i) && i != port) {
|
||||||
if (ds->ports[i].bridge_dev != bridge)
|
if (dsa_to_port(ds, i)->bridge_dev != bridge)
|
||||||
continue;
|
continue;
|
||||||
if (priv->ports[i].enable)
|
if (priv->ports[i].enable)
|
||||||
mt7530_set(priv, MT7530_PCR_P(i),
|
mt7530_set(priv, MT7530_PCR_P(i),
|
||||||
@ -819,7 +819,7 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
|
|||||||
* is kept and not being setup until the port becomes enabled.
|
* is kept and not being setup until the port becomes enabled.
|
||||||
*/
|
*/
|
||||||
if (ds->enabled_port_mask & BIT(i) && i != port) {
|
if (ds->enabled_port_mask & BIT(i) && i != port) {
|
||||||
if (ds->ports[i].bridge_dev != bridge)
|
if (dsa_to_port(ds, i)->bridge_dev != bridge)
|
||||||
continue;
|
continue;
|
||||||
if (priv->ports[i].enable)
|
if (priv->ports[i].enable)
|
||||||
mt7530_clear(priv, MT7530_PCR_P(i),
|
mt7530_clear(priv, MT7530_PCR_P(i),
|
||||||
@ -933,7 +933,7 @@ mt7530_setup(struct dsa_switch *ds)
|
|||||||
* controller also is the container for two GMACs nodes representing
|
* controller also is the container for two GMACs nodes representing
|
||||||
* as two netdev instances.
|
* as two netdev instances.
|
||||||
*/
|
*/
|
||||||
dn = ds->ports[MT7530_CPU_PORT].netdev->dev.of_node->parent;
|
dn = ds->ports[MT7530_CPU_PORT].master->dev.of_node->parent;
|
||||||
priv->ethernet = syscon_node_to_regmap(dn);
|
priv->ethernet = syscon_node_to_regmap(dn);
|
||||||
if (IS_ERR(priv->ethernet))
|
if (IS_ERR(priv->ethernet))
|
||||||
return PTR_ERR(priv->ethernet);
|
return PTR_ERR(priv->ethernet);
|
||||||
|
@ -177,7 +177,7 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p)
|
|||||||
((p & 0xf) << PORT_VLAN_MAP_DBNUM_SHIFT) |
|
((p & 0xf) << PORT_VLAN_MAP_DBNUM_SHIFT) |
|
||||||
(dsa_is_cpu_port(ds, p) ?
|
(dsa_is_cpu_port(ds, p) ?
|
||||||
ds->enabled_port_mask :
|
ds->enabled_port_mask :
|
||||||
BIT(ds->ports[p].cpu_dp->index)));
|
BIT(dsa_to_port(ds, p)->cpu_dp->index)));
|
||||||
|
|
||||||
/* Port Association Vector: when learning source addresses
|
/* Port Association Vector: when learning source addresses
|
||||||
* of packets, add the address to the address database using
|
* of packets, add the address to the address database using
|
||||||
|
@ -851,7 +851,7 @@ static u16 mv88e6xxx_port_vlan(struct mv88e6xxx_chip *chip, int dev, int port)
|
|||||||
for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
|
for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
|
||||||
if (dsa_is_cpu_port(chip->ds, i) ||
|
if (dsa_is_cpu_port(chip->ds, i) ||
|
||||||
dsa_is_dsa_port(chip->ds, i) ||
|
dsa_is_dsa_port(chip->ds, i) ||
|
||||||
(br && chip->ds->ports[i].bridge_dev == br))
|
(br && dsa_to_port(chip->ds, i)->bridge_dev == br))
|
||||||
pvlan |= BIT(i);
|
pvlan |= BIT(i);
|
||||||
|
|
||||||
return pvlan;
|
return pvlan;
|
||||||
@ -1137,23 +1137,23 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
|
|||||||
if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i))
|
if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!ds->ports[port].netdev)
|
if (!ds->ports[port].slave)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (vlan.member[i] ==
|
if (vlan.member[i] ==
|
||||||
MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER)
|
MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ds->ports[i].bridge_dev ==
|
if (dsa_to_port(ds, i)->bridge_dev ==
|
||||||
ds->ports[port].bridge_dev)
|
ds->ports[port].bridge_dev)
|
||||||
break; /* same bridge, check next VLAN */
|
break; /* same bridge, check next VLAN */
|
||||||
|
|
||||||
if (!ds->ports[i].bridge_dev)
|
if (!dsa_to_port(ds, i)->bridge_dev)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dev_err(ds->dev, "p%d: hw VLAN %d already used by %s\n",
|
dev_err(ds->dev, "p%d: hw VLAN %d already used by %s\n",
|
||||||
port, vlan.vid,
|
port, vlan.vid,
|
||||||
netdev_name(ds->ports[i].bridge_dev));
|
netdev_name(dsa_to_port(ds, i)->bridge_dev));
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
@ -700,7 +700,7 @@ qca8k_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *br)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 1; i < QCA8K_NUM_PORTS; i++) {
|
for (i = 1; i < QCA8K_NUM_PORTS; i++) {
|
||||||
if (ds->ports[i].bridge_dev != br)
|
if (dsa_to_port(ds, i)->bridge_dev != br)
|
||||||
continue;
|
continue;
|
||||||
/* Add this port to the portvlan mask of the other ports
|
/* Add this port to the portvlan mask of the other ports
|
||||||
* in the bridge
|
* in the bridge
|
||||||
@ -725,7 +725,7 @@ qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 1; i < QCA8K_NUM_PORTS; i++) {
|
for (i = 1; i < QCA8K_NUM_PORTS; i++) {
|
||||||
if (ds->ports[i].bridge_dev != br)
|
if (dsa_to_port(ds, i)->bridge_dev != br)
|
||||||
continue;
|
continue;
|
||||||
/* Remove this port to the portvlan mask of the other ports
|
/* Remove this port to the portvlan mask of the other ports
|
||||||
* in the bridge
|
* in the bridge
|
||||||
|
@ -164,6 +164,14 @@ struct dsa_mall_tc_entry {
|
|||||||
|
|
||||||
|
|
||||||
struct dsa_port {
|
struct dsa_port {
|
||||||
|
/* A CPU port is physically connected to a master device.
|
||||||
|
* A user port exposed to userspace has a slave device.
|
||||||
|
*/
|
||||||
|
union {
|
||||||
|
struct net_device *master;
|
||||||
|
struct net_device *slave;
|
||||||
|
};
|
||||||
|
|
||||||
/* CPU port tagging operations used by master or slave devices */
|
/* CPU port tagging operations used by master or slave devices */
|
||||||
const struct dsa_device_ops *tag_ops;
|
const struct dsa_device_ops *tag_ops;
|
||||||
|
|
||||||
@ -176,7 +184,6 @@ struct dsa_port {
|
|||||||
unsigned int index;
|
unsigned int index;
|
||||||
const char *name;
|
const char *name;
|
||||||
struct dsa_port *cpu_dp;
|
struct dsa_port *cpu_dp;
|
||||||
struct net_device *netdev;
|
|
||||||
struct device_node *dn;
|
struct device_node *dn;
|
||||||
unsigned int ageing_time;
|
unsigned int ageing_time;
|
||||||
u8 stp_state;
|
u8 stp_state;
|
||||||
@ -262,6 +269,11 @@ static inline bool dsa_is_normal_port(struct dsa_switch *ds, int p)
|
|||||||
return !dsa_is_cpu_port(ds, p) && !dsa_is_dsa_port(ds, p);
|
return !dsa_is_cpu_port(ds, p) && !dsa_is_dsa_port(ds, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline const struct dsa_port *dsa_to_port(struct dsa_switch *ds, int p)
|
||||||
|
{
|
||||||
|
return &ds->ports[p];
|
||||||
|
}
|
||||||
|
|
||||||
static inline u8 dsa_upstream_port(struct dsa_switch *ds)
|
static inline u8 dsa_upstream_port(struct dsa_switch *ds)
|
||||||
{
|
{
|
||||||
struct dsa_switch_tree *dst = ds->dst;
|
struct dsa_switch_tree *dst = ds->dst;
|
||||||
|
@ -201,7 +201,7 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
|
|||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
static bool dsa_is_port_initialized(struct dsa_switch *ds, int p)
|
static bool dsa_is_port_initialized(struct dsa_switch *ds, int p)
|
||||||
{
|
{
|
||||||
return ds->enabled_port_mask & (1 << p) && ds->ports[p].netdev;
|
return ds->enabled_port_mask & (1 << p) && ds->ports[p].slave;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dsa_switch_suspend(struct dsa_switch *ds)
|
int dsa_switch_suspend(struct dsa_switch *ds)
|
||||||
@ -213,7 +213,7 @@ int dsa_switch_suspend(struct dsa_switch *ds)
|
|||||||
if (!dsa_is_port_initialized(ds, i))
|
if (!dsa_is_port_initialized(ds, i))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret = dsa_slave_suspend(ds->ports[i].netdev);
|
ret = dsa_slave_suspend(ds->ports[i].slave);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -240,7 +240,7 @@ int dsa_switch_resume(struct dsa_switch *ds)
|
|||||||
if (!dsa_is_port_initialized(ds, i))
|
if (!dsa_is_port_initialized(ds, i))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret = dsa_slave_resume(ds->ports[i].netdev);
|
ret = dsa_slave_resume(ds->ports[i].slave);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -279,7 +279,7 @@ static int dsa_user_port_apply(struct dsa_port *port)
|
|||||||
if (err) {
|
if (err) {
|
||||||
dev_warn(ds->dev, "Failed to create slave %d: %d\n",
|
dev_warn(ds->dev, "Failed to create slave %d: %d\n",
|
||||||
port->index, err);
|
port->index, err);
|
||||||
port->netdev = NULL;
|
port->slave = NULL;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,7 +289,7 @@ static int dsa_user_port_apply(struct dsa_port *port)
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
devlink_port_type_eth_set(&port->devlink_port, port->netdev);
|
devlink_port_type_eth_set(&port->devlink_port, port->slave);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -297,9 +297,9 @@ static int dsa_user_port_apply(struct dsa_port *port)
|
|||||||
static void dsa_user_port_unapply(struct dsa_port *port)
|
static void dsa_user_port_unapply(struct dsa_port *port)
|
||||||
{
|
{
|
||||||
devlink_port_unregister(&port->devlink_port);
|
devlink_port_unregister(&port->devlink_port);
|
||||||
if (port->netdev) {
|
if (port->slave) {
|
||||||
dsa_slave_destroy(port->netdev);
|
dsa_slave_destroy(port->slave);
|
||||||
port->netdev = NULL;
|
port->slave = NULL;
|
||||||
port->ds->enabled_port_mask &= ~(1 << port->index);
|
port->ds->enabled_port_mask &= ~(1 << port->index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -432,9 +432,9 @@ static int dsa_dst_apply(struct dsa_switch_tree *dst)
|
|||||||
* sent to the tag format's receive function.
|
* sent to the tag format's receive function.
|
||||||
*/
|
*/
|
||||||
wmb();
|
wmb();
|
||||||
dst->cpu_dp->netdev->dsa_ptr = dst->cpu_dp;
|
dst->cpu_dp->master->dsa_ptr = dst->cpu_dp;
|
||||||
|
|
||||||
err = dsa_master_ethtool_setup(dst->cpu_dp->netdev);
|
err = dsa_master_ethtool_setup(dst->cpu_dp->master);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -451,9 +451,9 @@ static void dsa_dst_unapply(struct dsa_switch_tree *dst)
|
|||||||
if (!dst->applied)
|
if (!dst->applied)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dsa_master_ethtool_restore(dst->cpu_dp->netdev);
|
dsa_master_ethtool_restore(dst->cpu_dp->master);
|
||||||
|
|
||||||
dst->cpu_dp->netdev->dsa_ptr = NULL;
|
dst->cpu_dp->master->dsa_ptr = NULL;
|
||||||
|
|
||||||
/* If we used a tagging format that doesn't have an ethertype
|
/* If we used a tagging format that doesn't have an ethertype
|
||||||
* field, make sure that all packets from this point get sent
|
* field, make sure that all packets from this point get sent
|
||||||
@ -499,7 +499,7 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,
|
|||||||
|
|
||||||
if (!dst->cpu_dp) {
|
if (!dst->cpu_dp) {
|
||||||
dst->cpu_dp = port;
|
dst->cpu_dp = port;
|
||||||
dst->cpu_dp->netdev = ethernet_dev;
|
dst->cpu_dp->master = ethernet_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize cpu_port_mask now for drv->setup()
|
/* Initialize cpu_port_mask now for drv->setup()
|
||||||
|
@ -113,8 +113,8 @@ int dsa_legacy_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
|
|||||||
int dsa_master_ethtool_setup(struct net_device *dev);
|
int dsa_master_ethtool_setup(struct net_device *dev);
|
||||||
void dsa_master_ethtool_restore(struct net_device *dev);
|
void dsa_master_ethtool_restore(struct net_device *dev);
|
||||||
|
|
||||||
static inline struct net_device *dsa_master_get_slave(struct net_device *dev,
|
static inline struct net_device *dsa_master_find_slave(struct net_device *dev,
|
||||||
int device, int port)
|
int device, int port)
|
||||||
{
|
{
|
||||||
struct dsa_port *cpu_dp = dev->dsa_ptr;
|
struct dsa_port *cpu_dp = dev->dsa_ptr;
|
||||||
struct dsa_switch_tree *dst = cpu_dp->dst;
|
struct dsa_switch_tree *dst = cpu_dp->dst;
|
||||||
@ -130,7 +130,7 @@ static inline struct net_device *dsa_master_get_slave(struct net_device *dev,
|
|||||||
if (port < 0 || port >= ds->num_ports)
|
if (port < 0 || port >= ds->num_ports)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return ds->ports[port].netdev;
|
return ds->ports[port].slave;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* port.c */
|
/* port.c */
|
||||||
@ -169,6 +169,21 @@ int dsa_slave_resume(struct net_device *slave_dev);
|
|||||||
int dsa_slave_register_notifier(void);
|
int dsa_slave_register_notifier(void);
|
||||||
void dsa_slave_unregister_notifier(void);
|
void dsa_slave_unregister_notifier(void);
|
||||||
|
|
||||||
|
static inline struct dsa_port *dsa_slave_to_port(const struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct dsa_slave_priv *p = netdev_priv(dev);
|
||||||
|
|
||||||
|
return p->dp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct net_device *
|
||||||
|
dsa_slave_to_master(const struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
|
|
||||||
|
return dp->cpu_dp->master;
|
||||||
|
}
|
||||||
|
|
||||||
/* switch.c */
|
/* switch.c */
|
||||||
int dsa_switch_register_notifier(struct dsa_switch *ds);
|
int dsa_switch_register_notifier(struct dsa_switch *ds);
|
||||||
void dsa_switch_unregister_notifier(struct dsa_switch *ds);
|
void dsa_switch_unregister_notifier(struct dsa_switch *ds);
|
||||||
@ -197,9 +212,4 @@ extern const struct dsa_device_ops qca_netdev_ops;
|
|||||||
/* tag_trailer.c */
|
/* tag_trailer.c */
|
||||||
extern const struct dsa_device_ops trailer_netdev_ops;
|
extern const struct dsa_device_ops trailer_netdev_ops;
|
||||||
|
|
||||||
static inline struct net_device *dsa_master_netdev(struct dsa_slave_priv *p)
|
|
||||||
{
|
|
||||||
return p->dp->cpu_dp->netdev;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -120,7 +120,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
dst->cpu_dp = &ds->ports[i];
|
dst->cpu_dp = &ds->ports[i];
|
||||||
dst->cpu_dp->netdev = master;
|
dst->cpu_dp->master = master;
|
||||||
ds->cpu_port_mask |= 1 << i;
|
ds->cpu_port_mask |= 1 << i;
|
||||||
} else if (!strcmp(name, "dsa")) {
|
} else if (!strcmp(name, "dsa")) {
|
||||||
ds->dsa_port_mask |= 1 << i;
|
ds->dsa_port_mask |= 1 << i;
|
||||||
@ -261,10 +261,10 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
|
|||||||
if (!(ds->enabled_port_mask & (1 << port)))
|
if (!(ds->enabled_port_mask & (1 << port)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!ds->ports[port].netdev)
|
if (!ds->ports[port].slave)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dsa_slave_destroy(ds->ports[port].netdev);
|
dsa_slave_destroy(ds->ports[port].slave);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable configuration of the CPU and DSA ports */
|
/* Disable configuration of the CPU and DSA ports */
|
||||||
@ -601,7 +601,7 @@ static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
|
|||||||
wmb();
|
wmb();
|
||||||
dev->dsa_ptr = dst->cpu_dp;
|
dev->dsa_ptr = dst->cpu_dp;
|
||||||
|
|
||||||
return dsa_master_ethtool_setup(dst->cpu_dp->netdev);
|
return dsa_master_ethtool_setup(dst->cpu_dp->master);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dsa_probe(struct platform_device *pdev)
|
static int dsa_probe(struct platform_device *pdev)
|
||||||
@ -666,9 +666,9 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
dsa_master_ethtool_restore(dst->cpu_dp->netdev);
|
dsa_master_ethtool_restore(dst->cpu_dp->master);
|
||||||
|
|
||||||
dst->cpu_dp->netdev->dsa_ptr = NULL;
|
dst->cpu_dp->master->dsa_ptr = NULL;
|
||||||
|
|
||||||
/* If we used a tagging format that doesn't have an ethertype
|
/* If we used a tagging format that doesn't have an ethertype
|
||||||
* field, make sure that all packets from this point get sent
|
* field, make sure that all packets from this point get sent
|
||||||
@ -683,7 +683,7 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
|
|||||||
dsa_switch_destroy(ds);
|
dsa_switch_destroy(ds);
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_put(dst->cpu_dp->netdev);
|
dev_put(dst->cpu_dp->master);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dsa_remove(struct platform_device *pdev)
|
static int dsa_remove(struct platform_device *pdev)
|
||||||
@ -740,8 +740,7 @@ int dsa_legacy_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
|
|||||||
const unsigned char *addr, u16 vid,
|
const unsigned char *addr, u16 vid,
|
||||||
u16 flags)
|
u16 flags)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_port *dp = p->dp;
|
|
||||||
|
|
||||||
return dsa_port_fdb_add(dp, addr, vid);
|
return dsa_port_fdb_add(dp, addr, vid);
|
||||||
}
|
}
|
||||||
@ -750,8 +749,7 @@ int dsa_legacy_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
|
|||||||
struct net_device *dev,
|
struct net_device *dev,
|
||||||
const unsigned char *addr, u16 vid)
|
const unsigned char *addr, u16 vid)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_port *dp = p->dp;
|
|
||||||
|
|
||||||
return dsa_port_fdb_del(dp, addr, vid);
|
return dsa_port_fdb_del(dp, addr, vid);
|
||||||
}
|
}
|
||||||
|
227
net/dsa/slave.c
227
net/dsa/slave.c
@ -64,16 +64,13 @@ void dsa_slave_mii_bus_init(struct dsa_switch *ds)
|
|||||||
/* slave device handling ****************************************************/
|
/* slave device handling ****************************************************/
|
||||||
static int dsa_slave_get_iflink(const struct net_device *dev)
|
static int dsa_slave_get_iflink(const struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
return dsa_slave_to_master(dev)->ifindex;
|
||||||
|
|
||||||
return dsa_master_netdev(p)->ifindex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dsa_slave_open(struct net_device *dev)
|
static int dsa_slave_open(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct net_device *master = dsa_slave_to_master(dev);
|
||||||
struct dsa_port *dp = p->dp;
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct net_device *master = dsa_master_netdev(p);
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!(master->flags & IFF_UP))
|
if (!(master->flags & IFF_UP))
|
||||||
@ -120,9 +117,8 @@ out:
|
|||||||
|
|
||||||
static int dsa_slave_close(struct net_device *dev)
|
static int dsa_slave_close(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct net_device *master = dsa_slave_to_master(dev);
|
||||||
struct net_device *master = dsa_master_netdev(p);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_port *dp = p->dp;
|
|
||||||
|
|
||||||
if (dev->phydev)
|
if (dev->phydev)
|
||||||
phy_stop(dev->phydev);
|
phy_stop(dev->phydev);
|
||||||
@ -144,8 +140,7 @@ static int dsa_slave_close(struct net_device *dev)
|
|||||||
|
|
||||||
static void dsa_slave_change_rx_flags(struct net_device *dev, int change)
|
static void dsa_slave_change_rx_flags(struct net_device *dev, int change)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct net_device *master = dsa_slave_to_master(dev);
|
||||||
struct net_device *master = dsa_master_netdev(p);
|
|
||||||
|
|
||||||
if (change & IFF_ALLMULTI)
|
if (change & IFF_ALLMULTI)
|
||||||
dev_set_allmulti(master, dev->flags & IFF_ALLMULTI ? 1 : -1);
|
dev_set_allmulti(master, dev->flags & IFF_ALLMULTI ? 1 : -1);
|
||||||
@ -155,8 +150,7 @@ static void dsa_slave_change_rx_flags(struct net_device *dev, int change)
|
|||||||
|
|
||||||
static void dsa_slave_set_rx_mode(struct net_device *dev)
|
static void dsa_slave_set_rx_mode(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct net_device *master = dsa_slave_to_master(dev);
|
||||||
struct net_device *master = dsa_master_netdev(p);
|
|
||||||
|
|
||||||
dev_mc_sync(master, dev);
|
dev_mc_sync(master, dev);
|
||||||
dev_uc_sync(master, dev);
|
dev_uc_sync(master, dev);
|
||||||
@ -164,8 +158,7 @@ static void dsa_slave_set_rx_mode(struct net_device *dev)
|
|||||||
|
|
||||||
static int dsa_slave_set_mac_address(struct net_device *dev, void *a)
|
static int dsa_slave_set_mac_address(struct net_device *dev, void *a)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct net_device *master = dsa_slave_to_master(dev);
|
||||||
struct net_device *master = dsa_master_netdev(p);
|
|
||||||
struct sockaddr *addr = a;
|
struct sockaddr *addr = a;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -246,14 +239,13 @@ dsa_slave_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
|
|||||||
struct net_device *dev, struct net_device *filter_dev,
|
struct net_device *dev, struct net_device *filter_dev,
|
||||||
int *idx)
|
int *idx)
|
||||||
{
|
{
|
||||||
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_slave_dump_ctx dump = {
|
struct dsa_slave_dump_ctx dump = {
|
||||||
.dev = dev,
|
.dev = dev,
|
||||||
.skb = skb,
|
.skb = skb,
|
||||||
.cb = cb,
|
.cb = cb,
|
||||||
.idx = *idx,
|
.idx = *idx,
|
||||||
};
|
};
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
|
||||||
struct dsa_port *dp = p->dp;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = dsa_port_fdb_dump(dp, dsa_slave_port_fdb_do_dump, &dump);
|
err = dsa_port_fdb_dump(dp, dsa_slave_port_fdb_do_dump, &dump);
|
||||||
@ -274,8 +266,7 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
|
|||||||
const struct switchdev_attr *attr,
|
const struct switchdev_attr *attr,
|
||||||
struct switchdev_trans *trans)
|
struct switchdev_trans *trans)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_port *dp = p->dp;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
switch (attr->id) {
|
switch (attr->id) {
|
||||||
@ -301,8 +292,7 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
|
|||||||
const struct switchdev_obj *obj,
|
const struct switchdev_obj *obj,
|
||||||
struct switchdev_trans *trans)
|
struct switchdev_trans *trans)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_port *dp = p->dp;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* For the prepare phase, ensure the full set of changes is feasable in
|
/* For the prepare phase, ensure the full set of changes is feasable in
|
||||||
@ -329,8 +319,7 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
|
|||||||
static int dsa_slave_port_obj_del(struct net_device *dev,
|
static int dsa_slave_port_obj_del(struct net_device *dev,
|
||||||
const struct switchdev_obj *obj)
|
const struct switchdev_obj *obj)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_port *dp = p->dp;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
switch (obj->id) {
|
switch (obj->id) {
|
||||||
@ -351,8 +340,8 @@ static int dsa_slave_port_obj_del(struct net_device *dev,
|
|||||||
static int dsa_slave_port_attr_get(struct net_device *dev,
|
static int dsa_slave_port_attr_get(struct net_device *dev,
|
||||||
struct switchdev_attr *attr)
|
struct switchdev_attr *attr)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
|
|
||||||
switch (attr->id) {
|
switch (attr->id) {
|
||||||
case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
|
case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
|
||||||
@ -413,7 +402,7 @@ static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||||||
/* Queue the SKB for transmission on the parent interface, but
|
/* Queue the SKB for transmission on the parent interface, but
|
||||||
* do not modify its EtherType
|
* do not modify its EtherType
|
||||||
*/
|
*/
|
||||||
nskb->dev = dsa_master_netdev(p);
|
nskb->dev = dsa_slave_to_master(dev);
|
||||||
dev_queue_xmit(nskb);
|
dev_queue_xmit(nskb);
|
||||||
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
@ -431,11 +420,11 @@ static void dsa_slave_get_drvinfo(struct net_device *dev,
|
|||||||
|
|
||||||
static int dsa_slave_get_regs_len(struct net_device *dev)
|
static int dsa_slave_get_regs_len(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
|
|
||||||
if (ds->ops->get_regs_len)
|
if (ds->ops->get_regs_len)
|
||||||
return ds->ops->get_regs_len(ds, p->dp->index);
|
return ds->ops->get_regs_len(ds, dp->index);
|
||||||
|
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
@ -443,11 +432,11 @@ static int dsa_slave_get_regs_len(struct net_device *dev)
|
|||||||
static void
|
static void
|
||||||
dsa_slave_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *_p)
|
dsa_slave_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *_p)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
|
|
||||||
if (ds->ops->get_regs)
|
if (ds->ops->get_regs)
|
||||||
ds->ops->get_regs(ds, p->dp->index, regs, _p);
|
ds->ops->get_regs(ds, dp->index, regs, _p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 dsa_slave_get_link(struct net_device *dev)
|
static u32 dsa_slave_get_link(struct net_device *dev)
|
||||||
@ -462,8 +451,8 @@ static u32 dsa_slave_get_link(struct net_device *dev)
|
|||||||
|
|
||||||
static int dsa_slave_get_eeprom_len(struct net_device *dev)
|
static int dsa_slave_get_eeprom_len(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
|
|
||||||
if (ds->cd && ds->cd->eeprom_len)
|
if (ds->cd && ds->cd->eeprom_len)
|
||||||
return ds->cd->eeprom_len;
|
return ds->cd->eeprom_len;
|
||||||
@ -477,8 +466,8 @@ static int dsa_slave_get_eeprom_len(struct net_device *dev)
|
|||||||
static int dsa_slave_get_eeprom(struct net_device *dev,
|
static int dsa_slave_get_eeprom(struct net_device *dev,
|
||||||
struct ethtool_eeprom *eeprom, u8 *data)
|
struct ethtool_eeprom *eeprom, u8 *data)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
|
|
||||||
if (ds->ops->get_eeprom)
|
if (ds->ops->get_eeprom)
|
||||||
return ds->ops->get_eeprom(ds, eeprom, data);
|
return ds->ops->get_eeprom(ds, eeprom, data);
|
||||||
@ -489,8 +478,8 @@ static int dsa_slave_get_eeprom(struct net_device *dev,
|
|||||||
static int dsa_slave_set_eeprom(struct net_device *dev,
|
static int dsa_slave_set_eeprom(struct net_device *dev,
|
||||||
struct ethtool_eeprom *eeprom, u8 *data)
|
struct ethtool_eeprom *eeprom, u8 *data)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
|
|
||||||
if (ds->ops->set_eeprom)
|
if (ds->ops->set_eeprom)
|
||||||
return ds->ops->set_eeprom(ds, eeprom, data);
|
return ds->ops->set_eeprom(ds, eeprom, data);
|
||||||
@ -501,8 +490,8 @@ static int dsa_slave_set_eeprom(struct net_device *dev,
|
|||||||
static void dsa_slave_get_strings(struct net_device *dev,
|
static void dsa_slave_get_strings(struct net_device *dev,
|
||||||
uint32_t stringset, uint8_t *data)
|
uint32_t stringset, uint8_t *data)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
|
|
||||||
if (stringset == ETH_SS_STATS) {
|
if (stringset == ETH_SS_STATS) {
|
||||||
int len = ETH_GSTRING_LEN;
|
int len = ETH_GSTRING_LEN;
|
||||||
@ -512,7 +501,7 @@ static void dsa_slave_get_strings(struct net_device *dev,
|
|||||||
strncpy(data + 2 * len, "rx_packets", len);
|
strncpy(data + 2 * len, "rx_packets", len);
|
||||||
strncpy(data + 3 * len, "rx_bytes", len);
|
strncpy(data + 3 * len, "rx_bytes", len);
|
||||||
if (ds->ops->get_strings)
|
if (ds->ops->get_strings)
|
||||||
ds->ops->get_strings(ds, p->dp->index, data + 4 * len);
|
ds->ops->get_strings(ds, dp->index, data + 4 * len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -520,8 +509,9 @@ static void dsa_slave_get_ethtool_stats(struct net_device *dev,
|
|||||||
struct ethtool_stats *stats,
|
struct ethtool_stats *stats,
|
||||||
uint64_t *data)
|
uint64_t *data)
|
||||||
{
|
{
|
||||||
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_slave_priv *p = netdev_priv(dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
struct pcpu_sw_netstats *s;
|
struct pcpu_sw_netstats *s;
|
||||||
unsigned int start;
|
unsigned int start;
|
||||||
int i;
|
int i;
|
||||||
@ -543,13 +533,13 @@ static void dsa_slave_get_ethtool_stats(struct net_device *dev,
|
|||||||
data[3] += rx_bytes;
|
data[3] += rx_bytes;
|
||||||
}
|
}
|
||||||
if (ds->ops->get_ethtool_stats)
|
if (ds->ops->get_ethtool_stats)
|
||||||
ds->ops->get_ethtool_stats(ds, p->dp->index, data + 4);
|
ds->ops->get_ethtool_stats(ds, dp->index, data + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dsa_slave_get_sset_count(struct net_device *dev, int sset)
|
static int dsa_slave_get_sset_count(struct net_device *dev, int sset)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
|
|
||||||
if (sset == ETH_SS_STATS) {
|
if (sset == ETH_SS_STATS) {
|
||||||
int count;
|
int count;
|
||||||
@ -566,29 +556,29 @@ static int dsa_slave_get_sset_count(struct net_device *dev, int sset)
|
|||||||
|
|
||||||
static void dsa_slave_get_wol(struct net_device *dev, struct ethtool_wolinfo *w)
|
static void dsa_slave_get_wol(struct net_device *dev, struct ethtool_wolinfo *w)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
|
|
||||||
if (ds->ops->get_wol)
|
if (ds->ops->get_wol)
|
||||||
ds->ops->get_wol(ds, p->dp->index, w);
|
ds->ops->get_wol(ds, dp->index, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dsa_slave_set_wol(struct net_device *dev, struct ethtool_wolinfo *w)
|
static int dsa_slave_set_wol(struct net_device *dev, struct ethtool_wolinfo *w)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
int ret = -EOPNOTSUPP;
|
int ret = -EOPNOTSUPP;
|
||||||
|
|
||||||
if (ds->ops->set_wol)
|
if (ds->ops->set_wol)
|
||||||
ret = ds->ops->set_wol(ds, p->dp->index, w);
|
ret = ds->ops->set_wol(ds, dp->index, w);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dsa_slave_set_eee(struct net_device *dev, struct ethtool_eee *e)
|
static int dsa_slave_set_eee(struct net_device *dev, struct ethtool_eee *e)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Port's PHY and MAC both need to be EEE capable */
|
/* Port's PHY and MAC both need to be EEE capable */
|
||||||
@ -598,7 +588,7 @@ static int dsa_slave_set_eee(struct net_device *dev, struct ethtool_eee *e)
|
|||||||
if (!ds->ops->set_mac_eee)
|
if (!ds->ops->set_mac_eee)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
ret = ds->ops->set_mac_eee(ds, p->dp->index, e);
|
ret = ds->ops->set_mac_eee(ds, dp->index, e);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -613,8 +603,8 @@ static int dsa_slave_set_eee(struct net_device *dev, struct ethtool_eee *e)
|
|||||||
|
|
||||||
static int dsa_slave_get_eee(struct net_device *dev, struct ethtool_eee *e)
|
static int dsa_slave_get_eee(struct net_device *dev, struct ethtool_eee *e)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Port's PHY and MAC both need to be EEE capable */
|
/* Port's PHY and MAC both need to be EEE capable */
|
||||||
@ -624,7 +614,7 @@ static int dsa_slave_get_eee(struct net_device *dev, struct ethtool_eee *e)
|
|||||||
if (!ds->ops->get_mac_eee)
|
if (!ds->ops->get_mac_eee)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
ret = ds->ops->get_mac_eee(ds, p->dp->index, e);
|
ret = ds->ops->get_mac_eee(ds, dp->index, e);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -635,8 +625,8 @@ static int dsa_slave_get_eee(struct net_device *dev, struct ethtool_eee *e)
|
|||||||
static int dsa_slave_netpoll_setup(struct net_device *dev,
|
static int dsa_slave_netpoll_setup(struct net_device *dev,
|
||||||
struct netpoll_info *ni)
|
struct netpoll_info *ni)
|
||||||
{
|
{
|
||||||
|
struct net_device *master = dsa_slave_to_master(dev);
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_slave_priv *p = netdev_priv(dev);
|
||||||
struct net_device *master = dsa_master_netdev(p);
|
|
||||||
struct netpoll *netpoll;
|
struct netpoll *netpoll;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
@ -676,9 +666,9 @@ static void dsa_slave_poll_controller(struct net_device *dev)
|
|||||||
static int dsa_slave_get_phys_port_name(struct net_device *dev,
|
static int dsa_slave_get_phys_port_name(struct net_device *dev,
|
||||||
char *name, size_t len)
|
char *name, size_t len)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
|
|
||||||
if (snprintf(name, len, "p%d", p->dp->index) >= len)
|
if (snprintf(name, len, "p%d", dp->index) >= len)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -701,14 +691,15 @@ static int dsa_slave_add_cls_matchall(struct net_device *dev,
|
|||||||
struct tc_cls_matchall_offload *cls,
|
struct tc_cls_matchall_offload *cls,
|
||||||
bool ingress)
|
bool ingress)
|
||||||
{
|
{
|
||||||
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_slave_priv *p = netdev_priv(dev);
|
||||||
struct dsa_mall_tc_entry *mall_tc_entry;
|
struct dsa_mall_tc_entry *mall_tc_entry;
|
||||||
__be16 protocol = cls->common.protocol;
|
__be16 protocol = cls->common.protocol;
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
|
||||||
struct net *net = dev_net(dev);
|
struct net *net = dev_net(dev);
|
||||||
struct dsa_slave_priv *to_p;
|
struct dsa_switch *ds = dp->ds;
|
||||||
struct net_device *to_dev;
|
struct net_device *to_dev;
|
||||||
const struct tc_action *a;
|
const struct tc_action *a;
|
||||||
|
struct dsa_port *to_dp;
|
||||||
int err = -EOPNOTSUPP;
|
int err = -EOPNOTSUPP;
|
||||||
LIST_HEAD(actions);
|
LIST_HEAD(actions);
|
||||||
int ifindex;
|
int ifindex;
|
||||||
@ -741,13 +732,12 @@ static int dsa_slave_add_cls_matchall(struct net_device *dev,
|
|||||||
mall_tc_entry->type = DSA_PORT_MALL_MIRROR;
|
mall_tc_entry->type = DSA_PORT_MALL_MIRROR;
|
||||||
mirror = &mall_tc_entry->mirror;
|
mirror = &mall_tc_entry->mirror;
|
||||||
|
|
||||||
to_p = netdev_priv(to_dev);
|
to_dp = dsa_slave_to_port(to_dev);
|
||||||
|
|
||||||
mirror->to_local_port = to_p->dp->index;
|
mirror->to_local_port = to_dp->index;
|
||||||
mirror->ingress = ingress;
|
mirror->ingress = ingress;
|
||||||
|
|
||||||
err = ds->ops->port_mirror_add(ds, p->dp->index, mirror,
|
err = ds->ops->port_mirror_add(ds, dp->index, mirror, ingress);
|
||||||
ingress);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
kfree(mall_tc_entry);
|
kfree(mall_tc_entry);
|
||||||
return err;
|
return err;
|
||||||
@ -762,9 +752,9 @@ static int dsa_slave_add_cls_matchall(struct net_device *dev,
|
|||||||
static void dsa_slave_del_cls_matchall(struct net_device *dev,
|
static void dsa_slave_del_cls_matchall(struct net_device *dev,
|
||||||
struct tc_cls_matchall_offload *cls)
|
struct tc_cls_matchall_offload *cls)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_mall_tc_entry *mall_tc_entry;
|
struct dsa_mall_tc_entry *mall_tc_entry;
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
|
|
||||||
if (!ds->ops->port_mirror_del)
|
if (!ds->ops->port_mirror_del)
|
||||||
return;
|
return;
|
||||||
@ -777,8 +767,7 @@ static void dsa_slave_del_cls_matchall(struct net_device *dev,
|
|||||||
|
|
||||||
switch (mall_tc_entry->type) {
|
switch (mall_tc_entry->type) {
|
||||||
case DSA_PORT_MALL_MIRROR:
|
case DSA_PORT_MALL_MIRROR:
|
||||||
ds->ops->port_mirror_del(ds, p->dp->index,
|
ds->ops->port_mirror_del(ds, dp->index, &mall_tc_entry->mirror);
|
||||||
&mall_tc_entry->mirror);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
@ -855,25 +844,25 @@ static void dsa_slave_get_stats64(struct net_device *dev,
|
|||||||
static int dsa_slave_get_rxnfc(struct net_device *dev,
|
static int dsa_slave_get_rxnfc(struct net_device *dev,
|
||||||
struct ethtool_rxnfc *nfc, u32 *rule_locs)
|
struct ethtool_rxnfc *nfc, u32 *rule_locs)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
|
|
||||||
if (!ds->ops->get_rxnfc)
|
if (!ds->ops->get_rxnfc)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
return ds->ops->get_rxnfc(ds, p->dp->index, nfc, rule_locs);
|
return ds->ops->get_rxnfc(ds, dp->index, nfc, rule_locs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dsa_slave_set_rxnfc(struct net_device *dev,
|
static int dsa_slave_set_rxnfc(struct net_device *dev,
|
||||||
struct ethtool_rxnfc *nfc)
|
struct ethtool_rxnfc *nfc)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
|
|
||||||
if (!ds->ops->set_rxnfc)
|
if (!ds->ops->set_rxnfc)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
return ds->ops->set_rxnfc(ds, p->dp->index, nfc);
|
return ds->ops->set_rxnfc(ds, dp->index, nfc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct ethtool_ops dsa_slave_ethtool_ops = {
|
static const struct ethtool_ops dsa_slave_ethtool_ops = {
|
||||||
@ -933,8 +922,9 @@ static struct device_type dsa_type = {
|
|||||||
|
|
||||||
static void dsa_slave_adjust_link(struct net_device *dev)
|
static void dsa_slave_adjust_link(struct net_device *dev)
|
||||||
{
|
{
|
||||||
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_slave_priv *p = netdev_priv(dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
unsigned int status_changed = 0;
|
unsigned int status_changed = 0;
|
||||||
|
|
||||||
if (p->old_link != dev->phydev->link) {
|
if (p->old_link != dev->phydev->link) {
|
||||||
@ -953,7 +943,7 @@ static void dsa_slave_adjust_link(struct net_device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ds->ops->adjust_link && status_changed)
|
if (ds->ops->adjust_link && status_changed)
|
||||||
ds->ops->adjust_link(ds, p->dp->index, dev->phydev);
|
ds->ops->adjust_link(ds, dp->index, dev->phydev);
|
||||||
|
|
||||||
if (status_changed)
|
if (status_changed)
|
||||||
phy_print_status(dev->phydev);
|
phy_print_status(dev->phydev);
|
||||||
@ -962,14 +952,14 @@ static void dsa_slave_adjust_link(struct net_device *dev)
|
|||||||
static int dsa_slave_fixed_link_update(struct net_device *dev,
|
static int dsa_slave_fixed_link_update(struct net_device *dev,
|
||||||
struct fixed_phy_status *status)
|
struct fixed_phy_status *status)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p;
|
|
||||||
struct dsa_switch *ds;
|
struct dsa_switch *ds;
|
||||||
|
struct dsa_port *dp;
|
||||||
|
|
||||||
if (dev) {
|
if (dev) {
|
||||||
p = netdev_priv(dev);
|
dp = dsa_slave_to_port(dev);
|
||||||
ds = p->dp->ds;
|
ds = dp->ds;
|
||||||
if (ds->ops->fixed_link_update)
|
if (ds->ops->fixed_link_update)
|
||||||
ds->ops->fixed_link_update(ds, p->dp->index, status);
|
ds->ops->fixed_link_update(ds, dp->index, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -978,8 +968,9 @@ static int dsa_slave_fixed_link_update(struct net_device *dev,
|
|||||||
/* slave device setup *******************************************************/
|
/* slave device setup *******************************************************/
|
||||||
static int dsa_slave_phy_connect(struct net_device *slave_dev, int addr)
|
static int dsa_slave_phy_connect(struct net_device *slave_dev, int addr)
|
||||||
{
|
{
|
||||||
|
struct dsa_port *dp = dsa_slave_to_port(slave_dev);
|
||||||
struct dsa_slave_priv *p = netdev_priv(slave_dev);
|
struct dsa_slave_priv *p = netdev_priv(slave_dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
|
|
||||||
slave_dev->phydev = mdiobus_get_phy(ds->slave_mii_bus, addr);
|
slave_dev->phydev = mdiobus_get_phy(ds->slave_mii_bus, addr);
|
||||||
if (!slave_dev->phydev) {
|
if (!slave_dev->phydev) {
|
||||||
@ -997,14 +988,15 @@ static int dsa_slave_phy_connect(struct net_device *slave_dev, int addr)
|
|||||||
|
|
||||||
static int dsa_slave_phy_setup(struct net_device *slave_dev)
|
static int dsa_slave_phy_setup(struct net_device *slave_dev)
|
||||||
{
|
{
|
||||||
|
struct dsa_port *dp = dsa_slave_to_port(slave_dev);
|
||||||
struct dsa_slave_priv *p = netdev_priv(slave_dev);
|
struct dsa_slave_priv *p = netdev_priv(slave_dev);
|
||||||
struct dsa_switch *ds = p->dp->ds;
|
struct device_node *port_dn = dp->dn;
|
||||||
struct device_node *phy_dn, *port_dn;
|
struct dsa_switch *ds = dp->ds;
|
||||||
|
struct device_node *phy_dn;
|
||||||
bool phy_is_fixed = false;
|
bool phy_is_fixed = false;
|
||||||
u32 phy_flags = 0;
|
u32 phy_flags = 0;
|
||||||
int mode, ret;
|
int mode, ret;
|
||||||
|
|
||||||
port_dn = p->dp->dn;
|
|
||||||
mode = of_get_phy_mode(port_dn);
|
mode = of_get_phy_mode(port_dn);
|
||||||
if (mode < 0)
|
if (mode < 0)
|
||||||
mode = PHY_INTERFACE_MODE_NA;
|
mode = PHY_INTERFACE_MODE_NA;
|
||||||
@ -1025,7 +1017,7 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ds->ops->get_phy_flags)
|
if (ds->ops->get_phy_flags)
|
||||||
phy_flags = ds->ops->get_phy_flags(ds, p->dp->index);
|
phy_flags = ds->ops->get_phy_flags(ds, dp->index);
|
||||||
|
|
||||||
if (phy_dn) {
|
if (phy_dn) {
|
||||||
int phy_id = of_mdio_parse_addr(&slave_dev->dev, phy_dn);
|
int phy_id = of_mdio_parse_addr(&slave_dev->dev, phy_dn);
|
||||||
@ -1061,10 +1053,10 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev)
|
|||||||
* MDIO bus instead
|
* MDIO bus instead
|
||||||
*/
|
*/
|
||||||
if (!slave_dev->phydev) {
|
if (!slave_dev->phydev) {
|
||||||
ret = dsa_slave_phy_connect(slave_dev, p->dp->index);
|
ret = dsa_slave_phy_connect(slave_dev, dp->index);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
netdev_err(slave_dev, "failed to connect to port %d: %d\n",
|
netdev_err(slave_dev, "failed to connect to port %d: %d\n",
|
||||||
p->dp->index, ret);
|
dp->index, ret);
|
||||||
if (phy_is_fixed)
|
if (phy_is_fixed)
|
||||||
of_phy_deregister_fixed_link(port_dn);
|
of_phy_deregister_fixed_link(port_dn);
|
||||||
return ret;
|
return ret;
|
||||||
@ -1114,19 +1106,29 @@ int dsa_slave_resume(struct net_device *slave_dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dsa_slave_notify(struct net_device *dev, unsigned long val)
|
||||||
|
{
|
||||||
|
struct net_device *master = dsa_slave_to_master(dev);
|
||||||
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
|
struct dsa_notifier_register_info rinfo = {
|
||||||
|
.switch_number = dp->ds->index,
|
||||||
|
.port_number = dp->index,
|
||||||
|
.master = master,
|
||||||
|
.info.dev = dev,
|
||||||
|
};
|
||||||
|
|
||||||
|
call_dsa_notifiers(val, dev, &rinfo.info);
|
||||||
|
}
|
||||||
|
|
||||||
int dsa_slave_create(struct dsa_port *port, const char *name)
|
int dsa_slave_create(struct dsa_port *port, const char *name)
|
||||||
{
|
{
|
||||||
struct dsa_notifier_register_info rinfo = { };
|
struct dsa_port *cpu_dp = port->cpu_dp;
|
||||||
|
struct net_device *master = cpu_dp->master;
|
||||||
struct dsa_switch *ds = port->ds;
|
struct dsa_switch *ds = port->ds;
|
||||||
struct net_device *master;
|
|
||||||
struct net_device *slave_dev;
|
struct net_device *slave_dev;
|
||||||
struct dsa_slave_priv *p;
|
struct dsa_slave_priv *p;
|
||||||
struct dsa_port *cpu_dp;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
cpu_dp = ds->dst->cpu_dp;
|
|
||||||
master = cpu_dp->netdev;
|
|
||||||
|
|
||||||
if (!ds->num_tx_queues)
|
if (!ds->num_tx_queues)
|
||||||
ds->num_tx_queues = 1;
|
ds->num_tx_queues = 1;
|
||||||
|
|
||||||
@ -1168,7 +1170,7 @@ int dsa_slave_create(struct dsa_port *port, const char *name)
|
|||||||
p->old_link = -1;
|
p->old_link = -1;
|
||||||
p->old_duplex = -1;
|
p->old_duplex = -1;
|
||||||
|
|
||||||
port->netdev = slave_dev;
|
port->slave = slave_dev;
|
||||||
|
|
||||||
netif_carrier_off(slave_dev);
|
netif_carrier_off(slave_dev);
|
||||||
|
|
||||||
@ -1178,11 +1180,7 @@ int dsa_slave_create(struct dsa_port *port, const char *name)
|
|||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
rinfo.info.dev = slave_dev;
|
dsa_slave_notify(slave_dev, DSA_PORT_REGISTER);
|
||||||
rinfo.master = master;
|
|
||||||
rinfo.port_number = p->dp->index;
|
|
||||||
rinfo.switch_number = p->dp->ds->index;
|
|
||||||
call_dsa_notifiers(DSA_PORT_REGISTER, slave_dev, &rinfo.info);
|
|
||||||
|
|
||||||
ret = register_netdev(slave_dev);
|
ret = register_netdev(slave_dev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -1195,22 +1193,20 @@ int dsa_slave_create(struct dsa_port *port, const char *name)
|
|||||||
|
|
||||||
out_phy:
|
out_phy:
|
||||||
phy_disconnect(slave_dev->phydev);
|
phy_disconnect(slave_dev->phydev);
|
||||||
if (of_phy_is_fixed_link(p->dp->dn))
|
if (of_phy_is_fixed_link(port->dn))
|
||||||
of_phy_deregister_fixed_link(p->dp->dn);
|
of_phy_deregister_fixed_link(port->dn);
|
||||||
out_free:
|
out_free:
|
||||||
free_percpu(p->stats64);
|
free_percpu(p->stats64);
|
||||||
free_netdev(slave_dev);
|
free_netdev(slave_dev);
|
||||||
port->netdev = NULL;
|
port->slave = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dsa_slave_destroy(struct net_device *slave_dev)
|
void dsa_slave_destroy(struct net_device *slave_dev)
|
||||||
{
|
{
|
||||||
|
struct dsa_port *dp = dsa_slave_to_port(slave_dev);
|
||||||
struct dsa_slave_priv *p = netdev_priv(slave_dev);
|
struct dsa_slave_priv *p = netdev_priv(slave_dev);
|
||||||
struct dsa_notifier_register_info rinfo = { };
|
struct device_node *port_dn = dp->dn;
|
||||||
struct device_node *port_dn;
|
|
||||||
|
|
||||||
port_dn = p->dp->dn;
|
|
||||||
|
|
||||||
netif_carrier_off(slave_dev);
|
netif_carrier_off(slave_dev);
|
||||||
if (slave_dev->phydev) {
|
if (slave_dev->phydev) {
|
||||||
@ -1219,11 +1215,7 @@ void dsa_slave_destroy(struct net_device *slave_dev)
|
|||||||
if (of_phy_is_fixed_link(port_dn))
|
if (of_phy_is_fixed_link(port_dn))
|
||||||
of_phy_deregister_fixed_link(port_dn);
|
of_phy_deregister_fixed_link(port_dn);
|
||||||
}
|
}
|
||||||
rinfo.info.dev = slave_dev;
|
dsa_slave_notify(slave_dev, DSA_PORT_UNREGISTER);
|
||||||
rinfo.master = p->dp->cpu_dp->netdev;
|
|
||||||
rinfo.port_number = p->dp->index;
|
|
||||||
rinfo.switch_number = p->dp->ds->index;
|
|
||||||
call_dsa_notifiers(DSA_PORT_UNREGISTER, slave_dev, &rinfo.info);
|
|
||||||
unregister_netdev(slave_dev);
|
unregister_netdev(slave_dev);
|
||||||
free_percpu(p->stats64);
|
free_percpu(p->stats64);
|
||||||
free_netdev(slave_dev);
|
free_netdev(slave_dev);
|
||||||
@ -1237,8 +1229,7 @@ static bool dsa_slave_dev_check(struct net_device *dev)
|
|||||||
static int dsa_slave_changeupper(struct net_device *dev,
|
static int dsa_slave_changeupper(struct net_device *dev,
|
||||||
struct netdev_notifier_changeupper_info *info)
|
struct netdev_notifier_changeupper_info *info)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct dsa_port *dp = p->dp;
|
|
||||||
int err = NOTIFY_DONE;
|
int err = NOTIFY_DONE;
|
||||||
|
|
||||||
if (netif_is_bridge_master(info->upper_dev)) {
|
if (netif_is_bridge_master(info->upper_dev)) {
|
||||||
@ -1281,14 +1272,14 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work)
|
|||||||
container_of(work, struct dsa_switchdev_event_work, work);
|
container_of(work, struct dsa_switchdev_event_work, work);
|
||||||
struct net_device *dev = switchdev_work->dev;
|
struct net_device *dev = switchdev_work->dev;
|
||||||
struct switchdev_notifier_fdb_info *fdb_info;
|
struct switchdev_notifier_fdb_info *fdb_info;
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
switch (switchdev_work->event) {
|
switch (switchdev_work->event) {
|
||||||
case SWITCHDEV_FDB_ADD_TO_DEVICE:
|
case SWITCHDEV_FDB_ADD_TO_DEVICE:
|
||||||
fdb_info = &switchdev_work->fdb_info;
|
fdb_info = &switchdev_work->fdb_info;
|
||||||
err = dsa_port_fdb_add(p->dp, fdb_info->addr, fdb_info->vid);
|
err = dsa_port_fdb_add(dp, fdb_info->addr, fdb_info->vid);
|
||||||
if (err) {
|
if (err) {
|
||||||
netdev_dbg(dev, "fdb add failed err=%d\n", err);
|
netdev_dbg(dev, "fdb add failed err=%d\n", err);
|
||||||
break;
|
break;
|
||||||
@ -1299,7 +1290,7 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work)
|
|||||||
|
|
||||||
case SWITCHDEV_FDB_DEL_TO_DEVICE:
|
case SWITCHDEV_FDB_DEL_TO_DEVICE:
|
||||||
fdb_info = &switchdev_work->fdb_info;
|
fdb_info = &switchdev_work->fdb_info;
|
||||||
err = dsa_port_fdb_del(p->dp, fdb_info->addr, fdb_info->vid);
|
err = dsa_port_fdb_del(dp, fdb_info->addr, fdb_info->vid);
|
||||||
if (err) {
|
if (err) {
|
||||||
netdev_dbg(dev, "fdb del failed err=%d\n", err);
|
netdev_dbg(dev, "fdb del failed err=%d\n", err);
|
||||||
dev_close(dev);
|
dev_close(dev);
|
||||||
|
@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
static struct sk_buff *brcm_tag_xmit(struct sk_buff *skb, struct net_device *dev)
|
static struct sk_buff *brcm_tag_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
u16 queue = skb_get_queue_mapping(skb);
|
u16 queue = skb_get_queue_mapping(skb);
|
||||||
u8 *brcm_tag;
|
u8 *brcm_tag;
|
||||||
|
|
||||||
@ -82,15 +82,14 @@ static struct sk_buff *brcm_tag_xmit(struct sk_buff *skb, struct net_device *dev
|
|||||||
((queue & BRCM_IG_TC_MASK) << BRCM_IG_TC_SHIFT);
|
((queue & BRCM_IG_TC_MASK) << BRCM_IG_TC_SHIFT);
|
||||||
brcm_tag[1] = 0;
|
brcm_tag[1] = 0;
|
||||||
brcm_tag[2] = 0;
|
brcm_tag[2] = 0;
|
||||||
if (p->dp->index == 8)
|
if (dp->index == 8)
|
||||||
brcm_tag[2] = BRCM_IG_DSTMAP2_MASK;
|
brcm_tag[2] = BRCM_IG_DSTMAP2_MASK;
|
||||||
brcm_tag[3] = (1 << p->dp->index) & BRCM_IG_DSTMAP1_MASK;
|
brcm_tag[3] = (1 << dp->index) & BRCM_IG_DSTMAP1_MASK;
|
||||||
|
|
||||||
/* Now tell the master network device about the desired output queue
|
/* Now tell the master network device about the desired output queue
|
||||||
* as well
|
* as well
|
||||||
*/
|
*/
|
||||||
skb_set_queue_mapping(skb, BRCM_TAG_SET_PORT_QUEUE(p->dp->index,
|
skb_set_queue_mapping(skb, BRCM_TAG_SET_PORT_QUEUE(dp->index, queue));
|
||||||
queue));
|
|
||||||
|
|
||||||
return skb;
|
return skb;
|
||||||
}
|
}
|
||||||
@ -120,7 +119,7 @@ static struct sk_buff *brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev,
|
|||||||
/* Locate which port this is coming from */
|
/* Locate which port this is coming from */
|
||||||
source_port = brcm_tag[3] & BRCM_EG_PID_MASK;
|
source_port = brcm_tag[3] & BRCM_EG_PID_MASK;
|
||||||
|
|
||||||
skb->dev = dsa_master_get_slave(dev, 0, source_port);
|
skb->dev = dsa_master_find_slave(dev, 0, source_port);
|
||||||
if (!skb->dev)
|
if (!skb->dev)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
static struct sk_buff *dsa_xmit(struct sk_buff *skb, struct net_device *dev)
|
static struct sk_buff *dsa_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
u8 *dsa_header;
|
u8 *dsa_header;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -34,8 +34,8 @@ static struct sk_buff *dsa_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||||||
* Construct tagged FROM_CPU DSA tag from 802.1q tag.
|
* Construct tagged FROM_CPU DSA tag from 802.1q tag.
|
||||||
*/
|
*/
|
||||||
dsa_header = skb->data + 2 * ETH_ALEN;
|
dsa_header = skb->data + 2 * ETH_ALEN;
|
||||||
dsa_header[0] = 0x60 | p->dp->ds->index;
|
dsa_header[0] = 0x60 | dp->ds->index;
|
||||||
dsa_header[1] = p->dp->index << 3;
|
dsa_header[1] = dp->index << 3;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Move CFI field from byte 2 to byte 1.
|
* Move CFI field from byte 2 to byte 1.
|
||||||
@ -55,8 +55,8 @@ static struct sk_buff *dsa_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||||||
* Construct untagged FROM_CPU DSA tag.
|
* Construct untagged FROM_CPU DSA tag.
|
||||||
*/
|
*/
|
||||||
dsa_header = skb->data + 2 * ETH_ALEN;
|
dsa_header = skb->data + 2 * ETH_ALEN;
|
||||||
dsa_header[0] = 0x40 | p->dp->ds->index;
|
dsa_header[0] = 0x40 | dp->ds->index;
|
||||||
dsa_header[1] = p->dp->index << 3;
|
dsa_header[1] = dp->index << 3;
|
||||||
dsa_header[2] = 0x00;
|
dsa_header[2] = 0x00;
|
||||||
dsa_header[3] = 0x00;
|
dsa_header[3] = 0x00;
|
||||||
}
|
}
|
||||||
@ -91,7 +91,7 @@ static struct sk_buff *dsa_rcv(struct sk_buff *skb, struct net_device *dev,
|
|||||||
source_device = dsa_header[0] & 0x1f;
|
source_device = dsa_header[0] & 0x1f;
|
||||||
source_port = (dsa_header[1] >> 3) & 0x1f;
|
source_port = (dsa_header[1] >> 3) & 0x1f;
|
||||||
|
|
||||||
skb->dev = dsa_master_get_slave(dev, source_device, source_port);
|
skb->dev = dsa_master_find_slave(dev, source_device, source_port);
|
||||||
if (!skb->dev)
|
if (!skb->dev)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev)
|
static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
u8 *edsa_header;
|
u8 *edsa_header;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -43,8 +43,8 @@ static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||||||
edsa_header[1] = ETH_P_EDSA & 0xff;
|
edsa_header[1] = ETH_P_EDSA & 0xff;
|
||||||
edsa_header[2] = 0x00;
|
edsa_header[2] = 0x00;
|
||||||
edsa_header[3] = 0x00;
|
edsa_header[3] = 0x00;
|
||||||
edsa_header[4] = 0x60 | p->dp->ds->index;
|
edsa_header[4] = 0x60 | dp->ds->index;
|
||||||
edsa_header[5] = p->dp->index << 3;
|
edsa_header[5] = dp->index << 3;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Move CFI field from byte 6 to byte 5.
|
* Move CFI field from byte 6 to byte 5.
|
||||||
@ -68,8 +68,8 @@ static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||||||
edsa_header[1] = ETH_P_EDSA & 0xff;
|
edsa_header[1] = ETH_P_EDSA & 0xff;
|
||||||
edsa_header[2] = 0x00;
|
edsa_header[2] = 0x00;
|
||||||
edsa_header[3] = 0x00;
|
edsa_header[3] = 0x00;
|
||||||
edsa_header[4] = 0x40 | p->dp->ds->index;
|
edsa_header[4] = 0x40 | dp->ds->index;
|
||||||
edsa_header[5] = p->dp->index << 3;
|
edsa_header[5] = dp->index << 3;
|
||||||
edsa_header[6] = 0x00;
|
edsa_header[6] = 0x00;
|
||||||
edsa_header[7] = 0x00;
|
edsa_header[7] = 0x00;
|
||||||
}
|
}
|
||||||
@ -104,7 +104,7 @@ static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev,
|
|||||||
source_device = edsa_header[0] & 0x1f;
|
source_device = edsa_header[0] & 0x1f;
|
||||||
source_port = (edsa_header[1] >> 3) & 0x1f;
|
source_port = (edsa_header[1] >> 3) & 0x1f;
|
||||||
|
|
||||||
skb->dev = dsa_master_get_slave(dev, source_device, source_port);
|
skb->dev = dsa_master_find_slave(dev, source_device, source_port);
|
||||||
if (!skb->dev)
|
if (!skb->dev)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev)
|
static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct sk_buff *nskb;
|
struct sk_buff *nskb;
|
||||||
int padlen;
|
int padlen;
|
||||||
u8 *tag;
|
u8 *tag;
|
||||||
@ -72,7 +72,7 @@ static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||||||
|
|
||||||
tag = skb_put(nskb, KSZ_INGRESS_TAG_LEN);
|
tag = skb_put(nskb, KSZ_INGRESS_TAG_LEN);
|
||||||
tag[0] = 0;
|
tag[0] = 0;
|
||||||
tag[1] = 1 << p->dp->index; /* destination port */
|
tag[1] = 1 << dp->index; /* destination port */
|
||||||
|
|
||||||
return nskb;
|
return nskb;
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@ static struct sk_buff *ksz_rcv(struct sk_buff *skb, struct net_device *dev,
|
|||||||
|
|
||||||
source_port = tag[0] & 7;
|
source_port = tag[0] & 7;
|
||||||
|
|
||||||
skb->dev = dsa_master_get_slave(dev, 0, source_port);
|
skb->dev = dsa_master_find_slave(dev, 0, source_port);
|
||||||
if (!skb->dev)
|
if (!skb->dev)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
static struct sk_buff *lan9303_xmit(struct sk_buff *skb, struct net_device *dev)
|
static struct sk_buff *lan9303_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
u16 *lan9303_tag;
|
u16 *lan9303_tag;
|
||||||
|
|
||||||
/* insert a special VLAN tag between the MAC addresses
|
/* insert a special VLAN tag between the MAC addresses
|
||||||
@ -62,7 +62,7 @@ static struct sk_buff *lan9303_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||||||
|
|
||||||
lan9303_tag = (u16 *)(skb->data + 2 * ETH_ALEN);
|
lan9303_tag = (u16 *)(skb->data + 2 * ETH_ALEN);
|
||||||
lan9303_tag[0] = htons(ETH_P_8021Q);
|
lan9303_tag[0] = htons(ETH_P_8021Q);
|
||||||
lan9303_tag[1] = htons(p->dp->index | BIT(4));
|
lan9303_tag[1] = htons(dp->index | BIT(4));
|
||||||
|
|
||||||
return skb;
|
return skb;
|
||||||
}
|
}
|
||||||
@ -94,7 +94,7 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev,
|
|||||||
|
|
||||||
source_port = ntohs(lan9303_tag[1]) & 0x3;
|
source_port = ntohs(lan9303_tag[1]) & 0x3;
|
||||||
|
|
||||||
skb->dev = dsa_master_get_slave(dev, 0, source_port);
|
skb->dev = dsa_master_find_slave(dev, 0, source_port);
|
||||||
if (!skb->dev) {
|
if (!skb->dev) {
|
||||||
dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid source port\n");
|
dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid source port\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
|
static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
|
||||||
struct net_device *dev)
|
struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
u8 *mtk_tag;
|
u8 *mtk_tag;
|
||||||
|
|
||||||
if (skb_cow_head(skb, MTK_HDR_LEN) < 0)
|
if (skb_cow_head(skb, MTK_HDR_LEN) < 0)
|
||||||
@ -36,7 +36,7 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
|
|||||||
/* Build the tag after the MAC Source Address */
|
/* Build the tag after the MAC Source Address */
|
||||||
mtk_tag = skb->data + 2 * ETH_ALEN;
|
mtk_tag = skb->data + 2 * ETH_ALEN;
|
||||||
mtk_tag[0] = 0;
|
mtk_tag[0] = 0;
|
||||||
mtk_tag[1] = (1 << p->dp->index) & MTK_HDR_XMIT_DP_BIT_MASK;
|
mtk_tag[1] = (1 << dp->index) & MTK_HDR_XMIT_DP_BIT_MASK;
|
||||||
mtk_tag[2] = 0;
|
mtk_tag[2] = 0;
|
||||||
mtk_tag[3] = 0;
|
mtk_tag[3] = 0;
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
|
|||||||
/* Get source port information */
|
/* Get source port information */
|
||||||
port = (hdr & MTK_HDR_RECV_SOURCE_PORT_MASK);
|
port = (hdr & MTK_HDR_RECV_SOURCE_PORT_MASK);
|
||||||
|
|
||||||
skb->dev = dsa_master_get_slave(dev, 0, port);
|
skb->dev = dsa_master_find_slave(dev, 0, port);
|
||||||
if (!skb->dev)
|
if (!skb->dev)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
|
|
||||||
static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev)
|
static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
u16 *phdr, hdr;
|
u16 *phdr, hdr;
|
||||||
|
|
||||||
dev->stats.tx_packets++;
|
dev->stats.tx_packets++;
|
||||||
@ -54,8 +54,7 @@ static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||||||
|
|
||||||
/* Set the version field, and set destination port information */
|
/* Set the version field, and set destination port information */
|
||||||
hdr = QCA_HDR_VERSION << QCA_HDR_XMIT_VERSION_S |
|
hdr = QCA_HDR_VERSION << QCA_HDR_XMIT_VERSION_S |
|
||||||
QCA_HDR_XMIT_FROM_CPU |
|
QCA_HDR_XMIT_FROM_CPU | BIT(dp->index);
|
||||||
BIT(p->dp->index);
|
|
||||||
|
|
||||||
*phdr = htons(hdr);
|
*phdr = htons(hdr);
|
||||||
|
|
||||||
@ -92,7 +91,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev,
|
|||||||
/* Get source port information */
|
/* Get source port information */
|
||||||
port = (hdr & QCA_HDR_RECV_SOURCE_PORT_MASK);
|
port = (hdr & QCA_HDR_RECV_SOURCE_PORT_MASK);
|
||||||
|
|
||||||
skb->dev = dsa_master_get_slave(dev, 0, port);
|
skb->dev = dsa_master_find_slave(dev, 0, port);
|
||||||
if (!skb->dev)
|
if (!skb->dev)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
static struct sk_buff *trailer_xmit(struct sk_buff *skb, struct net_device *dev)
|
static struct sk_buff *trailer_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct sk_buff *nskb;
|
struct sk_buff *nskb;
|
||||||
int padlen;
|
int padlen;
|
||||||
u8 *trailer;
|
u8 *trailer;
|
||||||
@ -48,7 +48,7 @@ static struct sk_buff *trailer_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||||||
|
|
||||||
trailer = skb_put(nskb, 4);
|
trailer = skb_put(nskb, 4);
|
||||||
trailer[0] = 0x80;
|
trailer[0] = 0x80;
|
||||||
trailer[1] = 1 << p->dp->index;
|
trailer[1] = 1 << dp->index;
|
||||||
trailer[2] = 0x10;
|
trailer[2] = 0x10;
|
||||||
trailer[3] = 0x00;
|
trailer[3] = 0x00;
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev,
|
|||||||
|
|
||||||
source_port = trailer[1] & 7;
|
source_port = trailer[1] & 7;
|
||||||
|
|
||||||
skb->dev = dsa_master_get_slave(dev, 0, source_port);
|
skb->dev = dsa_master_find_slave(dev, 0, source_port);
|
||||||
if (!skb->dev)
|
if (!skb->dev)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user