Commit 383f0993 authored by Vincent Mailhol's avatar Vincent Mailhol Committed by Marc Kleine-Budde

can: netlink: report the CAN controller mode supported flags

Currently, the CAN netlink interface provides no easy ways to check
the capabilities of a given controller. The only method from the
command line is to try each CAN_CTRLMODE_* individually to check
whether the netlink interface returns an -EOPNOTSUPP error or not
(alternatively, one may find it easier to directly check the source
code of the driver instead...)

This patch introduces a method for the user to check both the
supported and the static capabilities. The proposed method introduces
a new IFLA nest: IFLA_CAN_CTRLMODE_EXT which extends the current
IFLA_CAN_CTRLMODE. This is done to guaranty a full forward and
backward compatibility between the kernel and the user land
applications.

The IFLA_CAN_CTRLMODE_EXT nest contains one single entry:
IFLA_CAN_CTRLMODE_SUPPORTED. Because this entry is only used in one
direction: kernel to userland, no new struct nla_policy are
introduced.

Below table explains how IFLA_CAN_CTRLMODE_SUPPORTED (hereafter:
"supported") and can_ctrlmode::flags (hereafter: "flags") allow us to
identify both the supported and the static capabilities, when masked
with any of the CAN_CTRLMODE_* bit flags:

 supported &	flags &		Controller capabilities
 CAN_CTRLMODE_*	CAN_CTRLMODE_*
 -----------------------------------------------------------------------
 false		false		Feature not supported (always disabled)
 false		true		Static feature (always enabled)
 true		false		Feature supported but disabled
 true		true		Feature supported and enabled

Link: https://lore.kernel.org/all/20211213160226.56219-5-mailhol.vincent@wanadoo.frSigned-off-by: default avatarVincent Mailhol <mailhol.vincent@wanadoo.fr>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 5fe1be81
...@@ -21,6 +21,7 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = { ...@@ -21,6 +21,7 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
[IFLA_CAN_DATA_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) }, [IFLA_CAN_DATA_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) },
[IFLA_CAN_TERMINATION] = { .type = NLA_U16 }, [IFLA_CAN_TERMINATION] = { .type = NLA_U16 },
[IFLA_CAN_TDC] = { .type = NLA_NESTED }, [IFLA_CAN_TDC] = { .type = NLA_NESTED },
[IFLA_CAN_CTRLMODE_EXT] = { .type = NLA_NESTED },
}; };
static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = { static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = {
...@@ -383,6 +384,12 @@ static size_t can_tdc_get_size(const struct net_device *dev) ...@@ -383,6 +384,12 @@ static size_t can_tdc_get_size(const struct net_device *dev)
return size; return size;
} }
static size_t can_ctrlmode_ext_get_size(void)
{
return nla_total_size(0) + /* nest IFLA_CAN_CTRLMODE_EXT */
nla_total_size(sizeof(u32)); /* IFLA_CAN_CTRLMODE_SUPPORTED */
}
static size_t can_get_size(const struct net_device *dev) static size_t can_get_size(const struct net_device *dev)
{ {
struct can_priv *priv = netdev_priv(dev); struct can_priv *priv = netdev_priv(dev);
...@@ -415,6 +422,7 @@ static size_t can_get_size(const struct net_device *dev) ...@@ -415,6 +422,7 @@ static size_t can_get_size(const struct net_device *dev)
priv->data_bitrate_const_cnt); priv->data_bitrate_const_cnt);
size += sizeof(priv->bitrate_max); /* IFLA_CAN_BITRATE_MAX */ size += sizeof(priv->bitrate_max); /* IFLA_CAN_BITRATE_MAX */
size += can_tdc_get_size(dev); /* IFLA_CAN_TDC */ size += can_tdc_get_size(dev); /* IFLA_CAN_TDC */
size += can_ctrlmode_ext_get_size(); /* IFLA_CAN_CTRLMODE_EXT */
return size; return size;
} }
...@@ -472,6 +480,25 @@ static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev) ...@@ -472,6 +480,25 @@ static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev)
return -EMSGSIZE; return -EMSGSIZE;
} }
static int can_ctrlmode_ext_fill_info(struct sk_buff *skb,
const struct can_priv *priv)
{
struct nlattr *nest;
nest = nla_nest_start(skb, IFLA_CAN_CTRLMODE_EXT);
if (!nest)
return -EMSGSIZE;
if (nla_put_u32(skb, IFLA_CAN_CTRLMODE_SUPPORTED,
priv->ctrlmode_supported)) {
nla_nest_cancel(skb, nest);
return -EMSGSIZE;
}
nla_nest_end(skb, nest);
return 0;
}
static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
{ {
struct can_priv *priv = netdev_priv(dev); struct can_priv *priv = netdev_priv(dev);
...@@ -531,7 +558,9 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) ...@@ -531,7 +558,9 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
sizeof(priv->bitrate_max), sizeof(priv->bitrate_max),
&priv->bitrate_max)) || &priv->bitrate_max)) ||
(can_tdc_fill_info(skb, dev)) can_tdc_fill_info(skb, dev) ||
can_ctrlmode_ext_fill_info(skb, priv)
) )
return -EMSGSIZE; return -EMSGSIZE;
......
...@@ -137,6 +137,7 @@ enum { ...@@ -137,6 +137,7 @@ enum {
IFLA_CAN_DATA_BITRATE_CONST, IFLA_CAN_DATA_BITRATE_CONST,
IFLA_CAN_BITRATE_MAX, IFLA_CAN_BITRATE_MAX,
IFLA_CAN_TDC, IFLA_CAN_TDC,
IFLA_CAN_CTRLMODE_EXT,
/* add new constants above here */ /* add new constants above here */
__IFLA_CAN_MAX, __IFLA_CAN_MAX,
...@@ -166,6 +167,18 @@ enum { ...@@ -166,6 +167,18 @@ enum {
IFLA_CAN_TDC_MAX = __IFLA_CAN_TDC - 1 IFLA_CAN_TDC_MAX = __IFLA_CAN_TDC - 1
}; };
/*
* IFLA_CAN_CTRLMODE_EXT nest: controller mode extended parameters
*/
enum {
IFLA_CAN_CTRLMODE_UNSPEC,
IFLA_CAN_CTRLMODE_SUPPORTED, /* u32 */
/* add new constants above here */
__IFLA_CAN_CTRLMODE,
IFLA_CAN_CTRLMODE_MAX = __IFLA_CAN_CTRLMODE - 1
};
/* u16 termination range: 1..65535 Ohms */ /* u16 termination range: 1..65535 Ohms */
#define CAN_TERMINATION_DISABLED 0 #define CAN_TERMINATION_DISABLED 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment