forked from mirrors/linux
		
	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; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * 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 | ||||
|  * @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 | ||||
|  * * -EMSGSIZE - no space in message to attach pin handle | ||||
|  */ | ||||
| static int | ||||
| dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin) | ||||
| int dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin) | ||||
| { | ||||
| 	if (!pin) | ||||
| 		return 0; | ||||
|  | @ -65,6 +76,7 @@ dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin) | |||
| 		return -EMSGSIZE; | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(dpll_msg_add_pin_handle); | ||||
| 
 | ||||
| static int | ||||
| 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; | ||||
| }; | ||||
| 
 | ||||
| #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 * | ||||
| 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_metadata_ops; | ||||
| struct xdp_md; | ||||
| /* DPLL specific */ | ||||
| struct dpll_pin; | ||||
| 
 | ||||
| typedef u32 xdp_features_t; | ||||
| 
 | ||||
|  | @ -2049,6 +2051,9 @@ enum netdev_ml_priv_type { | |||
|  *			SET_NETDEV_DEVLINK_PORT macro. This pointer is static | ||||
|  *			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 | ||||
|  *	moves out. | ||||
|  */ | ||||
|  | @ -2405,6 +2410,10 @@ struct net_device { | |||
| 	struct rtnl_hw_stats64	*offload_xstats_l3; | ||||
| 
 | ||||
| 	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) | ||||
| 
 | ||||
|  | @ -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, | ||||
| 			   struct netdev_phys_item_id *ppid, bool recurse); | ||||
| 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 *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, | ||||
| 				    struct netdev_queue *txq, int *ret); | ||||
|  |  | |||
|  | @ -376,7 +376,7 @@ enum { | |||
| 
 | ||||
| 	IFLA_GSO_IPV4_MAX_SIZE, | ||||
| 	IFLA_GRO_IPV4_MAX_SIZE, | ||||
| 
 | ||||
| 	IFLA_DPLL_PIN, | ||||
| 	__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); | ||||
| 
 | ||||
| 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. | ||||
|  * | ||||
|  |  | |||
|  | @ -57,6 +57,7 @@ | |||
| #if IS_ENABLED(CONFIG_IPV6) | ||||
| #include <net/addrconf.h> | ||||
| #endif | ||||
| #include <linux/dpll.h> | ||||
| 
 | ||||
| #include "dev.h" | ||||
| 
 | ||||
|  | @ -1055,6 +1056,15 @@ static size_t rtnl_devlink_port_size(const struct net_device *dev) | |||
| 	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, | ||||
| 				     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) | ||||
| 	       + nla_total_size(MAX_ADDR_LEN) /* IFLA_PERM_ADDRESS */ | ||||
| 	       + rtnl_devlink_port_size(dev) | ||||
| 	       + rtnl_dpll_pin_size(dev) | ||||
| 	       + 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -1774,6 +1785,28 @@ static int rtnl_fill_devlink_port(struct sk_buff *skb, | |||
| 	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, | ||||
| 			    struct net_device *dev, struct net *src_net, | ||||
| 			    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)) | ||||
| 		goto nla_put_failure; | ||||
| 
 | ||||
| 	if (rtnl_fill_dpll_pin(skb, dev)) | ||||
| 		goto nla_put_failure; | ||||
| 
 | ||||
| 	nlmsg_end(skb, nlh); | ||||
| 	return 0; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Jiri Pirko
						Jiri Pirko