mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	netdev: expose DPLL pin handle for netdevice
In case netdevice represents a SyncE port, the user needs to understand the connection between netdevice and associated DPLL pin. There might me multiple netdevices pointing to the same pin, in case of VF/SF implementation. Add a IFLA Netlink attribute to nest the DPLL pin handle, similar to how it is implemented for devlink port. Add a struct dpll_pin pointer to netdev and protect access to it by RTNL. Expose netdev_dpll_pin_set() and netdev_dpll_pin_clear() helpers to the drivers so they can set/clear the DPLL pin relationship to netdev. Note that during the lifetime of struct dpll_pin the pin handle does not change. Therefore it is save to access it lockless. It is drivers responsibility to call netdev_dpll_pin_clear() before dpll_pin_put(). Signed-off-by: Jiri Pirko <jiri@nvidia.com> Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com> Signed-off-by: Vadim Fedorenko <vadim.fedorenko@linux.dev> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									9d71b54b65
								
							
						
					
					
						commit
						5f18426928
					
				
					 6 changed files with 109 additions and 3 deletions
				
			
		| 
						 | 
					@ -47,6 +47,18 @@ dpll_msg_add_dev_parent_handle(struct sk_buff *msg, u32 id)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * dpll_msg_pin_handle_size - get size of pin handle attribute for given pin
 | 
				
			||||||
 | 
					 * @pin: pin pointer
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: byte size of pin handle attribute for given pin.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					size_t dpll_msg_pin_handle_size(struct dpll_pin *pin)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return pin ? nla_total_size(4) : 0; /* DPLL_A_PIN_ID */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(dpll_msg_pin_handle_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * dpll_msg_add_pin_handle - attach pin handle attribute to a given message
 | 
					 * dpll_msg_add_pin_handle - attach pin handle attribute to a given message
 | 
				
			||||||
 * @msg: pointer to sk_buff message to attach a pin handle
 | 
					 * @msg: pointer to sk_buff message to attach a pin handle
 | 
				
			||||||
| 
						 | 
					@ -56,8 +68,7 @@ dpll_msg_add_dev_parent_handle(struct sk_buff *msg, u32 id)
 | 
				
			||||||
 * * 0 - success
 | 
					 * * 0 - success
 | 
				
			||||||
 * * -EMSGSIZE - no space in message to attach pin handle
 | 
					 * * -EMSGSIZE - no space in message to attach pin handle
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int
 | 
					int dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin)
 | 
				
			||||||
dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!pin)
 | 
						if (!pin)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -65,6 +76,7 @@ dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin)
 | 
				
			||||||
		return -EMSGSIZE;
 | 
							return -EMSGSIZE;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(dpll_msg_add_pin_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
dpll_msg_add_mode(struct sk_buff *msg, struct dpll_device *dpll,
 | 
					dpll_msg_add_mode(struct sk_buff *msg, struct dpll_device *dpll,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,6 +101,21 @@ struct dpll_pin_properties {
 | 
				
			||||||
	struct dpll_pin_frequency *freq_supported;
 | 
						struct dpll_pin_frequency *freq_supported;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if IS_ENABLED(CONFIG_DPLL)
 | 
				
			||||||
 | 
					size_t dpll_msg_pin_handle_size(struct dpll_pin *pin);
 | 
				
			||||||
 | 
					int dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					static inline size_t dpll_msg_pin_handle_size(struct dpll_pin *pin)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct dpll_device *
 | 
					struct dpll_device *
 | 
				
			||||||
dpll_device_get(u64 clock_id, u32 dev_driver_id, struct module *module);
 | 
					dpll_device_get(u64 clock_id, u32 dev_driver_id, struct module *module);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,6 +79,8 @@ struct xdp_buff;
 | 
				
			||||||
struct xdp_frame;
 | 
					struct xdp_frame;
 | 
				
			||||||
struct xdp_metadata_ops;
 | 
					struct xdp_metadata_ops;
 | 
				
			||||||
struct xdp_md;
 | 
					struct xdp_md;
 | 
				
			||||||
 | 
					/* DPLL specific */
 | 
				
			||||||
 | 
					struct dpll_pin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef u32 xdp_features_t;
 | 
					typedef u32 xdp_features_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2049,6 +2051,9 @@ enum netdev_ml_priv_type {
 | 
				
			||||||
 *			SET_NETDEV_DEVLINK_PORT macro. This pointer is static
 | 
					 *			SET_NETDEV_DEVLINK_PORT macro. This pointer is static
 | 
				
			||||||
 *			during the time netdevice is registered.
 | 
					 *			during the time netdevice is registered.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 *	@dpll_pin: Pointer to the SyncE source pin of a DPLL subsystem,
 | 
				
			||||||
 | 
					 *		   where the clock is recovered.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 *	FIXME: cleanup struct net_device such that network protocol info
 | 
					 *	FIXME: cleanup struct net_device such that network protocol info
 | 
				
			||||||
 *	moves out.
 | 
					 *	moves out.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -2405,6 +2410,10 @@ struct net_device {
 | 
				
			||||||
	struct rtnl_hw_stats64	*offload_xstats_l3;
 | 
						struct rtnl_hw_stats64	*offload_xstats_l3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct devlink_port	*devlink_port;
 | 
						struct devlink_port	*devlink_port;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if IS_ENABLED(CONFIG_DPLL)
 | 
				
			||||||
 | 
						struct dpll_pin		*dpll_pin;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#define to_net_dev(d) container_of(d, struct net_device, dev)
 | 
					#define to_net_dev(d) container_of(d, struct net_device, dev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3940,6 +3949,18 @@ int dev_get_mac_address(struct sockaddr *sa, struct net *net, char *dev_name);
 | 
				
			||||||
int dev_get_port_parent_id(struct net_device *dev,
 | 
					int dev_get_port_parent_id(struct net_device *dev,
 | 
				
			||||||
			   struct netdev_phys_item_id *ppid, bool recurse);
 | 
								   struct netdev_phys_item_id *ppid, bool recurse);
 | 
				
			||||||
bool netdev_port_same_parent_id(struct net_device *a, struct net_device *b);
 | 
					bool netdev_port_same_parent_id(struct net_device *a, struct net_device *b);
 | 
				
			||||||
 | 
					void netdev_dpll_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin);
 | 
				
			||||||
 | 
					void netdev_dpll_pin_clear(struct net_device *dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct dpll_pin *netdev_dpll_pin(const struct net_device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if IS_ENABLED(CONFIG_DPLL)
 | 
				
			||||||
 | 
						return dev->dpll_pin;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *dev, bool *again);
 | 
					struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *dev, bool *again);
 | 
				
			||||||
struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 | 
					struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 | 
				
			||||||
				    struct netdev_queue *txq, int *ret);
 | 
									    struct netdev_queue *txq, int *ret);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -376,7 +376,7 @@ enum {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	IFLA_GSO_IPV4_MAX_SIZE,
 | 
						IFLA_GSO_IPV4_MAX_SIZE,
 | 
				
			||||||
	IFLA_GRO_IPV4_MAX_SIZE,
 | 
						IFLA_GRO_IPV4_MAX_SIZE,
 | 
				
			||||||
 | 
						IFLA_DPLL_PIN,
 | 
				
			||||||
	__IFLA_MAX
 | 
						__IFLA_MAX
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9023,6 +9023,28 @@ bool netdev_port_same_parent_id(struct net_device *a, struct net_device *b)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(netdev_port_same_parent_id);
 | 
					EXPORT_SYMBOL(netdev_port_same_parent_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void netdev_dpll_pin_assign(struct net_device *dev, struct dpll_pin *dpll_pin)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if IS_ENABLED(CONFIG_DPLL)
 | 
				
			||||||
 | 
						rtnl_lock();
 | 
				
			||||||
 | 
						dev->dpll_pin = dpll_pin;
 | 
				
			||||||
 | 
						rtnl_unlock();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void netdev_dpll_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						WARN_ON(!dpll_pin);
 | 
				
			||||||
 | 
						netdev_dpll_pin_assign(dev, dpll_pin);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL(netdev_dpll_pin_set);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void netdev_dpll_pin_clear(struct net_device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						netdev_dpll_pin_assign(dev, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL(netdev_dpll_pin_clear);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 *	dev_change_proto_down - set carrier according to proto_down.
 | 
					 *	dev_change_proto_down - set carrier according to proto_down.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,6 +57,7 @@
 | 
				
			||||||
#if IS_ENABLED(CONFIG_IPV6)
 | 
					#if IS_ENABLED(CONFIG_IPV6)
 | 
				
			||||||
#include <net/addrconf.h>
 | 
					#include <net/addrconf.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#include <linux/dpll.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "dev.h"
 | 
					#include "dev.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1055,6 +1056,15 @@ static size_t rtnl_devlink_port_size(const struct net_device *dev)
 | 
				
			||||||
	return size;
 | 
						return size;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static size_t rtnl_dpll_pin_size(const struct net_device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						size_t size = nla_total_size(0); /* nest IFLA_DPLL_PIN */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size += dpll_msg_pin_handle_size(netdev_dpll_pin(dev));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static noinline size_t if_nlmsg_size(const struct net_device *dev,
 | 
					static noinline size_t if_nlmsg_size(const struct net_device *dev,
 | 
				
			||||||
				     u32 ext_filter_mask)
 | 
									     u32 ext_filter_mask)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1111,6 +1121,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
 | 
				
			||||||
	       + rtnl_prop_list_size(dev)
 | 
						       + rtnl_prop_list_size(dev)
 | 
				
			||||||
	       + nla_total_size(MAX_ADDR_LEN) /* IFLA_PERM_ADDRESS */
 | 
						       + nla_total_size(MAX_ADDR_LEN) /* IFLA_PERM_ADDRESS */
 | 
				
			||||||
	       + rtnl_devlink_port_size(dev)
 | 
						       + rtnl_devlink_port_size(dev)
 | 
				
			||||||
 | 
						       + rtnl_dpll_pin_size(dev)
 | 
				
			||||||
	       + 0;
 | 
						       + 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1774,6 +1785,28 @@ static int rtnl_fill_devlink_port(struct sk_buff *skb,
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int rtnl_fill_dpll_pin(struct sk_buff *skb,
 | 
				
			||||||
 | 
								      const struct net_device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nlattr *dpll_pin_nest;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dpll_pin_nest = nla_nest_start(skb, IFLA_DPLL_PIN);
 | 
				
			||||||
 | 
						if (!dpll_pin_nest)
 | 
				
			||||||
 | 
							return -EMSGSIZE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = dpll_msg_add_pin_handle(skb, netdev_dpll_pin(dev));
 | 
				
			||||||
 | 
						if (ret < 0)
 | 
				
			||||||
 | 
							goto nest_cancel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nla_nest_end(skb, dpll_pin_nest);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nest_cancel:
 | 
				
			||||||
 | 
						nla_nest_cancel(skb, dpll_pin_nest);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int rtnl_fill_ifinfo(struct sk_buff *skb,
 | 
					static int rtnl_fill_ifinfo(struct sk_buff *skb,
 | 
				
			||||||
			    struct net_device *dev, struct net *src_net,
 | 
								    struct net_device *dev, struct net *src_net,
 | 
				
			||||||
			    int type, u32 pid, u32 seq, u32 change,
 | 
								    int type, u32 pid, u32 seq, u32 change,
 | 
				
			||||||
| 
						 | 
					@ -1916,6 +1949,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
 | 
				
			||||||
	if (rtnl_fill_devlink_port(skb, dev))
 | 
						if (rtnl_fill_devlink_port(skb, dev))
 | 
				
			||||||
		goto nla_put_failure;
 | 
							goto nla_put_failure;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rtnl_fill_dpll_pin(skb, dev))
 | 
				
			||||||
 | 
							goto nla_put_failure;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nlmsg_end(skb, nlh);
 | 
						nlmsg_end(skb, nlh);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue