Message ID | 20230720091903.297066-8-vadim.fedorenko@linux.dev (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Create common DPLL configuration API | expand |
On 20/07/2023 10:18, Vadim Fedorenko wrote: > From: Jiri Pirko <jiri@nvidia.com> > > 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> > --- > RFC v9->v0: > - rearrange function definition according to usage > v8->v9: > - net_device->dpll_pin is only valid if IS_ENABLED(CONFIG_DPLL) fix the > code in net/core/rtnetlink.c to respect that. > - move dpll_msg_add_pin_handle to "dpll: netlink" patch + export the > function with this patch > > drivers/dpll/dpll_netlink.c | 19 ++++++++++++++++--- > include/linux/dpll.h | 20 ++++++++++++++++++++ > include/linux/netdevice.h | 20 ++++++++++++++++++++ > include/uapi/linux/if_link.h | 2 ++ > net/core/dev.c | 22 ++++++++++++++++++++++ > net/core/rtnetlink.c | 35 +++++++++++++++++++++++++++++++++++ > 6 files changed, 115 insertions(+), 3 deletions(-) > > diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c > index c44dda78737d..e4a9bd767b92 100644 > --- a/drivers/dpll/dpll_netlink.c > +++ b/drivers/dpll/dpll_netlink.c > @@ -37,6 +37,18 @@ dpll_msg_add_dev_handle(struct sk_buff *msg, struct dpll_device *dpll) > 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 > @@ -54,6 +66,7 @@ int 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); Jiri, could you please remind me what is the reason to export this function? Because I cannot any usage of this function in drivers. [....]
On 01/08/2023 14:23, Vadim Fedorenko wrote: > On 20/07/2023 10:18, Vadim Fedorenko wrote: >> From: Jiri Pirko <jiri@nvidia.com> >> >> 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> >> --- >> RFC v9->v0: >> - rearrange function definition according to usage >> v8->v9: >> - net_device->dpll_pin is only valid if IS_ENABLED(CONFIG_DPLL) fix the >> code in net/core/rtnetlink.c to respect that. >> - move dpll_msg_add_pin_handle to "dpll: netlink" patch + export the >> function with this patch >> >> drivers/dpll/dpll_netlink.c | 19 ++++++++++++++++--- >> include/linux/dpll.h | 20 ++++++++++++++++++++ >> include/linux/netdevice.h | 20 ++++++++++++++++++++ >> include/uapi/linux/if_link.h | 2 ++ >> net/core/dev.c | 22 ++++++++++++++++++++++ >> net/core/rtnetlink.c | 35 +++++++++++++++++++++++++++++++++++ >> 6 files changed, 115 insertions(+), 3 deletions(-) >> >> diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c >> index c44dda78737d..e4a9bd767b92 100644 >> --- a/drivers/dpll/dpll_netlink.c >> +++ b/drivers/dpll/dpll_netlink.c >> @@ -37,6 +37,18 @@ dpll_msg_add_dev_handle(struct sk_buff *msg, struct >> dpll_device *dpll) >> 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 >> @@ -54,6 +66,7 @@ int 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); > > Jiri, could you please remind me what is the reason to export this > function? Because I cannot > any usage of this function in drivers. > Ah, found it, sorry for the noise. > > [....]
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c index c44dda78737d..e4a9bd767b92 100644 --- a/drivers/dpll/dpll_netlink.c +++ b/drivers/dpll/dpll_netlink.c @@ -37,6 +37,18 @@ dpll_msg_add_dev_handle(struct sk_buff *msg, struct dpll_device *dpll) 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 @@ -54,6 +66,7 @@ int 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, @@ -267,10 +280,9 @@ dpll_msg_add_pin_parents(struct sk_buff *msg, struct dpll_pin *pin, nest = nla_nest_start(msg, DPLL_A_PIN_PARENT_PIN); if (!nest) return -EMSGSIZE; - if (nla_put_u32(msg, DPLL_A_PIN_ID, ppin->id)) { - ret = -EMSGSIZE; + ret = dpll_msg_add_pin_handle(msg, ppin); + if (ret) goto nest_cancel; - } if (nla_put_u8(msg, DPLL_A_PIN_STATE, state)) { ret = -EMSGSIZE; goto nest_cancel; @@ -330,6 +342,7 @@ dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin, ref = dpll_xa_ref_dpll_first(&pin->dpll_refs); ASSERT_NOT_NULL(ref); + ret = dpll_msg_add_pin_handle(msg, pin); if (ret) return ret; diff --git a/include/linux/dpll.h b/include/linux/dpll.h index a96fddbc5279..16470f508487 100644 --- a/include/linux/dpll.h +++ b/include/linux/dpll.h @@ -104,6 +104,26 @@ 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); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index b828c7a75be2..a4865c131e40 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -34,6 +34,7 @@ #include <linux/rculist.h> #include <linux/workqueue.h> #include <linux/dynamic_queue_limits.h> +#include <linux/dpll.h> #include <net/net_namespace.h> #ifdef CONFIG_DCB @@ -2058,6 +2059,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. */ @@ -2414,6 +2418,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) @@ -3961,6 +3969,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); diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 0f6a0fe09bdb..be03c8292cd7 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -377,6 +377,8 @@ enum { IFLA_GSO_IPV4_MAX_SIZE, IFLA_GRO_IPV4_MAX_SIZE, + IFLA_DPLL_PIN, + __IFLA_MAX }; diff --git a/net/core/dev.c b/net/core/dev.c index d6e1b786c5c5..ad4f12fed4a7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -8952,6 +8952,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. * diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 70838d7e5b32..7d651dcb49fd 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1055,6 +1055,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 +1120,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 +1784,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 +1948,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;