* [PATCH 0/7] iplink_can: add CAN XL support
@ 2025-11-29 15:29 Vincent Mailhol
2025-11-29 15:29 ` [PATCH 1/7] iplink_can: print_usage: fix the text indentation Vincent Mailhol
` (7 more replies)
0 siblings, 8 replies; 15+ messages in thread
From: Vincent Mailhol @ 2025-11-29 15:29 UTC (permalink / raw)
To: netdev, Stephen Hemminger, Marc Kleine-Budde, Oliver Hartkopp,
David Ahern
Cc: linux-kernel, linux-can, Vincent Mailhol
Support for CAN XL was added to the kernel in [1]. This series is the
iproute2 counterpart.
Patches #1 to #3 are clean-ups. They refactor iplink_can's
print_usage()'s function.
Patches #4 to #7 add the CAN XL interface to iplink_can.
[1] commit 113aa9101a91 ("Merge patch series "can: netlink: add CAN XL support")
Link: https://git.kernel.org/netdev/net-next/c/113aa9101a91
Signed-off-by: Vincent Mailhol <mailhol@kernel.org>
---
Vincent Mailhol (7):
iplink_can: print_usage: fix the text indentation
iplink_can: print_usage: change unit for minimum time quanta to mtq
iplink_can: print_usage: describe the CAN bittiming units
iplink_can: add the "restricted" option
iplink_can: add initial CAN XL support
iplink_can: add CAN XL's "tms" option
iplink_can: add CAN XL's PWM interface
ip/iplink_can.c | 338 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 314 insertions(+), 24 deletions(-)
---
base-commit: 69942d75ccb7c0fa041d194ab4cb0879e969c828
change-id: 20250921-canxl-netlink-dd17ae310258
Best regards,
--
Vincent Mailhol <mailhol@kernel.org>
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH 1/7] iplink_can: print_usage: fix the text indentation 2025-11-29 15:29 [PATCH 0/7] iplink_can: add CAN XL support Vincent Mailhol @ 2025-11-29 15:29 ` Vincent Mailhol 2025-11-29 15:29 ` [PATCH 2/7] iplink_can: print_usage: change unit for minimum time quanta to mtq Vincent Mailhol ` (6 subsequent siblings) 7 siblings, 0 replies; 15+ messages in thread From: Vincent Mailhol @ 2025-11-29 15:29 UTC (permalink / raw) To: netdev, Stephen Hemminger, Marc Kleine-Budde, Oliver Hartkopp, David Ahern Cc: linux-kernel, linux-can, Vincent Mailhol The description of the BITRATE variable is not correctly aligned with the other ones. Put it on a new line with the same indentation as the other variables. This done, reindent everything to only one tabulation (was one tabulation and two spaces before). Before this patch...: $ ip link help can Usage: ip link set DEVICE type can (...) Where: BITRATE := { NUMBER in bps } SAMPLE-POINT := { 0.000..0.999 } TQ := { NUMBER in ns } PROP-SEG := { NUMBER in tq } PHASE-SEG1 := { NUMBER in tq } PHASE-SEG2 := { NUMBER in tq } SJW := { NUMBER in tq } TDCV := { NUMBER in tc } TDCO := { NUMBER in tc } TDCF := { NUMBER in tc } RESTART-MS := { 0 | NUMBER in ms } ...and after: $ ip link help can Usage: ip link set DEVICE type can (...) Where: BITRATE := { NUMBER in bps } SAMPLE-POINT := { 0.000..0.999 } TQ := { NUMBER in ns } PROP-SEG := { NUMBER in tq } PHASE-SEG1 := { NUMBER in tq } PHASE-SEG2 := { NUMBER in tq } SJW := { NUMBER in tq } TDCV := { NUMBER in tc } TDCO := { NUMBER in tc } TDCF := { NUMBER in tc } RESTART-MS := { 0 | NUMBER in ms } Signed-off-by: Vincent Mailhol <mailhol@kernel.org> --- ip/iplink_can.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/ip/iplink_can.c b/ip/iplink_can.c index 1afdf088..f3640fe0 100644 --- a/ip/iplink_can.c +++ b/ip/iplink_can.c @@ -48,17 +48,18 @@ static void print_usage(FILE *f) "\n" "\t[ termination { 0..65535 } ]\n" "\n" - "\tWhere: BITRATE := { NUMBER in bps }\n" - "\t SAMPLE-POINT := { 0.000..0.999 }\n" - "\t TQ := { NUMBER in ns }\n" - "\t PROP-SEG := { NUMBER in tq }\n" - "\t PHASE-SEG1 := { NUMBER in tq }\n" - "\t PHASE-SEG2 := { NUMBER in tq }\n" - "\t SJW := { NUMBER in tq }\n" - "\t TDCV := { NUMBER in tc }\n" - "\t TDCO := { NUMBER in tc }\n" - "\t TDCF := { NUMBER in tc }\n" - "\t RESTART-MS := { 0 | NUMBER in ms }\n" + "\tWhere:\n" + "\t BITRATE := { NUMBER in bps }\n" + "\t SAMPLE-POINT := { 0.000..0.999 }\n" + "\t TQ := { NUMBER in ns }\n" + "\t PROP-SEG := { NUMBER in tq }\n" + "\t PHASE-SEG1 := { NUMBER in tq }\n" + "\t PHASE-SEG2 := { NUMBER in tq }\n" + "\t SJW := { NUMBER in tq }\n" + "\t TDCV := { NUMBER in tc }\n" + "\t TDCO := { NUMBER in tc }\n" + "\t TDCF := { NUMBER in tc }\n" + "\t RESTART-MS := { 0 | NUMBER in ms }\n" ); } -- 2.51.2 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 2/7] iplink_can: print_usage: change unit for minimum time quanta to mtq 2025-11-29 15:29 [PATCH 0/7] iplink_can: add CAN XL support Vincent Mailhol 2025-11-29 15:29 ` [PATCH 1/7] iplink_can: print_usage: fix the text indentation Vincent Mailhol @ 2025-11-29 15:29 ` Vincent Mailhol 2025-11-29 15:29 ` [PATCH 3/7] iplink_can: print_usage: describe the CAN bittiming units Vincent Mailhol ` (5 subsequent siblings) 7 siblings, 0 replies; 15+ messages in thread From: Vincent Mailhol @ 2025-11-29 15:29 UTC (permalink / raw) To: netdev, Stephen Hemminger, Marc Kleine-Budde, Oliver Hartkopp, David Ahern Cc: linux-kernel, linux-can, Vincent Mailhol In the vast majority of the available CAN datasheets, the minimum time quanta is abbreviated as "mtq". Note that the ISO standard uses "tqmin" (with the "min" part as a subscript). One fact is that no one seems to be using "tc". I was actually the one who initially proposed to use "tc", but I can not recall anymore the reasoning behind that. Change the minimum time quanta unit from "tc" to "mtq" to follow what the majority of the industry does. Fixes: 0c263d7c36ff ("iplink_can: add new CAN FD bittiming parameters: Transmitter Delay Compensation (TDC)") Signed-off-by: Vincent Mailhol <mailhol@kernel.org> --- ip/iplink_can.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ip/iplink_can.c b/ip/iplink_can.c index f3640fe0..ee27659c 100644 --- a/ip/iplink_can.c +++ b/ip/iplink_can.c @@ -56,9 +56,9 @@ static void print_usage(FILE *f) "\t PHASE-SEG1 := { NUMBER in tq }\n" "\t PHASE-SEG2 := { NUMBER in tq }\n" "\t SJW := { NUMBER in tq }\n" - "\t TDCV := { NUMBER in tc }\n" - "\t TDCO := { NUMBER in tc }\n" - "\t TDCF := { NUMBER in tc }\n" + "\t TDCV := { NUMBER in mtq }\n" + "\t TDCO := { NUMBER in mtq }\n" + "\t TDCF := { NUMBER in mtq }\n" "\t RESTART-MS := { 0 | NUMBER in ms }\n" ); } -- 2.51.2 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 3/7] iplink_can: print_usage: describe the CAN bittiming units 2025-11-29 15:29 [PATCH 0/7] iplink_can: add CAN XL support Vincent Mailhol 2025-11-29 15:29 ` [PATCH 1/7] iplink_can: print_usage: fix the text indentation Vincent Mailhol 2025-11-29 15:29 ` [PATCH 2/7] iplink_can: print_usage: change unit for minimum time quanta to mtq Vincent Mailhol @ 2025-11-29 15:29 ` Vincent Mailhol 2025-11-29 15:29 ` [PATCH 4/7] iplink_can: add the "restricted" option Vincent Mailhol ` (4 subsequent siblings) 7 siblings, 0 replies; 15+ messages in thread From: Vincent Mailhol @ 2025-11-29 15:29 UTC (permalink / raw) To: netdev, Stephen Hemminger, Marc Kleine-Budde, Oliver Hartkopp, David Ahern Cc: linux-kernel, linux-can, Vincent Mailhol While the meaning of "bps" or "ns" may be relatively easy to understand, some of the CAN specific units such as "mtq" (minimum time quanta) may be harder to understand. Add a new paragraph to the help menu which describes all the different units used for the CAN bittiming parameters. Signed-off-by: Vincent Mailhol <mailhol@kernel.org> --- ip/iplink_can.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ip/iplink_can.c b/ip/iplink_can.c index ee27659c..a2f59764 100644 --- a/ip/iplink_can.c +++ b/ip/iplink_can.c @@ -60,6 +60,13 @@ static void print_usage(FILE *f) "\t TDCO := { NUMBER in mtq }\n" "\t TDCF := { NUMBER in mtq }\n" "\t RESTART-MS := { 0 | NUMBER in ms }\n" + "\n" + "\tUnits:\n" + "\t bps := bit per second\n" + "\t ms := milli second\n" + "\t mtq := minimum time quanta\n" + "\t ns := nano second\n" + "\t tq := time quanta\n" ); } -- 2.51.2 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 4/7] iplink_can: add the "restricted" option 2025-11-29 15:29 [PATCH 0/7] iplink_can: add CAN XL support Vincent Mailhol ` (2 preceding siblings ...) 2025-11-29 15:29 ` [PATCH 3/7] iplink_can: print_usage: describe the CAN bittiming units Vincent Mailhol @ 2025-11-29 15:29 ` Vincent Mailhol 2025-11-29 17:03 ` Stephen Hemminger 2025-11-29 15:29 ` [PATCH 5/7] iplink_can: add initial CAN XL support Vincent Mailhol ` (3 subsequent siblings) 7 siblings, 1 reply; 15+ messages in thread From: Vincent Mailhol @ 2025-11-29 15:29 UTC (permalink / raw) To: netdev, Stephen Hemminger, Marc Kleine-Budde, Oliver Hartkopp, David Ahern Cc: linux-kernel, linux-can, Vincent Mailhol This is the iproute2 counterpart of Linux kernel's commit 60f511f443e5 ("can: netlink: add CAN_CTRLMODE_RESTRICTED"). ISO 11898-1:2024 adds a new restricted operation mode. This mode is added as a mandatory feature for nodes which support CAN XL and is retrofitted as optional for legacy nodes (i.e. the ones which only support Classical CAN and CAN FD). The restricted operation mode is nearly the same as the listen only mode: the node can not send data frames or remote frames and can not send dominant bits if an error occurs. The only exception is that the node shall still send the acknowledgment bit. Add the "restricted" option to iplink_can which controls the CAN_CTRLMODE_RESTRICTED flag of the netlink interface. Signed-off-by: Vincent Mailhol <mailhol@kernel.org> --- ip/iplink_can.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ip/iplink_can.c b/ip/iplink_can.c index a2f59764..aeae6185 100644 --- a/ip/iplink_can.c +++ b/ip/iplink_can.c @@ -42,6 +42,7 @@ static void print_usage(FILE *f) "\t[ presume-ack { on | off } ]\n" "\t[ cc-len8-dlc { on | off } ]\n" "\t[ tdc-mode { auto | manual | off } ]\n" + "\t[ restricted { on | off } ]\n" "\n" "\t[ restart-ms TIME-MS ]\n" "\t[ restart ]\n" @@ -116,6 +117,7 @@ static void print_ctrlmode(enum output_type t, __u32 flags, const char *key) print_flag(t, &flags, CAN_CTRLMODE_CC_LEN8_DLC, "CC-LEN8-DLC"); print_flag(t, &flags, CAN_CTRLMODE_TDC_AUTO, "TDC-AUTO"); print_flag(t, &flags, CAN_CTRLMODE_TDC_MANUAL, "TDC-MANUAL"); + print_flag(t, &flags, CAN_CTRLMODE_RESTRICTED, "RESTRICTED"); if (flags) print_hex(t, NULL, "%x", flags); @@ -257,6 +259,9 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, invarg("\"tdc-mode\" must be either of \"auto\", \"manual\" or \"off\"", *argv); } + } else if (matches(*argv, "restricted") == 0) { + NEXT_ARG(); + set_ctrlmode("restricted", *argv, &cm, CAN_CTRLMODE_RESTRICTED); } else if (matches(*argv, "restart") == 0) { __u32 val = 1; -- 2.51.2 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 4/7] iplink_can: add the "restricted" option 2025-11-29 15:29 ` [PATCH 4/7] iplink_can: add the "restricted" option Vincent Mailhol @ 2025-11-29 17:03 ` Stephen Hemminger 0 siblings, 0 replies; 15+ messages in thread From: Stephen Hemminger @ 2025-11-29 17:03 UTC (permalink / raw) To: Vincent Mailhol Cc: netdev, Marc Kleine-Budde, Oliver Hartkopp, David Ahern, linux-kernel, linux-can On Sat, 29 Nov 2025 16:29:09 +0100 Vincent Mailhol <mailhol@kernel.org> wrote: > @@ -257,6 +259,9 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, > invarg("\"tdc-mode\" must be either of \"auto\", \"manual\" or \"off\"", > *argv); > } > + } else if (matches(*argv, "restricted") == 0) { > + NEXT_ARG(); > + set_ctrlmode("restricted", *argv, &cm, CAN_CTRLMODE_RESTRICTED); > } else if (matches(*argv, "restart") == 0) { > __u32 val = 1; Good example of iproute2 has banned use of matches. Because usage like the (think of what happens when user was previously using 'r') ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 5/7] iplink_can: add initial CAN XL support 2025-11-29 15:29 [PATCH 0/7] iplink_can: add CAN XL support Vincent Mailhol ` (3 preceding siblings ...) 2025-11-29 15:29 ` [PATCH 4/7] iplink_can: add the "restricted" option Vincent Mailhol @ 2025-11-29 15:29 ` Vincent Mailhol 2025-11-29 17:04 ` Stephen Hemminger 2025-11-29 15:29 ` [PATCH 6/7] iplink_can: add CAN XL's "tms" option Vincent Mailhol ` (2 subsequent siblings) 7 siblings, 1 reply; 15+ messages in thread From: Vincent Mailhol @ 2025-11-29 15:29 UTC (permalink / raw) To: netdev, Stephen Hemminger, Marc Kleine-Budde, Oliver Hartkopp, David Ahern Cc: linux-kernel, linux-can, Vincent Mailhol This is the iproute2 counterpart of Linux kernel's commit e63281614747 ("can: netlink: add initial CAN XL support"). CAN XL uses bittiming parameters different from Classical CAN and CAN FD. Thus, all the data bittiming parameters, including TDC, need to be duplicated for CAN XL. Add the "xl" option to iplink_can which controls the CAN_CTRLMODE_XL flag of the netlink interface. Then add the "xbitrate", "xsample-point", "xtq", "xprop-seg", "xphase-seg1", "xphase-seg2", "xsjw", "xtdcv", "xtdco", "xtdcf" and "xtdc-mode" which are all sub options of "xl". Add the logic to query and print all those values. Update print_usage() accordingly. All these options behave similarly to their CAN FD equivalent. The new options which are specific to CAN XL (i.e. not inherited from CAN FD) will be added in a subsequent change. Example using the dummy_can driver: # modprobe dummy_can # ip link set can0 type can bitrate 500000 fd on dbitrate 2000000 xl on xbitrate 8000000 $ ip --details link show can0 5: can0: <NOARP> mtu 2060 qdisc noop state DOWN mode DEFAULT group default qlen 10 link/can promiscuity 0 allmulti 0 minmtu 76 maxmtu 2060 can <FD,TDC-AUTO,XL,XL-TDC-AUTO> state STOPPED restart-ms 0 bitrate 500000 sample-point 0.875 tq 12 prop-seg 69 phase-seg1 70 phase-seg2 20 sjw 10 brp 2 dummy_can CC: tseg1 2..256 tseg2 2..128 sjw 1..128 brp 1..512 brp_inc 1 dbitrate 2000000 dsample-point 0.750 dtq 6 dprop-seg 29 dphase-seg1 30 dphase-seg2 20 dsjw 10 dbrp 1 tdco 60 tdcf 0 dummy_can FD: dtseg1 2..256 dtseg2 2..128 dsjw 1..128 dbrp 1..512 dbrp_inc 1 tdco 0..127 tdcf 0..127 xbitrate 8000000 xsample-point 0.750 xtq 6 xprop-seg 7 xphase-seg1 7 xphase-seg2 5 xsjw 2 xbrp 1 xtdco 15 xtdcf 0 dummy_can XL: xtseg1 2..256 xtseg2 2..128 xsjw 1..128 xbrp 1..512 xbrp_inc 1 xtdco 0..127 xtdcf 0..127 clock 160000000 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 tso_max_size 65536 tso_max_segs 65535 gro_max_size 65536 gso_ipv4_max_size 65536 gro_ipv4_max_size 65536 Signed-off-by: Vincent Mailhol <mailhol@kernel.org> --- ip/iplink_can.c | 208 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 195 insertions(+), 13 deletions(-) diff --git a/ip/iplink_can.c b/ip/iplink_can.c index aeae6185..24f59aad 100644 --- a/ip/iplink_can.c +++ b/ip/iplink_can.c @@ -32,6 +32,10 @@ static void print_usage(FILE *f) "\t[ dtq TQ dprop-seg PROP_SEG dphase-seg1 PHASE-SEG1\n \t dphase-seg2 PHASE-SEG2 [ dsjw SJW ] ]\n" "\t[ tdcv TDCV tdco TDCO tdcf TDCF ]\n" "\n" + "\t[ xbitrate BITRATE [ xsample-point SAMPLE-POINT] ] |\n" + "\t[ xtq TQ xprop-seg PROP_SEG xphase-seg1 PHASE-SEG1\n \t xphase-seg2 PHASE-SEG2 [ xsjw SJW ] ]\n" + "\t[ xtdcv TDCV xtdco TDCO xtdcf TDCF ]\n" + "\n" "\t[ loopback { on | off } ]\n" "\t[ listen-only { on | off } ]\n" "\t[ triple-sampling { on | off } ]\n" @@ -43,6 +47,8 @@ static void print_usage(FILE *f) "\t[ cc-len8-dlc { on | off } ]\n" "\t[ tdc-mode { auto | manual | off } ]\n" "\t[ restricted { on | off } ]\n" + "\t[ xl { on | off } ]\n" + "\t[ xtdc-mode { auto | manual | off } ]\n" "\n" "\t[ restart-ms TIME-MS ]\n" "\t[ restart ]\n" @@ -118,6 +124,9 @@ static void print_ctrlmode(enum output_type t, __u32 flags, const char *key) print_flag(t, &flags, CAN_CTRLMODE_TDC_AUTO, "TDC-AUTO"); print_flag(t, &flags, CAN_CTRLMODE_TDC_MANUAL, "TDC-MANUAL"); print_flag(t, &flags, CAN_CTRLMODE_RESTRICTED, "RESTRICTED"); + print_flag(t, &flags, CAN_CTRLMODE_XL, "XL"); + print_flag(t, &flags, CAN_CTRLMODE_XL_TDC_AUTO, "XL-TDC-AUTO"); + print_flag(t, &flags, CAN_CTRLMODE_XL_TDC_MANUAL, "XL-TDC-MANUAL"); if (flags) print_hex(t, NULL, "%x", flags); @@ -128,9 +137,10 @@ static void print_ctrlmode(enum output_type t, __u32 flags, const char *key) static int can_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { - struct can_bittiming bt = {}, fd_dbt = {}; + struct can_bittiming bt = {}, fd_dbt = {}, xl_dbt = {}; struct can_ctrlmode cm = { 0 }; struct can_tdc fd = { .tdcv = -1, .tdco = -1, .tdcf = -1 }; + struct can_tdc xl = { .tdcv = -1, .tdco = -1, .tdcf = -1 }; while (argc > 0) { if (matches(*argv, "bitrate") == 0) { @@ -208,6 +218,52 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, NEXT_ARG(); if (get_u32(&fd.tdcf, *argv, 0)) invarg("invalid \"tdcf\" value", *argv); + } else if (matches(*argv, "xl") == 0) { + NEXT_ARG(); + set_ctrlmode("xl", *argv, &cm, CAN_CTRLMODE_XL); + } else if (matches(*argv, "xbitrate") == 0) { + NEXT_ARG(); + if (get_u32(&xl_dbt.bitrate, *argv, 0)) + invarg("invalid \"xbitrate\" value", *argv); + } else if (matches(*argv, "xsample-point") == 0) { + float sp; + + NEXT_ARG(); + if (get_float(&sp, *argv)) + invarg("invalid \"xsample-point\" value", *argv); + xl_dbt.sample_point = (__u32)(sp * 1000); + } else if (matches(*argv, "xtq") == 0) { + NEXT_ARG(); + if (get_u32(&xl_dbt.tq, *argv, 0)) + invarg("invalid \"xtq\" value", *argv); + } else if (matches(*argv, "xprop-seg") == 0) { + NEXT_ARG(); + if (get_u32(&xl_dbt.prop_seg, *argv, 0)) + invarg("invalid \"xprop-seg\" value", *argv); + } else if (matches(*argv, "xphase-seg1") == 0) { + NEXT_ARG(); + if (get_u32(&xl_dbt.phase_seg1, *argv, 0)) + invarg("invalid \"xphase-seg1\" value", *argv); + } else if (matches(*argv, "xphase-seg2") == 0) { + NEXT_ARG(); + if (get_u32(&xl_dbt.phase_seg2, *argv, 0)) + invarg("invalid \"xphase-seg2\" value", *argv); + } else if (matches(*argv, "xsjw") == 0) { + NEXT_ARG(); + if (get_u32(&xl_dbt.sjw, *argv, 0)) + invarg("invalid \"xsjw\" value", *argv); + } else if (matches(*argv, "xtdcv") == 0) { + NEXT_ARG(); + if (get_u32(&xl.tdcv, *argv, 0)) + invarg("invalid \"xtdcv\" value", *argv); + } else if (matches(*argv, "xtdco") == 0) { + NEXT_ARG(); + if (get_u32(&xl.tdco, *argv, 0)) + invarg("invalid \"xtdco\" value", *argv); + } else if (matches(*argv, "xtdcf") == 0) { + NEXT_ARG(); + if (get_u32(&xl.tdcf, *argv, 0)) + invarg("invalid \"xtdcf\" value", *argv); } else if (matches(*argv, "loopback") == 0) { NEXT_ARG(); set_ctrlmode("loopback", *argv, &cm, @@ -262,6 +318,21 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, } else if (matches(*argv, "restricted") == 0) { NEXT_ARG(); set_ctrlmode("restricted", *argv, &cm, CAN_CTRLMODE_RESTRICTED); + } else if (matches(*argv, "xtdc-mode") == 0) { + NEXT_ARG(); + if (strcmp(*argv, "auto") == 0) { + cm.flags |= CAN_CTRLMODE_XL_TDC_AUTO; + cm.mask |= CAN_CTRLMODE_XL_TDC_AUTO; + } else if (strcmp(*argv, "manual") == 0) { + cm.flags |= CAN_CTRLMODE_XL_TDC_MANUAL; + cm.mask |= CAN_CTRLMODE_XL_TDC_MANUAL; + } else if (strcmp(*argv, "off") == 0) { + cm.mask |= CAN_CTRLMODE_XL_TDC_AUTO | + CAN_CTRLMODE_XL_TDC_MANUAL; + } else { + invarg("\"xtdc-mode\" must be either of \"auto\", \"manual\" or \"off\"", + *argv); + } } else if (matches(*argv, "restart") == 0) { __u32 val = 1; @@ -296,6 +367,8 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, addattr_l(n, 1024, IFLA_CAN_BITTIMING, &bt, sizeof(bt)); if (fd_dbt.bitrate || fd_dbt.tq) addattr_l(n, 1024, IFLA_CAN_DATA_BITTIMING, &fd_dbt, sizeof(fd_dbt)); + if (xl_dbt.bitrate || xl_dbt.tq) + addattr_l(n, 1024, IFLA_CAN_XL_DATA_BITTIMING, &xl_dbt, sizeof(xl_dbt)); if (cm.mask) addattr_l(n, 1024, IFLA_CAN_CTRLMODE, &cm, sizeof(cm)); @@ -311,6 +384,18 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, addattr32(n, 1024, IFLA_CAN_TDC_TDCF, fd.tdcf); addattr_nest_end(n, tdc); } + if (xl.tdcv != -1 || xl.tdco != -1 || xl.tdcf != -1) { + struct rtattr *tdc = addattr_nest(n, 1024, + IFLA_CAN_XL_TDC | NLA_F_NESTED); + + if (xl.tdcv != -1) + addattr32(n, 1024, IFLA_CAN_TDC_TDCV, xl.tdcv); + if (xl.tdco != -1) + addattr32(n, 1024, IFLA_CAN_TDC_TDCO, xl.tdco); + if (xl.tdcf != -1) + addattr32(n, 1024, IFLA_CAN_TDC_TDCF, xl.tdcf); + addattr_nest_end(n, tdc); + } return 0; } @@ -341,58 +426,67 @@ can_print_timing_min_max(const char *json_attr, const char *fp_attr, close_json_object(); } -static void can_print_tdc_opt(struct rtattr *tdc_attr) +static void can_print_tdc_opt(struct rtattr *tdc_attr, bool is_xl) { struct rtattr *tb[IFLA_CAN_TDC_MAX + 1]; parse_rtattr_nested(tb, IFLA_CAN_TDC_MAX, tdc_attr); if (tb[IFLA_CAN_TDC_TDCV] || tb[IFLA_CAN_TDC_TDCO] || tb[IFLA_CAN_TDC_TDCF]) { - open_json_object("tdc"); + const char *tdc = is_xl ? "xtdc" : "tdc"; + + open_json_object(tdc); can_print_nl_indent(); if (tb[IFLA_CAN_TDC_TDCV]) { + const char *tdcv_fmt = is_xl ? " xtdcv %u" : " tdcv %u"; __u32 *tdcv = RTA_DATA(tb[IFLA_CAN_TDC_TDCV]); - print_uint(PRINT_ANY, "tdcv", " tdcv %u", *tdcv); + print_uint(PRINT_ANY, "tdcv", tdcv_fmt, *tdcv); } if (tb[IFLA_CAN_TDC_TDCO]) { + const char *tdco_fmt = is_xl ? " xtdco %u" : " tdco %u"; __u32 *tdco = RTA_DATA(tb[IFLA_CAN_TDC_TDCO]); - print_uint(PRINT_ANY, "tdco", " tdco %u", *tdco); + print_uint(PRINT_ANY, "tdco", tdco_fmt, *tdco); } if (tb[IFLA_CAN_TDC_TDCF]) { + const char *tdcf_fmt = is_xl ? " xtdcf %u" : " tdcf %u"; __u32 *tdcf = RTA_DATA(tb[IFLA_CAN_TDC_TDCF]); - print_uint(PRINT_ANY, "tdcf", " tdcf %u", *tdcf); + print_uint(PRINT_ANY, "tdcf", tdcf_fmt, *tdcf); } close_json_object(); } } -static void can_print_tdc_const_opt(struct rtattr *tdc_attr) +static void can_print_tdc_const_opt(struct rtattr *tdc_attr, bool is_xl) { + const char *tdc = is_xl ? "xtdc" : "tdc"; struct rtattr *tb[IFLA_CAN_TDC_MAX + 1]; parse_rtattr_nested(tb, IFLA_CAN_TDC_MAX, tdc_attr); - open_json_object("tdc"); + open_json_object(tdc); can_print_nl_indent(); if (tb[IFLA_CAN_TDC_TDCV_MIN] && tb[IFLA_CAN_TDC_TDCV_MAX]) { __u32 *tdcv_min = RTA_DATA(tb[IFLA_CAN_TDC_TDCV_MIN]); __u32 *tdcv_max = RTA_DATA(tb[IFLA_CAN_TDC_TDCV_MAX]); + const char *tdcv = is_xl ? " xtdcv" : " tdcv"; - can_print_timing_min_max("tdcv", " tdcv", *tdcv_min, *tdcv_max); + can_print_timing_min_max("tdcv", tdcv, *tdcv_min, *tdcv_max); } if (tb[IFLA_CAN_TDC_TDCO_MIN] && tb[IFLA_CAN_TDC_TDCO_MAX]) { __u32 *tdco_min = RTA_DATA(tb[IFLA_CAN_TDC_TDCO_MIN]); __u32 *tdco_max = RTA_DATA(tb[IFLA_CAN_TDC_TDCO_MAX]); + const char *tdco = is_xl ? " xtdco" : " tdco"; - can_print_timing_min_max("tdco", " tdco", *tdco_min, *tdco_max); + can_print_timing_min_max("tdco", tdco, *tdco_min, *tdco_max); } if (tb[IFLA_CAN_TDC_TDCF_MIN] && tb[IFLA_CAN_TDC_TDCF_MAX]) { __u32 *tdcf_min = RTA_DATA(tb[IFLA_CAN_TDC_TDCF_MIN]); __u32 *tdcf_max = RTA_DATA(tb[IFLA_CAN_TDC_TDCF_MAX]); + const char *tdcf = is_xl ? " xtdcf" : " tdcf"; - can_print_timing_min_max("tdcf", " tdcf", *tdcf_min, *tdcf_max); + can_print_timing_min_max("tdcf", tdcf, *tdcf_min, *tdcf_max); } close_json_object(); } @@ -546,7 +640,7 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) print_uint(PRINT_ANY, "brp", " dbrp %u", dbt->brp); if (tb[IFLA_CAN_TDC]) - can_print_tdc_opt(tb[IFLA_CAN_TDC]); + can_print_tdc_opt(tb[IFLA_CAN_TDC], false); close_json_object(); } @@ -570,7 +664,7 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) print_uint(PRINT_ANY, "brp_inc", " dbrp_inc %u", dbtc->brp_inc); if (tb[IFLA_CAN_TDC]) - can_print_tdc_const_opt(tb[IFLA_CAN_TDC]); + can_print_tdc_const_opt(tb[IFLA_CAN_TDC], false); close_json_object(); } @@ -609,6 +703,94 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) close_json_array(PRINT_ANY, " ]"); } + /* data bittiming is irrelevant if fixed bitrate is defined */ + if (tb[IFLA_CAN_XL_DATA_BITTIMING] && + !tb[IFLA_CAN_XL_DATA_BITRATE_CONST]) { + struct can_bittiming *dbt = + RTA_DATA(tb[IFLA_CAN_XL_DATA_BITTIMING]); + char dsp[6]; + + open_json_object("xl_data_bittiming"); + can_print_nl_indent(); + print_uint(PRINT_ANY, "bitrate", " xbitrate %u", dbt->bitrate); + snprintf(dsp, sizeof(dsp), "%.3f", dbt->sample_point / 1000.); + print_string(PRINT_ANY, "sample_point", " xsample-point %s", + dsp); + can_print_nl_indent(); + print_uint(PRINT_ANY, "tq", " xtq %u", dbt->tq); + print_uint(PRINT_ANY, "prop_seg", " xprop-seg %u", + dbt->prop_seg); + print_uint(PRINT_ANY, "phase_seg1", " xphase-seg1 %u", + dbt->phase_seg1); + print_uint(PRINT_ANY, "phase_seg2", " xphase-seg2 %u", + dbt->phase_seg2); + print_uint(PRINT_ANY, "sjw", " xsjw %u", dbt->sjw); + print_uint(PRINT_ANY, "brp", " xbrp %u", dbt->brp); + + if (tb[IFLA_CAN_XL_TDC]) + can_print_tdc_opt(tb[IFLA_CAN_XL_TDC], true); + + close_json_object(); + } + + /* data bittiming const is irrelevant if fixed bitrate is defined */ + if (tb[IFLA_CAN_XL_DATA_BITTIMING_CONST] && + !tb[IFLA_CAN_XL_DATA_BITRATE_CONST]) { + struct can_bittiming_const *dbtc = + RTA_DATA(tb[IFLA_CAN_XL_DATA_BITTIMING_CONST]); + + open_json_object("xl_data_bittiming_const"); + can_print_nl_indent(); + print_string(PRINT_ANY, "name", " %s:", dbtc->name); + can_print_timing_min_max("tseg1", " xtseg1", + dbtc->tseg1_min, dbtc->tseg1_max); + can_print_timing_min_max("tseg2", " xtseg2", + dbtc->tseg2_min, dbtc->tseg2_max); + can_print_timing_min_max("sjw", " xsjw", 1, dbtc->sjw_max); + can_print_timing_min_max("brp", " xbrp", + dbtc->brp_min, dbtc->brp_max); + print_uint(PRINT_ANY, "brp_inc", " xbrp_inc %u", dbtc->brp_inc); + + if (tb[IFLA_CAN_XL_TDC]) + can_print_tdc_const_opt(tb[IFLA_CAN_XL_TDC], true); + + close_json_object(); + } + + if (tb[IFLA_CAN_XL_DATA_BITRATE_CONST]) { + __u32 *dbitrate_const = + RTA_DATA(tb[IFLA_CAN_XL_DATA_BITRATE_CONST]); + int dbitrate_cnt = + RTA_PAYLOAD(tb[IFLA_CAN_XL_DATA_BITRATE_CONST]) / + sizeof(*dbitrate_const); + int i; + __u32 dbitrate = 0; + + if (tb[IFLA_CAN_XL_DATA_BITTIMING]) { + struct can_bittiming *dbt = + RTA_DATA(tb[IFLA_CAN_XL_DATA_BITTIMING]); + dbitrate = dbt->bitrate; + } + + can_print_nl_indent(); + print_uint(PRINT_ANY, "xl_data_bittiming_bitrate", " xbitrate %u", + dbitrate); + can_print_nl_indent(); + open_json_array(PRINT_ANY, is_json_context() ? + "data_bitrate_const" : " ["); + for (i = 0; i < dbitrate_cnt; ++i) { + /* This will keep lines below 80 signs */ + if (!(i % 6) && i) { + can_print_nl_indent(); + print_string(PRINT_FP, NULL, "%s", " "); + } + print_uint(PRINT_ANY, NULL, + i < dbitrate_cnt - 1 ? "%8u, " : "%8u", + dbitrate_const[i]); + } + close_json_array(PRINT_ANY, " ]"); + } + if (tb[IFLA_CAN_TERMINATION_CONST] && tb[IFLA_CAN_TERMINATION]) { __u16 *trm = RTA_DATA(tb[IFLA_CAN_TERMINATION]); __u16 *trm_const = RTA_DATA(tb[IFLA_CAN_TERMINATION_CONST]); -- 2.51.2 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 5/7] iplink_can: add initial CAN XL support 2025-11-29 15:29 ` [PATCH 5/7] iplink_can: add initial CAN XL support Vincent Mailhol @ 2025-11-29 17:04 ` Stephen Hemminger 2025-11-29 23:13 ` Vincent Mailhol 0 siblings, 1 reply; 15+ messages in thread From: Stephen Hemminger @ 2025-11-29 17:04 UTC (permalink / raw) To: Vincent Mailhol Cc: netdev, Marc Kleine-Budde, Oliver Hartkopp, David Ahern, linux-kernel, linux-can On Sat, 29 Nov 2025 16:29:10 +0100 Vincent Mailhol <mailhol@kernel.org> wrote: > + } else if (matches(*argv, "xl") == 0) { > + NEXT_ARG(); > + set_ctrlmode("xl", *argv, &cm, CAN_CTRLMODE_XL); > + } else if (matches(*argv, "xbitrate") == 0) { > + NEXT_ARG(); > + if (get_u32(&xl_dbt.bitrate, *argv, 0)) > + invarg("invalid \"xbitrate\" value", *argv); > + } else if (matches(*argv, "xsample-point") == 0) { > + float sp; > + > + NEXT_ARG(); > + if (get_float(&sp, *argv)) > + invarg("invalid \"xsample-point\" value", *argv); > + xl_dbt.sample_point = (__u32)(sp * 1000); > + } else if (matches(*argv, "xtq") == 0) { > + NEXT_ARG(); > + if (get_u32(&xl_dbt.tq, *argv, 0)) > + invarg("invalid \"xtq\" value", *argv); > + } else if (matches(*argv, "xprop-seg") == 0) { > + NEXT_ARG(); > + if (get_u32(&xl_dbt.prop_seg, *argv, 0)) > + invarg("invalid \"xprop-seg\" value", *argv); > + } else if (matches(*argv, "xphase-seg1") == 0) { > + NEXT_ARG(); > + if (get_u32(&xl_dbt.phase_seg1, *argv, 0)) > + invarg("invalid \"xphase-seg1\" value", *argv); > + } else if (matches(*argv, "xphase-seg2") == 0) { > + NEXT_ARG(); > + if (get_u32(&xl_dbt.phase_seg2, *argv, 0)) > + invarg("invalid \"xphase-seg2\" value", *argv); > + } else if (matches(*argv, "xsjw") == 0) { > + NEXT_ARG(); > + if (get_u32(&xl_dbt.sjw, *argv, 0)) > + invarg("invalid \"xsjw\" value", *argv); > + } else if (matches(*argv, "xtdcv") == 0) { > + NEXT_ARG(); > + if (get_u32(&xl.tdcv, *argv, 0)) > + invarg("invalid \"xtdcv\" value", *argv); > + } else if (matches(*argv, "xtdco") == 0) { > + NEXT_ARG(); > + if (get_u32(&xl.tdco, *argv, 0)) > + invarg("invalid \"xtdco\" value", *argv); > + } else if (matches(*argv, "xtdcf") == 0) { > + NEXT_ARG(); > + if (get_u32(&xl.tdcf, *argv, 0)) > + invarg("invalid \"xtdcf\" value", *argv); > } else if (matches(*argv, "loopback") == 0) { > NEXT_ARG(); not accepting any new code with matches() ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 5/7] iplink_can: add initial CAN XL support 2025-11-29 17:04 ` Stephen Hemminger @ 2025-11-29 23:13 ` Vincent Mailhol 0 siblings, 0 replies; 15+ messages in thread From: Vincent Mailhol @ 2025-11-29 23:13 UTC (permalink / raw) To: Stephen Hemminger Cc: netdev, Marc Kleine-Budde, Oliver Hartkopp, David Ahern, linux-kernel, linux-can On 29/11/2025 at 18:04, Stephen Hemminger wrote: > On Sat, 29 Nov 2025 16:29:10 +0100 > Vincent Mailhol <mailhol@kernel.org> wrote: > >> + } else if (matches(*argv, "xl") == 0) { >> + NEXT_ARG(); >> + set_ctrlmode("xl", *argv, &cm, CAN_CTRLMODE_XL); >> + } else if (matches(*argv, "xbitrate") == 0) { >> + NEXT_ARG(); >> + if (get_u32(&xl_dbt.bitrate, *argv, 0)) >> + invarg("invalid \"xbitrate\" value", *argv); >> + } else if (matches(*argv, "xsample-point") == 0) { >> + float sp; >> + >> + NEXT_ARG(); >> + if (get_float(&sp, *argv)) >> + invarg("invalid \"xsample-point\" value", *argv); >> + xl_dbt.sample_point = (__u32)(sp * 1000); >> + } else if (matches(*argv, "xtq") == 0) { >> + NEXT_ARG(); >> + if (get_u32(&xl_dbt.tq, *argv, 0)) >> + invarg("invalid \"xtq\" value", *argv); >> + } else if (matches(*argv, "xprop-seg") == 0) { >> + NEXT_ARG(); >> + if (get_u32(&xl_dbt.prop_seg, *argv, 0)) >> + invarg("invalid \"xprop-seg\" value", *argv); >> + } else if (matches(*argv, "xphase-seg1") == 0) { >> + NEXT_ARG(); >> + if (get_u32(&xl_dbt.phase_seg1, *argv, 0)) >> + invarg("invalid \"xphase-seg1\" value", *argv); >> + } else if (matches(*argv, "xphase-seg2") == 0) { >> + NEXT_ARG(); >> + if (get_u32(&xl_dbt.phase_seg2, *argv, 0)) >> + invarg("invalid \"xphase-seg2\" value", *argv); >> + } else if (matches(*argv, "xsjw") == 0) { >> + NEXT_ARG(); >> + if (get_u32(&xl_dbt.sjw, *argv, 0)) >> + invarg("invalid \"xsjw\" value", *argv); >> + } else if (matches(*argv, "xtdcv") == 0) { >> + NEXT_ARG(); >> + if (get_u32(&xl.tdcv, *argv, 0)) >> + invarg("invalid \"xtdcv\" value", *argv); >> + } else if (matches(*argv, "xtdco") == 0) { >> + NEXT_ARG(); >> + if (get_u32(&xl.tdco, *argv, 0)) >> + invarg("invalid \"xtdco\" value", *argv); >> + } else if (matches(*argv, "xtdcf") == 0) { >> + NEXT_ARG(); >> + if (get_u32(&xl.tdcf, *argv, 0)) >> + invarg("invalid \"xtdcf\" value", *argv); >> } else if (matches(*argv, "loopback") == 0) { >> NEXT_ARG(); > > not accepting any new code with matches() Ack. I will do a s/matches/strcmp/g in the next version. For the old code, I assume that we should keep it as-is, otherwise that would be a breaking change. Yours sincerely, Vincent Mailhol ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 6/7] iplink_can: add CAN XL's "tms" option 2025-11-29 15:29 [PATCH 0/7] iplink_can: add CAN XL support Vincent Mailhol ` (4 preceding siblings ...) 2025-11-29 15:29 ` [PATCH 5/7] iplink_can: add initial CAN XL support Vincent Mailhol @ 2025-11-29 15:29 ` Vincent Mailhol 2025-11-29 17:21 ` Oliver Hartkopp 2025-11-29 15:29 ` [PATCH 7/7] iplink_can: add CAN XL's PWM interface Vincent Mailhol 2025-11-29 15:38 ` [PATCH 0/7] iplink_can: add CAN XL support Vincent Mailhol 7 siblings, 1 reply; 15+ messages in thread From: Vincent Mailhol @ 2025-11-29 15:29 UTC (permalink / raw) To: netdev, Stephen Hemminger, Marc Kleine-Budde, Oliver Hartkopp, David Ahern Cc: linux-kernel, linux-can, Vincent Mailhol This is the iproute2 counterpart of Linux kernel's commit 233134af2086 ("can: netlink: add CAN_CTRLMODE_XL_TMS flag"). The Transceiver Mode Switching (TMS) indicates whether the CAN XL controller shall use the PWM or NRZ encoding during the data phase. The term "transceiver mode switching" is used in both ISO 11898-1 and CiA 612-2 (although only the latter one uses the abbreviation TMS). We adopt the same naming convention here for consistency. Add the "tms" option to iplink_can which controls the CAN_CTRLMODE_XL_TMS flag of the CAN netlink interface. Signed-off-by: Vincent Mailhol <mailhol@kernel.org> --- ip/iplink_can.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ip/iplink_can.c b/ip/iplink_can.c index 24f59aad..3e7925e8 100644 --- a/ip/iplink_can.c +++ b/ip/iplink_can.c @@ -49,6 +49,7 @@ static void print_usage(FILE *f) "\t[ restricted { on | off } ]\n" "\t[ xl { on | off } ]\n" "\t[ xtdc-mode { auto | manual | off } ]\n" + "\t[ tms { on | off } ]\n" "\n" "\t[ restart-ms TIME-MS ]\n" "\t[ restart ]\n" @@ -127,6 +128,7 @@ static void print_ctrlmode(enum output_type t, __u32 flags, const char *key) print_flag(t, &flags, CAN_CTRLMODE_XL, "XL"); print_flag(t, &flags, CAN_CTRLMODE_XL_TDC_AUTO, "XL-TDC-AUTO"); print_flag(t, &flags, CAN_CTRLMODE_XL_TDC_MANUAL, "XL-TDC-MANUAL"); + print_flag(t, &flags, CAN_CTRLMODE_XL_TMS, "XL-TMS"); if (flags) print_hex(t, NULL, "%x", flags); @@ -333,6 +335,9 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, invarg("\"xtdc-mode\" must be either of \"auto\", \"manual\" or \"off\"", *argv); } + } else if (matches(*argv, "tms") == 0) { + NEXT_ARG(); + set_ctrlmode("tms", *argv, &cm, CAN_CTRLMODE_XL_TMS); } else if (matches(*argv, "restart") == 0) { __u32 val = 1; -- 2.51.2 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 6/7] iplink_can: add CAN XL's "tms" option 2025-11-29 15:29 ` [PATCH 6/7] iplink_can: add CAN XL's "tms" option Vincent Mailhol @ 2025-11-29 17:21 ` Oliver Hartkopp 2025-11-29 23:16 ` Vincent Mailhol 0 siblings, 1 reply; 15+ messages in thread From: Oliver Hartkopp @ 2025-11-29 17:21 UTC (permalink / raw) To: Vincent Mailhol, netdev, Stephen Hemminger, Marc Kleine-Budde, David Ahern Cc: linux-kernel, linux-can Hi Vincent, On 29.11.25 16:29, Vincent Mailhol wrote: > This is the iproute2 counterpart of Linux kernel's commit 233134af2086 > ("can: netlink: add CAN_CTRLMODE_XL_TMS flag"). > > The Transceiver Mode Switching (TMS) indicates whether the CAN XL > controller shall use the PWM or NRZ encoding during the data phase. > > The term "transceiver mode switching" is used in both ISO 11898-1 and CiA > 612-2 (although only the latter one uses the abbreviation TMS). We adopt > the same naming convention here for consistency. > > Add the "tms" option to iplink_can which controls the CAN_CTRLMODE_XL_TMS > flag of the CAN netlink interface. > > Signed-off-by: Vincent Mailhol <mailhol@kernel.org> > --- > ip/iplink_can.c | 5 +++++ > 1 file changed, 5 insertions(+) > > diff --git a/ip/iplink_can.c b/ip/iplink_can.c > index 24f59aad..3e7925e8 100644 > --- a/ip/iplink_can.c > +++ b/ip/iplink_can.c > @@ -49,6 +49,7 @@ static void print_usage(FILE *f) > "\t[ restricted { on | off } ]\n" > "\t[ xl { on | off } ]\n" > "\t[ xtdc-mode { auto | manual | off } ]\n" > + "\t[ tms { on | off } ]\n" > "\n" > "\t[ restart-ms TIME-MS ]\n" > "\t[ restart ]\n" > @@ -127,6 +128,7 @@ static void print_ctrlmode(enum output_type t, __u32 flags, const char *key) > print_flag(t, &flags, CAN_CTRLMODE_XL, "XL"); > print_flag(t, &flags, CAN_CTRLMODE_XL_TDC_AUTO, "XL-TDC-AUTO"); > print_flag(t, &flags, CAN_CTRLMODE_XL_TDC_MANUAL, "XL-TDC-MANUAL"); > + print_flag(t, &flags, CAN_CTRLMODE_XL_TMS, "XL-TMS"); print_flag(t, &flags, CAN_CTRLMODE_XL_TMS, "TMS"); That fits to the command line option and the messages inside the kernel now. Best regards, Oliver > > if (flags) > print_hex(t, NULL, "%x", flags); > @@ -333,6 +335,9 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, > invarg("\"xtdc-mode\" must be either of \"auto\", \"manual\" or \"off\"", > *argv); > } > + } else if (matches(*argv, "tms") == 0) { > + NEXT_ARG(); > + set_ctrlmode("tms", *argv, &cm, CAN_CTRLMODE_XL_TMS); > } else if (matches(*argv, "restart") == 0) { > __u32 val = 1; > > ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 6/7] iplink_can: add CAN XL's "tms" option 2025-11-29 17:21 ` Oliver Hartkopp @ 2025-11-29 23:16 ` Vincent Mailhol 0 siblings, 0 replies; 15+ messages in thread From: Vincent Mailhol @ 2025-11-29 23:16 UTC (permalink / raw) To: Oliver Hartkopp, netdev, Stephen Hemminger, Marc Kleine-Budde, David Ahern Cc: linux-kernel, linux-can Hi Oliver, On 29/11/2025 at 18:21, Oliver Hartkopp wrote: > Hi Vincent, > > On 29.11.25 16:29, Vincent Mailhol wrote: >> This is the iproute2 counterpart of Linux kernel's commit 233134af2086 >> ("can: netlink: add CAN_CTRLMODE_XL_TMS flag"). >> >> The Transceiver Mode Switching (TMS) indicates whether the CAN XL >> controller shall use the PWM or NRZ encoding during the data phase. >> >> The term "transceiver mode switching" is used in both ISO 11898-1 and CiA >> 612-2 (although only the latter one uses the abbreviation TMS). We adopt >> the same naming convention here for consistency. >> >> Add the "tms" option to iplink_can which controls the CAN_CTRLMODE_XL_TMS >> flag of the CAN netlink interface. >> >> Signed-off-by: Vincent Mailhol <mailhol@kernel.org> >> --- >> ip/iplink_can.c | 5 +++++ >> 1 file changed, 5 insertions(+) >> >> diff --git a/ip/iplink_can.c b/ip/iplink_can.c >> index 24f59aad..3e7925e8 100644 >> --- a/ip/iplink_can.c >> +++ b/ip/iplink_can.c >> @@ -49,6 +49,7 @@ static void print_usage(FILE *f) >> "\t[ restricted { on | off } ]\n" >> "\t[ xl { on | off } ]\n" >> "\t[ xtdc-mode { auto | manual | off } ]\n" >> + "\t[ tms { on | off } ]\n" >> "\n" >> "\t[ restart-ms TIME-MS ]\n" >> "\t[ restart ]\n" >> @@ -127,6 +128,7 @@ static void print_ctrlmode(enum output_type t, __u32 >> flags, const char *key) >> print_flag(t, &flags, CAN_CTRLMODE_XL, "XL"); >> print_flag(t, &flags, CAN_CTRLMODE_XL_TDC_AUTO, "XL-TDC-AUTO"); >> print_flag(t, &flags, CAN_CTRLMODE_XL_TDC_MANUAL, "XL-TDC-MANUAL"); >> + print_flag(t, &flags, CAN_CTRLMODE_XL_TMS, "XL-TMS"); > > print_flag(t, &flags, CAN_CTRLMODE_XL_TMS, "TMS"); > > That fits to the command line option and the messages inside the kernel now. OK. This will be addressed in v2 (including the updates on Patch #7 description). Yours sincerely, Vincent Mailhol ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 7/7] iplink_can: add CAN XL's PWM interface 2025-11-29 15:29 [PATCH 0/7] iplink_can: add CAN XL support Vincent Mailhol ` (5 preceding siblings ...) 2025-11-29 15:29 ` [PATCH 6/7] iplink_can: add CAN XL's "tms" option Vincent Mailhol @ 2025-11-29 15:29 ` Vincent Mailhol 2025-11-29 17:26 ` Oliver Hartkopp 2025-11-29 15:38 ` [PATCH 0/7] iplink_can: add CAN XL support Vincent Mailhol 7 siblings, 1 reply; 15+ messages in thread From: Vincent Mailhol @ 2025-11-29 15:29 UTC (permalink / raw) To: netdev, Stephen Hemminger, Marc Kleine-Budde, Oliver Hartkopp, David Ahern Cc: linux-kernel, linux-can, Vincent Mailhol This is the iproute2 counterpart of Linux kernel's commit 46552323fa67 ("can: netlink: add PWM netlink interface"). When the TMS is switched on, the node uses PWM (Pulse Width Modulation) during the data phase instead of the classic NRZ (Non Return to Zero) encoding. PWM is configured by three parameters: - PWMS: Pulse Width Modulation Short phase - PWML: Pulse Width Modulation Long phase - PWMO: Pulse Width Modulation Offset time For each of these parameters, the CAN netlink interface defines three IFLA symbols: - IFLA_CAN_PWM_PWM*_MIN: the minimum allowed value. - IFLA_CAN_PWM_PWM*_MAX: the maximum allowed value. - IFLA_CAN_PWM_PWM*: the runtime value. This results in a total of nine IFLA symbols which are all nested in a parent IFLA_CAN_XL_PWM symbol. Add the "pwms", "pwml" and "pwmo" options to iplink_can which controls the IFLA_CAN_PWM_PWM* runtime values. Add the logic to query and print all those IFLA values. Update print_usage() accordingly. Example using the dummy_can driver: # modprobe dummy_can # ip link set can0 type can bitrate 1000000 xl on xbitrate 20000000 tms on $ ip --details link show can0 5: can0: <NOARP> mtu 2060 qdisc noop state DOWN mode DEFAULT group default qlen 10 link/can promiscuity 0 allmulti 0 minmtu 76 maxmtu 2060 can <XL,XL-TMS> state STOPPED restart-ms 0 bitrate 1000000 sample-point 0.750 tq 6 prop-seg 59 phase-seg1 60 phase-seg2 40 sjw 20 brp 1 dummy_can CC: tseg1 2..256 tseg2 2..128 sjw 1..128 brp 1..512 brp_inc 1 dummy_can FD: dtseg1 2..256 dtseg2 2..128 dsjw 1..128 dbrp 1..512 dbrp_inc 1 tdco 0..127 tdcf 0..127 xbitrate 20000000 xsample-point 0.625 xtq 6 xprop-seg 2 xphase-seg1 2 xphase-seg2 3 xsjw 1 xbrp 1 pwms 2 pwml 6 pwmo 0 dummy_can XL: xtseg1 2..256 xtseg2 2..128 xsjw 1..128 xbrp 1..512 xbrp_inc 1 xtdco 0..127 xtdcf 0..127 pwms 1..8 pwml 2..24 pwmo 0..16 clock 160000000 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 tso_max_size 65536 tso_max_segs 65535 gro_max_size 65536 gso_ipv4_max_size 65536 gro_ipv4_max_size 65536 Signed-off-by: Vincent Mailhol <mailhol@kernel.org> --- ip/iplink_can.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/ip/iplink_can.c b/ip/iplink_can.c index 3e7925e8..d43dc9bb 100644 --- a/ip/iplink_can.c +++ b/ip/iplink_can.c @@ -34,7 +34,7 @@ static void print_usage(FILE *f) "\n" "\t[ xbitrate BITRATE [ xsample-point SAMPLE-POINT] ] |\n" "\t[ xtq TQ xprop-seg PROP_SEG xphase-seg1 PHASE-SEG1\n \t xphase-seg2 PHASE-SEG2 [ xsjw SJW ] ]\n" - "\t[ xtdcv TDCV xtdco TDCO xtdcf TDCF ]\n" + "\t[ xtdcv TDCV xtdco TDCO xtdcf TDCF pwms PWMS pwml PWML pwmo PWMO]\n" "\n" "\t[ loopback { on | off } ]\n" "\t[ listen-only { on | off } ]\n" @@ -67,6 +67,9 @@ static void print_usage(FILE *f) "\t TDCV := { NUMBER in mtq }\n" "\t TDCO := { NUMBER in mtq }\n" "\t TDCF := { NUMBER in mtq }\n" + "\t PWMS := { NUMBER in mtq }\n" + "\t PWML := { NUMBER in mtq }\n" + "\t PWMO := { NUMBER in mtq }\n" "\t RESTART-MS := { 0 | NUMBER in ms }\n" "\n" "\tUnits:\n" @@ -143,6 +146,7 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, struct can_ctrlmode cm = { 0 }; struct can_tdc fd = { .tdcv = -1, .tdco = -1, .tdcf = -1 }; struct can_tdc xl = { .tdcv = -1, .tdco = -1, .tdcf = -1 }; + __u32 pwms = -1, pwml = -1, pwmo = -1; while (argc > 0) { if (matches(*argv, "bitrate") == 0) { @@ -266,6 +270,18 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, NEXT_ARG(); if (get_u32(&xl.tdcf, *argv, 0)) invarg("invalid \"xtdcf\" value", *argv); + } else if (matches(*argv, "pwms") == 0) { + NEXT_ARG(); + if (get_u32(&pwms, *argv, 0)) + invarg("invalid \"pwms\" value", *argv); + } else if (matches(*argv, "pwml") == 0) { + NEXT_ARG(); + if (get_u32(&pwml, *argv, 0)) + invarg("invalid \"pwml\" value", *argv); + } else if (matches(*argv, "pwmo") == 0) { + NEXT_ARG(); + if (get_u32(&pwmo, *argv, 0)) + invarg("invalid \"pwmo\" value", *argv); } else if (matches(*argv, "loopback") == 0) { NEXT_ARG(); set_ctrlmode("loopback", *argv, &cm, @@ -401,6 +417,18 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, addattr32(n, 1024, IFLA_CAN_TDC_TDCF, xl.tdcf); addattr_nest_end(n, tdc); } + if (pwms != -1 || pwml != -1 || pwmo != -1) { + struct rtattr *pwm = addattr_nest(n, 1024, + IFLA_CAN_XL_PWM | NLA_F_NESTED); + + if (pwms != -1) + addattr32(n, 1024, IFLA_CAN_PWM_PWMS, pwms); + if (pwml != -1) + addattr32(n, 1024, IFLA_CAN_PWM_PWML, pwml); + if (pwmo != -1) + addattr32(n, 1024, IFLA_CAN_PWM_PWMO, pwmo); + addattr_nest_end(n, pwm); + } return 0; } @@ -496,6 +524,62 @@ static void can_print_tdc_const_opt(struct rtattr *tdc_attr, bool is_xl) close_json_object(); } +static void can_print_pwm_opt(struct rtattr *pwm_attr) +{ + struct rtattr *tb[IFLA_CAN_PWM_MAX + 1]; + + parse_rtattr_nested(tb, IFLA_CAN_PWM_MAX, pwm_attr); + if (tb[IFLA_CAN_PWM_PWMS] || tb[IFLA_CAN_PWM_PWML] || + tb[IFLA_CAN_PWM_PWMO]) { + open_json_object("pwm"); + can_print_nl_indent(); + if (tb[IFLA_CAN_PWM_PWMS]) { + __u32 *pwms = RTA_DATA(tb[IFLA_CAN_PWM_PWMS]); + + print_uint(PRINT_ANY, " pwms", " pwms %u", *pwms); + } + if (tb[IFLA_CAN_PWM_PWML]) { + __u32 *pwml = RTA_DATA(tb[IFLA_CAN_PWM_PWML]); + + print_uint(PRINT_ANY, " pwml", " pwml %u", *pwml); + } + if (tb[IFLA_CAN_PWM_PWMO]) { + __u32 *pwmo = RTA_DATA(tb[IFLA_CAN_PWM_PWMO]); + + print_uint(PRINT_ANY, " pwmo", " pwmo %u", *pwmo); + } + close_json_object(); + } +} + +static void can_print_pwm_const_opt(struct rtattr *pwm_attr) +{ + struct rtattr *tb[IFLA_CAN_PWM_MAX + 1]; + + parse_rtattr_nested(tb, IFLA_CAN_PWM_MAX, pwm_attr); + open_json_object("pwm"); + can_print_nl_indent(); + if (tb[IFLA_CAN_PWM_PWMS_MAX]) { + __u32 *pwms_min = RTA_DATA(tb[IFLA_CAN_PWM_PWMS_MIN]); + __u32 *pwms_max = RTA_DATA(tb[IFLA_CAN_PWM_PWMS_MAX]); + + can_print_timing_min_max("pwms", " pwms", *pwms_min, *pwms_max); + } + if (tb[IFLA_CAN_PWM_PWML_MAX]) { + __u32 *pwml_min = RTA_DATA(tb[IFLA_CAN_PWM_PWML_MIN]); + __u32 *pwml_max = RTA_DATA(tb[IFLA_CAN_PWM_PWML_MAX]); + + can_print_timing_min_max("pwml", " pwml", *pwml_min, *pwml_max); + } + if (tb[IFLA_CAN_PWM_PWMO_MAX]) { + __u32 *pwmo_min = RTA_DATA(tb[IFLA_CAN_PWM_PWMO_MIN]); + __u32 *pwmo_max = RTA_DATA(tb[IFLA_CAN_PWM_PWMO_MAX]); + + can_print_timing_min_max("pwmo", " pwmo", *pwmo_min, *pwmo_max); + } + close_json_object(); +} + static void can_print_ctrlmode_ext(struct rtattr *ctrlmode_ext_attr, __u32 cm_flags) { @@ -735,6 +819,9 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) if (tb[IFLA_CAN_XL_TDC]) can_print_tdc_opt(tb[IFLA_CAN_XL_TDC], true); + if (tb[IFLA_CAN_XL_PWM]) + can_print_pwm_opt(tb[IFLA_CAN_XL_PWM]); + close_json_object(); } @@ -759,6 +846,9 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) if (tb[IFLA_CAN_XL_TDC]) can_print_tdc_const_opt(tb[IFLA_CAN_XL_TDC], true); + if (tb[IFLA_CAN_XL_PWM]) + can_print_pwm_const_opt(tb[IFLA_CAN_XL_PWM]); + close_json_object(); } -- 2.51.2 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 7/7] iplink_can: add CAN XL's PWM interface 2025-11-29 15:29 ` [PATCH 7/7] iplink_can: add CAN XL's PWM interface Vincent Mailhol @ 2025-11-29 17:26 ` Oliver Hartkopp 0 siblings, 0 replies; 15+ messages in thread From: Oliver Hartkopp @ 2025-11-29 17:26 UTC (permalink / raw) To: Vincent Mailhol, netdev, Stephen Hemminger, Marc Kleine-Budde, David Ahern Cc: linux-kernel, linux-can On 29.11.25 16:29, Vincent Mailhol wrote: > This is the iproute2 counterpart of Linux kernel's commit 46552323fa67 > ("can: netlink: add PWM netlink interface"). > > When the TMS is switched on, the node uses PWM (Pulse Width Modulation) > during the data phase instead of the classic NRZ (Non Return to Zero) > encoding. > > PWM is configured by three parameters: > > - PWMS: Pulse Width Modulation Short phase > - PWML: Pulse Width Modulation Long phase > - PWMO: Pulse Width Modulation Offset time > > For each of these parameters, the CAN netlink interface defines three IFLA > symbols: > > - IFLA_CAN_PWM_PWM*_MIN: the minimum allowed value. > - IFLA_CAN_PWM_PWM*_MAX: the maximum allowed value. > - IFLA_CAN_PWM_PWM*: the runtime value. > > This results in a total of nine IFLA symbols which are all nested in a > parent IFLA_CAN_XL_PWM symbol. > > Add the "pwms", "pwml" and "pwmo" options to iplink_can which controls the > IFLA_CAN_PWM_PWM* runtime values. > > Add the logic to query and print all those IFLA values. Update > print_usage() accordingly. > > Example using the dummy_can driver: > > # modprobe dummy_can ^^ two spaces > # ip link set can0 type can bitrate 1000000 xl on xbitrate 20000000 tms on > $ ip --details link show can0 > 5: can0: <NOARP> mtu 2060 qdisc noop state DOWN mode DEFAULT group default qlen 10 > link/can promiscuity 0 allmulti 0 minmtu 76 maxmtu 2060 > can <XL,XL-TMS> state STOPPED restart-ms 0 <XL,TMS> Best regards, Oliver > bitrate 1000000 sample-point 0.750 > tq 6 prop-seg 59 phase-seg1 60 phase-seg2 40 sjw 20 brp 1 > dummy_can CC: tseg1 2..256 tseg2 2..128 sjw 1..128 brp 1..512 brp_inc 1 > dummy_can FD: dtseg1 2..256 dtseg2 2..128 dsjw 1..128 dbrp 1..512 dbrp_inc 1 > tdco 0..127 tdcf 0..127 > xbitrate 20000000 xsample-point 0.625 > xtq 6 xprop-seg 2 xphase-seg1 2 xphase-seg2 3 xsjw 1 xbrp 1 > pwms 2 pwml 6 pwmo 0 > dummy_can XL: xtseg1 2..256 xtseg2 2..128 xsjw 1..128 xbrp 1..512 xbrp_inc 1 > xtdco 0..127 xtdcf 0..127 > pwms 1..8 pwml 2..24 pwmo 0..16 > clock 160000000 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 tso_max_size 65536 tso_max_segs 65535 gro_max_size 65536 gso_ipv4_max_size 65536 gro_ipv4_max_size 65536 > > Signed-off-by: Vincent Mailhol <mailhol@kernel.org> > --- > ip/iplink_can.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 91 insertions(+), 1 deletion(-) > > diff --git a/ip/iplink_can.c b/ip/iplink_can.c > index 3e7925e8..d43dc9bb 100644 > --- a/ip/iplink_can.c > +++ b/ip/iplink_can.c > @@ -34,7 +34,7 @@ static void print_usage(FILE *f) > "\n" > "\t[ xbitrate BITRATE [ xsample-point SAMPLE-POINT] ] |\n" > "\t[ xtq TQ xprop-seg PROP_SEG xphase-seg1 PHASE-SEG1\n \t xphase-seg2 PHASE-SEG2 [ xsjw SJW ] ]\n" > - "\t[ xtdcv TDCV xtdco TDCO xtdcf TDCF ]\n" > + "\t[ xtdcv TDCV xtdco TDCO xtdcf TDCF pwms PWMS pwml PWML pwmo PWMO]\n" > "\n" > "\t[ loopback { on | off } ]\n" > "\t[ listen-only { on | off } ]\n" > @@ -67,6 +67,9 @@ static void print_usage(FILE *f) > "\t TDCV := { NUMBER in mtq }\n" > "\t TDCO := { NUMBER in mtq }\n" > "\t TDCF := { NUMBER in mtq }\n" > + "\t PWMS := { NUMBER in mtq }\n" > + "\t PWML := { NUMBER in mtq }\n" > + "\t PWMO := { NUMBER in mtq }\n" > "\t RESTART-MS := { 0 | NUMBER in ms }\n" > "\n" > "\tUnits:\n" > @@ -143,6 +146,7 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, > struct can_ctrlmode cm = { 0 }; > struct can_tdc fd = { .tdcv = -1, .tdco = -1, .tdcf = -1 }; > struct can_tdc xl = { .tdcv = -1, .tdco = -1, .tdcf = -1 }; > + __u32 pwms = -1, pwml = -1, pwmo = -1; > > while (argc > 0) { > if (matches(*argv, "bitrate") == 0) { > @@ -266,6 +270,18 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, > NEXT_ARG(); > if (get_u32(&xl.tdcf, *argv, 0)) > invarg("invalid \"xtdcf\" value", *argv); > + } else if (matches(*argv, "pwms") == 0) { > + NEXT_ARG(); > + if (get_u32(&pwms, *argv, 0)) > + invarg("invalid \"pwms\" value", *argv); > + } else if (matches(*argv, "pwml") == 0) { > + NEXT_ARG(); > + if (get_u32(&pwml, *argv, 0)) > + invarg("invalid \"pwml\" value", *argv); > + } else if (matches(*argv, "pwmo") == 0) { > + NEXT_ARG(); > + if (get_u32(&pwmo, *argv, 0)) > + invarg("invalid \"pwmo\" value", *argv); > } else if (matches(*argv, "loopback") == 0) { > NEXT_ARG(); > set_ctrlmode("loopback", *argv, &cm, > @@ -401,6 +417,18 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, > addattr32(n, 1024, IFLA_CAN_TDC_TDCF, xl.tdcf); > addattr_nest_end(n, tdc); > } > + if (pwms != -1 || pwml != -1 || pwmo != -1) { > + struct rtattr *pwm = addattr_nest(n, 1024, > + IFLA_CAN_XL_PWM | NLA_F_NESTED); > + > + if (pwms != -1) > + addattr32(n, 1024, IFLA_CAN_PWM_PWMS, pwms); > + if (pwml != -1) > + addattr32(n, 1024, IFLA_CAN_PWM_PWML, pwml); > + if (pwmo != -1) > + addattr32(n, 1024, IFLA_CAN_PWM_PWMO, pwmo); > + addattr_nest_end(n, pwm); > + } > > return 0; > } > @@ -496,6 +524,62 @@ static void can_print_tdc_const_opt(struct rtattr *tdc_attr, bool is_xl) > close_json_object(); > } > > +static void can_print_pwm_opt(struct rtattr *pwm_attr) > +{ > + struct rtattr *tb[IFLA_CAN_PWM_MAX + 1]; > + > + parse_rtattr_nested(tb, IFLA_CAN_PWM_MAX, pwm_attr); > + if (tb[IFLA_CAN_PWM_PWMS] || tb[IFLA_CAN_PWM_PWML] || > + tb[IFLA_CAN_PWM_PWMO]) { > + open_json_object("pwm"); > + can_print_nl_indent(); > + if (tb[IFLA_CAN_PWM_PWMS]) { > + __u32 *pwms = RTA_DATA(tb[IFLA_CAN_PWM_PWMS]); > + > + print_uint(PRINT_ANY, " pwms", " pwms %u", *pwms); > + } > + if (tb[IFLA_CAN_PWM_PWML]) { > + __u32 *pwml = RTA_DATA(tb[IFLA_CAN_PWM_PWML]); > + > + print_uint(PRINT_ANY, " pwml", " pwml %u", *pwml); > + } > + if (tb[IFLA_CAN_PWM_PWMO]) { > + __u32 *pwmo = RTA_DATA(tb[IFLA_CAN_PWM_PWMO]); > + > + print_uint(PRINT_ANY, " pwmo", " pwmo %u", *pwmo); > + } > + close_json_object(); > + } > +} > + > +static void can_print_pwm_const_opt(struct rtattr *pwm_attr) > +{ > + struct rtattr *tb[IFLA_CAN_PWM_MAX + 1]; > + > + parse_rtattr_nested(tb, IFLA_CAN_PWM_MAX, pwm_attr); > + open_json_object("pwm"); > + can_print_nl_indent(); > + if (tb[IFLA_CAN_PWM_PWMS_MAX]) { > + __u32 *pwms_min = RTA_DATA(tb[IFLA_CAN_PWM_PWMS_MIN]); > + __u32 *pwms_max = RTA_DATA(tb[IFLA_CAN_PWM_PWMS_MAX]); > + > + can_print_timing_min_max("pwms", " pwms", *pwms_min, *pwms_max); > + } > + if (tb[IFLA_CAN_PWM_PWML_MAX]) { > + __u32 *pwml_min = RTA_DATA(tb[IFLA_CAN_PWM_PWML_MIN]); > + __u32 *pwml_max = RTA_DATA(tb[IFLA_CAN_PWM_PWML_MAX]); > + > + can_print_timing_min_max("pwml", " pwml", *pwml_min, *pwml_max); > + } > + if (tb[IFLA_CAN_PWM_PWMO_MAX]) { > + __u32 *pwmo_min = RTA_DATA(tb[IFLA_CAN_PWM_PWMO_MIN]); > + __u32 *pwmo_max = RTA_DATA(tb[IFLA_CAN_PWM_PWMO_MAX]); > + > + can_print_timing_min_max("pwmo", " pwmo", *pwmo_min, *pwmo_max); > + } > + close_json_object(); > +} > + > static void can_print_ctrlmode_ext(struct rtattr *ctrlmode_ext_attr, > __u32 cm_flags) > { > @@ -735,6 +819,9 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) > if (tb[IFLA_CAN_XL_TDC]) > can_print_tdc_opt(tb[IFLA_CAN_XL_TDC], true); > > + if (tb[IFLA_CAN_XL_PWM]) > + can_print_pwm_opt(tb[IFLA_CAN_XL_PWM]); > + > close_json_object(); > } > > @@ -759,6 +846,9 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) > if (tb[IFLA_CAN_XL_TDC]) > can_print_tdc_const_opt(tb[IFLA_CAN_XL_TDC], true); > > + if (tb[IFLA_CAN_XL_PWM]) > + can_print_pwm_const_opt(tb[IFLA_CAN_XL_PWM]); > + > close_json_object(); > } > > ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 0/7] iplink_can: add CAN XL support 2025-11-29 15:29 [PATCH 0/7] iplink_can: add CAN XL support Vincent Mailhol ` (6 preceding siblings ...) 2025-11-29 15:29 ` [PATCH 7/7] iplink_can: add CAN XL's PWM interface Vincent Mailhol @ 2025-11-29 15:38 ` Vincent Mailhol 7 siblings, 0 replies; 15+ messages in thread From: Vincent Mailhol @ 2025-11-29 15:38 UTC (permalink / raw) To: netdev, Stephen Hemminger, Marc Kleine-Budde, Oliver Hartkopp, David Ahern Cc: linux-kernel, linux-can On 29/11/2025 at 16:29, Vincent Mailhol wrote: > Support for CAN XL was added to the kernel in [1]. This series is the > iproute2 counterpart. > > Patches #1 to #3 are clean-ups. They refactor iplink_can's > print_usage()'s function. > > Patches #4 to #7 add the CAN XL interface to iplink_can. > > [1] commit 113aa9101a91 ("Merge patch series "can: netlink: add CAN XL support") > Link: https://git.kernel.org/netdev/net-next/c/113aa9101a91 > > Signed-off-by: Vincent Mailhol <mailhol@kernel.org> And just after sending, I realized that I forgot to add the "iproute2-next" prefix in the patch subjects. Well, I will wait for the comments first and resent on Monday with the correct tag. Yours sincerely, Vincent Mailhol ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2025-11-29 23:16 UTC | newest] Thread overview: 15+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-11-29 15:29 [PATCH 0/7] iplink_can: add CAN XL support Vincent Mailhol 2025-11-29 15:29 ` [PATCH 1/7] iplink_can: print_usage: fix the text indentation Vincent Mailhol 2025-11-29 15:29 ` [PATCH 2/7] iplink_can: print_usage: change unit for minimum time quanta to mtq Vincent Mailhol 2025-11-29 15:29 ` [PATCH 3/7] iplink_can: print_usage: describe the CAN bittiming units Vincent Mailhol 2025-11-29 15:29 ` [PATCH 4/7] iplink_can: add the "restricted" option Vincent Mailhol 2025-11-29 17:03 ` Stephen Hemminger 2025-11-29 15:29 ` [PATCH 5/7] iplink_can: add initial CAN XL support Vincent Mailhol 2025-11-29 17:04 ` Stephen Hemminger 2025-11-29 23:13 ` Vincent Mailhol 2025-11-29 15:29 ` [PATCH 6/7] iplink_can: add CAN XL's "tms" option Vincent Mailhol 2025-11-29 17:21 ` Oliver Hartkopp 2025-11-29 23:16 ` Vincent Mailhol 2025-11-29 15:29 ` [PATCH 7/7] iplink_can: add CAN XL's PWM interface Vincent Mailhol 2025-11-29 17:26 ` Oliver Hartkopp 2025-11-29 15:38 ` [PATCH 0/7] iplink_can: add CAN XL support Vincent Mailhol
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).