Skip to content

Commit

Permalink
netdev: expose DPLL pin handle for netdevice
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jiri Pirko authored and David S. Miller committed Sep 17, 2023
1 parent 9d71b54 commit 5f18426
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 3 deletions.
16 changes: 14 additions & 2 deletions drivers/dpll/dpll_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -56,15 +68,15 @@ 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;
if (nla_put_u32(msg, DPLL_A_PIN_ID, pin->id))
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,
Expand Down
15 changes: 15 additions & 0 deletions include/linux/dpll.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
21 changes: 21 additions & 0 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion include/uapi/linux/if_link.h
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ enum {

IFLA_GSO_IPV4_MAX_SIZE,
IFLA_GRO_IPV4_MAX_SIZE,

IFLA_DPLL_PIN,
__IFLA_MAX
};

Expand Down
22 changes: 22 additions & 0 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
36 changes: 36 additions & 0 deletions net/core/rtnetlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#if IS_ENABLED(CONFIG_IPV6)
#include <net/addrconf.h>
#endif
#include <linux/dpll.h>

#include "dev.h"

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit 5f18426

Please sign in to comment.