diff options
Diffstat (limited to 'net/dsa/slave.c')
| -rw-r--r-- | net/dsa/slave.c | 95 | 
1 files changed, 69 insertions, 26 deletions
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 992fcab4b552..8c0f3c6ab365 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -15,11 +15,11 @@  #include <linux/mdio.h>  #include <net/rtnetlink.h>  #include <net/pkt_cls.h> +#include <net/selftests.h>  #include <net/tc_act/tc_mirred.h>  #include <linux/if_bridge.h>  #include <linux/if_hsr.h>  #include <linux/netpoll.h> -#include <linux/ptp_classify.h>  #include "dsa_priv.h" @@ -555,26 +555,14 @@ static void dsa_skb_tx_timestamp(struct dsa_slave_priv *p,  				 struct sk_buff *skb)  {  	struct dsa_switch *ds = p->dp->ds; -	struct sk_buff *clone; -	unsigned int type; -	type = ptp_classify_raw(skb); -	if (type == PTP_CLASS_NONE) +	if (!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))  		return;  	if (!ds->ops->port_txtstamp)  		return; -	clone = skb_clone_sk(skb); -	if (!clone) -		return; - -	if (ds->ops->port_txtstamp(ds, p->dp->index, clone, type)) { -		DSA_SKB_CB(skb)->clone = clone; -		return; -	} - -	kfree_skb(clone); +	ds->ops->port_txtstamp(ds, p->dp->index, skb);  }  netdev_tx_t dsa_enqueue_skb(struct sk_buff *skb, struct net_device *dev) @@ -626,11 +614,9 @@ static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)  	dev_sw_netstats_tx_add(dev, 1, skb->len); -	DSA_SKB_CB(skb)->clone = NULL; +	memset(skb->cb, 0, sizeof(skb->cb)); -	/* Identify PTP protocol packets, clone them, and pass them to the -	 * switch driver -	 */ +	/* Handle tx timestamp if any */  	dsa_skb_tx_timestamp(p, skb);  	if (dsa_realloc_skb(skb, dev)) { @@ -748,7 +734,10 @@ static void dsa_slave_get_strings(struct net_device *dev,  		if (ds->ops->get_strings)  			ds->ops->get_strings(ds, dp->index, stringset,  					     data + 4 * len); +	} else if (stringset ==  ETH_SS_TEST) { +		net_selftest_get_strings(data);  	} +  }  static void dsa_slave_get_ethtool_stats(struct net_device *dev, @@ -794,11 +783,27 @@ static int dsa_slave_get_sset_count(struct net_device *dev, int sset)  			count += ds->ops->get_sset_count(ds, dp->index, sset);  		return count; +	} else if (sset ==  ETH_SS_TEST) { +		return net_selftest_get_count();  	}  	return -EOPNOTSUPP;  } +static void dsa_slave_net_selftest(struct net_device *ndev, +				   struct ethtool_test *etest, u64 *buf) +{ +	struct dsa_port *dp = dsa_slave_to_port(ndev); +	struct dsa_switch *ds = dp->ds; + +	if (ds->ops->self_test) { +		ds->ops->self_test(ds, dp->index, etest, buf); +		return; +	} + +	net_selftest(ndev, etest, buf); +} +  static void dsa_slave_get_wol(struct net_device *dev, struct ethtool_wolinfo *w)  {  	struct dsa_port *dp = dsa_slave_to_port(dev); @@ -1278,14 +1283,32 @@ static int dsa_slave_setup_tc_block(struct net_device *dev,  	}  } +static int dsa_slave_setup_ft_block(struct dsa_switch *ds, int port, +				    void *type_data) +{ +	struct dsa_port *cpu_dp = dsa_to_port(ds, port)->cpu_dp; +	struct net_device *master = cpu_dp->master; + +	if (!master->netdev_ops->ndo_setup_tc) +		return -EOPNOTSUPP; + +	return master->netdev_ops->ndo_setup_tc(master, TC_SETUP_FT, type_data); +} +  static int dsa_slave_setup_tc(struct net_device *dev, enum tc_setup_type type,  			      void *type_data)  {  	struct dsa_port *dp = dsa_slave_to_port(dev);  	struct dsa_switch *ds = dp->ds; -	if (type == TC_SETUP_BLOCK) +	switch (type) { +	case TC_SETUP_BLOCK:  		return dsa_slave_setup_tc_block(dev, type_data); +	case TC_SETUP_FT: +		return dsa_slave_setup_ft_block(ds, dp->index, type_data); +	default: +		break; +	}  	if (!ds->ops->port_setup_tc)  		return -EOPNOTSUPP; @@ -1612,6 +1635,7 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {  	.get_rxnfc		= dsa_slave_get_rxnfc,  	.set_rxnfc		= dsa_slave_set_rxnfc,  	.get_ts_info		= dsa_slave_get_ts_info, +	.self_test		= dsa_slave_net_selftest,  };  /* legacy way, bypassing the bridge *****************************************/ @@ -1654,6 +1678,21 @@ static void dsa_slave_get_stats64(struct net_device *dev,  		dev_get_tstats64(dev, s);  } +static int dsa_slave_fill_forward_path(struct net_device_path_ctx *ctx, +				       struct net_device_path *path) +{ +	struct dsa_port *dp = dsa_slave_to_port(ctx->dev); +	struct dsa_port *cpu_dp = dp->cpu_dp; + +	path->dev = ctx->dev; +	path->type = DEV_PATH_DSA; +	path->dsa.proto = cpu_dp->tag_ops->proto; +	path->dsa.port = dp->index; +	ctx->dev = cpu_dp->master; + +	return 0; +} +  static const struct net_device_ops dsa_slave_netdev_ops = {  	.ndo_open	 	= dsa_slave_open,  	.ndo_stop		= dsa_slave_close, @@ -1679,6 +1718,7 @@ static const struct net_device_ops dsa_slave_netdev_ops = {  	.ndo_vlan_rx_kill_vid	= dsa_slave_vlan_rx_kill_vid,  	.ndo_get_devlink_port	= dsa_slave_get_devlink_port,  	.ndo_change_mtu		= dsa_slave_change_mtu, +	.ndo_fill_forward_path	= dsa_slave_fill_forward_path,  };  static struct device_type dsa_type = { @@ -1862,7 +1902,7 @@ int dsa_slave_create(struct dsa_port *port)  	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)) +	if (!is_zero_ether_addr(port->mac))  		ether_addr_copy(slave_dev->dev_addr, port->mac);  	else  		eth_hw_addr_inherit(slave_dev, master); @@ -1976,11 +2016,14 @@ static int dsa_slave_changeupper(struct net_device *dev,  				 struct netdev_notifier_changeupper_info *info)  {  	struct dsa_port *dp = dsa_slave_to_port(dev); +	struct netlink_ext_ack *extack;  	int err = NOTIFY_DONE; +	extack = netdev_notifier_info_to_extack(&info->info); +  	if (netif_is_bridge_master(info->upper_dev)) {  		if (info->linking) { -			err = dsa_port_bridge_join(dp, info->upper_dev); +			err = dsa_port_bridge_join(dp, info->upper_dev, extack);  			if (!err)  				dsa_bridge_mtu_normalization(dp);  			err = notifier_from_errno(err); @@ -1991,7 +2034,7 @@ static int dsa_slave_changeupper(struct net_device *dev,  	} else if (netif_is_lag_master(info->upper_dev)) {  		if (info->linking) {  			err = dsa_port_lag_join(dp, info->upper_dev, -						info->upper_info); +						info->upper_info, extack);  			if (err == -EOPNOTSUPP) {  				NL_SET_ERR_MSG_MOD(info->info.extack,  						   "Offloading not supported"); @@ -2292,7 +2335,7 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,  		fdb_info = ptr;  		if (dsa_slave_dev_check(dev)) { -			if (!fdb_info->added_by_user) +			if (!fdb_info->added_by_user || fdb_info->is_local)  				return NOTIFY_OK;  			dp = dsa_slave_to_port(dev); @@ -2389,11 +2432,11 @@ static struct notifier_block dsa_slave_nb __read_mostly = {  	.notifier_call  = dsa_slave_netdevice_event,  }; -static struct notifier_block dsa_slave_switchdev_notifier = { +struct notifier_block dsa_slave_switchdev_notifier = {  	.notifier_call = dsa_slave_switchdev_event,  }; -static struct notifier_block dsa_slave_switchdev_blocking_notifier = { +struct notifier_block dsa_slave_switchdev_blocking_notifier = {  	.notifier_call = dsa_slave_switchdev_blocking_event,  };  | 
