aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/net/dsa/slave.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dsa/slave.c')
-rw-r--r--net/dsa/slave.c62
1 files changed, 42 insertions, 20 deletions
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 62f4ee3da172..4c7f086a047b 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -314,7 +314,7 @@ static int dsa_slave_vlan_add(struct net_device *dev,
if (obj->orig_dev != dev)
return -EOPNOTSUPP;
- if (dp->bridge_dev && !br_vlan_enabled(dp->bridge_dev))
+ if (dsa_port_skip_vlan_configuration(dp))
return 0;
vlan = *SWITCHDEV_OBJ_PORT_VLAN(obj);
@@ -381,7 +381,7 @@ static int dsa_slave_vlan_del(struct net_device *dev,
if (obj->orig_dev != dev)
return -EOPNOTSUPP;
- if (dp->bridge_dev && !br_vlan_enabled(dp->bridge_dev))
+ if (dsa_port_skip_vlan_configuration(dp))
return 0;
/* Do not deprogram the CPU port as it may be shared with other user
@@ -445,12 +445,11 @@ static inline netdev_tx_t dsa_slave_netpoll_send_skb(struct net_device *dev,
#ifdef CONFIG_NET_POLL_CONTROLLER
struct dsa_slave_priv *p = netdev_priv(dev);
- if (p->netpoll)
- netpoll_send_skb(p->netpoll, skb);
+ return netpoll_send_skb(p->netpoll, skb);
#else
BUG();
-#endif
return NETDEV_TX_OK;
+#endif
}
static void dsa_skb_tx_timestamp(struct dsa_slave_priv *p,
@@ -911,13 +910,13 @@ dsa_slave_add_cls_matchall_police(struct net_device *dev,
if (!ds->ops->port_policer_add) {
NL_SET_ERR_MSG_MOD(extack,
- "Policing offload not implemented\n");
+ "Policing offload not implemented");
return -EOPNOTSUPP;
}
if (!ingress) {
NL_SET_ERR_MSG_MOD(extack,
- "Only supported on ingress qdisc\n");
+ "Only supported on ingress qdisc");
return -EOPNOTSUPP;
}
@@ -928,7 +927,7 @@ dsa_slave_add_cls_matchall_police(struct net_device *dev,
list_for_each_entry(mall_tc_entry, &p->mall_tc_list, list) {
if (mall_tc_entry->type == DSA_PORT_MALL_POLICER) {
NL_SET_ERR_MSG_MOD(extack,
- "Only one port policer allowed\n");
+ "Only one port policer allowed");
return -EEXIST;
}
}
@@ -1241,7 +1240,7 @@ static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
* need to emulate the switchdev prepare + commit phase.
*/
if (dp->bridge_dev) {
- if (!br_vlan_enabled(dp->bridge_dev))
+ if (dsa_port_skip_vlan_configuration(dp))
return 0;
/* br_vlan_get_info() returns -EINVAL or -ENOENT if the
@@ -1275,7 +1274,7 @@ static int dsa_slave_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
* need to emulate the switchdev prepare + commit phase.
*/
if (dp->bridge_dev) {
- if (!br_vlan_enabled(dp->bridge_dev))
+ if (dsa_port_skip_vlan_configuration(dp))
return 0;
/* br_vlan_get_info() returns -EINVAL or -ENOENT if the
@@ -1588,10 +1587,10 @@ void dsa_port_phylink_mac_change(struct dsa_switch *ds, int port, bool up)
}
EXPORT_SYMBOL_GPL(dsa_port_phylink_mac_change);
-static void dsa_slave_phylink_fixed_state(struct net_device *dev,
+static void dsa_slave_phylink_fixed_state(struct phylink_config *config,
struct phylink_link_state *state)
{
- struct dsa_port *dp = dsa_slave_to_port(dev);
+ struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
struct dsa_switch *ds = dp->ds;
/* No need to check that this operation is valid, the callback would
@@ -1631,6 +1630,15 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev)
dp->pl_config.dev = &slave_dev->dev;
dp->pl_config.type = PHYLINK_NETDEV;
+ /* The get_fixed_state callback takes precedence over polling the
+ * link GPIO in PHYLINK (see phylink_get_fixed_state). Only set
+ * this if the switch provides such a callback.
+ */
+ if (ds->ops->phylink_fixed_state) {
+ dp->pl_config.get_fixed_state = dsa_slave_phylink_fixed_state;
+ dp->pl_config.poll_fixed_state = true;
+ }
+
dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(port_dn), mode,
&dsa_port_phylink_mac_ops);
if (IS_ERR(dp->pl)) {
@@ -1639,13 +1647,6 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev)
return PTR_ERR(dp->pl);
}
- /* Register only if the switch provides such a callback, since this
- * callback takes precedence over polling the link GPIO in PHYLINK
- * (see phylink_get_fixed_state).
- */
- if (ds->ops->phylink_fixed_state)
- phylink_fixed_state_cb(dp->pl, dsa_slave_phylink_fixed_state);
-
if (ds->ops->get_phy_flags)
phy_flags = ds->ops->get_phy_flags(ds, dp->index);
@@ -1667,6 +1668,15 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev)
return ret;
}
+static struct lock_class_key dsa_slave_netdev_xmit_lock_key;
+static void dsa_slave_set_lockdep_class_one(struct net_device *dev,
+ struct netdev_queue *txq,
+ void *_unused)
+{
+ lockdep_set_class(&txq->_xmit_lock,
+ &dsa_slave_netdev_xmit_lock_key);
+}
+
int dsa_slave_suspend(struct net_device *slave_dev)
{
struct dsa_port *dp = dsa_slave_to_port(slave_dev);
@@ -1736,6 +1746,7 @@ int dsa_slave_create(struct dsa_port *port)
if (ds->ops->port_vlan_add && ds->ops->port_vlan_del)
slave_dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
slave_dev->hw_features |= NETIF_F_HW_TC;
+ slave_dev->features |= NETIF_F_LLTX;
slave_dev->ethtool_ops = &dsa_slave_ethtool_ops;
if (!IS_ERR_OR_NULL(port->mac))
ether_addr_copy(slave_dev->dev_addr, port->mac);
@@ -1750,6 +1761,9 @@ int dsa_slave_create(struct dsa_port *port)
slave_dev->max_mtu = ETH_MAX_MTU;
SET_NETDEV_DEVTYPE(slave_dev, &dsa_type);
+ netdev_for_each_tx_queue(slave_dev, dsa_slave_set_lockdep_class_one,
+ NULL);
+
SET_NETDEV_DEV(slave_dev, port->ds->dev);
slave_dev->dev.of_node = port->dn;
slave_dev->vlan_features = master->vlan_features;
@@ -1760,6 +1774,11 @@ int dsa_slave_create(struct dsa_port *port)
free_netdev(slave_dev);
return -ENOMEM;
}
+
+ ret = gro_cells_init(&p->gcells, slave_dev);
+ if (ret)
+ goto out_free;
+
p->dp = port;
INIT_LIST_HEAD(&p->mall_tc_list);
p->xmit = cpu_dp->tag_ops->xmit;
@@ -1777,7 +1796,7 @@ int dsa_slave_create(struct dsa_port *port)
ret = dsa_slave_phy_setup(slave_dev);
if (ret) {
netdev_err(master, "error %d setting up slave phy\n", ret);
- goto out_free;
+ goto out_gcells;
}
dsa_slave_notify(slave_dev, DSA_PORT_REGISTER);
@@ -1796,6 +1815,8 @@ out_phy:
phylink_disconnect_phy(p->dp->pl);
rtnl_unlock();
phylink_destroy(p->dp->pl);
+out_gcells:
+ gro_cells_destroy(&p->gcells);
out_free:
free_percpu(p->stats64);
free_netdev(slave_dev);
@@ -1816,6 +1837,7 @@ void dsa_slave_destroy(struct net_device *slave_dev)
dsa_slave_notify(slave_dev, DSA_PORT_UNREGISTER);
unregister_netdev(slave_dev);
phylink_destroy(dp->pl);
+ gro_cells_destroy(&p->gcells);
free_percpu(p->stats64);
free_netdev(slave_dev);
}