Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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.fr
Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Vincent Mailhol and committed by
Marc Kleine-Budde
383f0993 5fe1be81

+43 -1
+30 -1
drivers/net/can/dev/netlink.c
··· 21 21 [IFLA_CAN_DATA_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) }, 22 22 [IFLA_CAN_TERMINATION] = { .type = NLA_U16 }, 23 23 [IFLA_CAN_TDC] = { .type = NLA_NESTED }, 24 + [IFLA_CAN_CTRLMODE_EXT] = { .type = NLA_NESTED }, 24 25 }; 25 26 26 27 static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = { ··· 384 383 return size; 385 384 } 386 385 386 + static size_t can_ctrlmode_ext_get_size(void) 387 + { 388 + return nla_total_size(0) + /* nest IFLA_CAN_CTRLMODE_EXT */ 389 + nla_total_size(sizeof(u32)); /* IFLA_CAN_CTRLMODE_SUPPORTED */ 390 + } 391 + 387 392 static size_t can_get_size(const struct net_device *dev) 388 393 { 389 394 struct can_priv *priv = netdev_priv(dev); ··· 422 415 priv->data_bitrate_const_cnt); 423 416 size += sizeof(priv->bitrate_max); /* IFLA_CAN_BITRATE_MAX */ 424 417 size += can_tdc_get_size(dev); /* IFLA_CAN_TDC */ 418 + size += can_ctrlmode_ext_get_size(); /* IFLA_CAN_CTRLMODE_EXT */ 425 419 426 420 return size; 427 421 } ··· 478 470 err_cancel: 479 471 nla_nest_cancel(skb, nest); 480 472 return -EMSGSIZE; 473 + } 474 + 475 + static int can_ctrlmode_ext_fill_info(struct sk_buff *skb, 476 + const struct can_priv *priv) 477 + { 478 + struct nlattr *nest; 479 + 480 + nest = nla_nest_start(skb, IFLA_CAN_CTRLMODE_EXT); 481 + if (!nest) 482 + return -EMSGSIZE; 483 + 484 + if (nla_put_u32(skb, IFLA_CAN_CTRLMODE_SUPPORTED, 485 + priv->ctrlmode_supported)) { 486 + nla_nest_cancel(skb, nest); 487 + return -EMSGSIZE; 488 + } 489 + 490 + nla_nest_end(skb, nest); 491 + return 0; 481 492 } 482 493 483 494 static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) ··· 558 531 sizeof(priv->bitrate_max), 559 532 &priv->bitrate_max)) || 560 533 561 - (can_tdc_fill_info(skb, dev)) 534 + can_tdc_fill_info(skb, dev) || 535 + 536 + can_ctrlmode_ext_fill_info(skb, priv) 562 537 ) 563 538 564 539 return -EMSGSIZE;
+13
include/uapi/linux/can/netlink.h
··· 137 137 IFLA_CAN_DATA_BITRATE_CONST, 138 138 IFLA_CAN_BITRATE_MAX, 139 139 IFLA_CAN_TDC, 140 + IFLA_CAN_CTRLMODE_EXT, 140 141 141 142 /* add new constants above here */ 142 143 __IFLA_CAN_MAX, ··· 165 164 /* add new constants above here */ 166 165 __IFLA_CAN_TDC, 167 166 IFLA_CAN_TDC_MAX = __IFLA_CAN_TDC - 1 167 + }; 168 + 169 + /* 170 + * IFLA_CAN_CTRLMODE_EXT nest: controller mode extended parameters 171 + */ 172 + enum { 173 + IFLA_CAN_CTRLMODE_UNSPEC, 174 + IFLA_CAN_CTRLMODE_SUPPORTED, /* u32 */ 175 + 176 + /* add new constants above here */ 177 + __IFLA_CAN_CTRLMODE, 178 + IFLA_CAN_CTRLMODE_MAX = __IFLA_CAN_CTRLMODE - 1 168 179 }; 169 180 170 181 /* u16 termination range: 1..65535 Ohms */