[PATCH v2 05/10] can: netlink: add CAN_CTRLMODE_XL_TMS flag

Vincent Mailhol posted 10 patches 3 months, 2 weeks ago
Re: [PATCH v2 05/10] can: netlink: add CAN_CTRLMODE_XL_TMS flag
Posted by Oliver Hartkopp 3 months ago
Hello Vincent,

On 21.10.25 17:47, Vincent Mailhol wrote:
> 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 CAN_CTRLMODE_XL_TMS flag to the list of the CAN control modes.
> 
> In the netlink interface, each boolean option is in reality a tristate
> in disguise: on, off or omitted. For the moment, TMS is implemented as
> below:
> 
>    - CAN_CTRLMODE_XL_TMS is set to false: TMS is disabled.
>    - CAN_CTRLMODE_XL_TMS is set to true: TMS is enabled.
>    - CAN_CTRLMODE_XL_TMS is omitted: return -EOPNOTSUPP.

I would propose to follow the usual pattern:

- TMS off (default)
- TMS on (when selected on the command line)

> For most of the other control modes, omitting a flag default to the
> option turned off. It could also be possible to provide a default
> behaviour if the TMS flag is omitted (i.e. either default to TMS off
> or on). However, it is not clear for the moment which default
> behaviour is preferable. If the usage shows a clear trend (for example
> if the vast majority of the users want TMS on by default), it is still
> possible to revisit that choice in the future. Whereas once a default
> option is provided, we can not change it back without breaking the
> interface.
> 
> As a corollary, for the moment, the users will be forced to specify
> the TMS in the ip tool when using CAN XL.
> 
> Add can_validate_xl_flags() to check the coherency of the TMS flag.
> That function will be reused in upcoming changes to validate the other
> CAN XL flags.
> 
> Signed-off-by: Vincent Mailhol <mailhol@kernel.org>
> ---
> Question:
> 
> Is it still possible to send Classical CAN frames when TMS is on? If
> not, we need to also add this filter in can_dev_dropped_skb():

No.

I've now learned there are two "CANXL-only" modes:

1. TMS on -> no CC/FD traffic
2. TMS off and ERR_SIG off -> no CC/FD traffic, because CC/FD require 
ERR_SIG on for a compliant transmission

And there is a "mixed-mode" with CC/FD/XL with TMS off ('ERR_SIG on' is 
default anyway).

This "mixed-mode" requires all bitrates for CC/FD/XL to be set and all 
these CAN protocols can be sent.

Currently the "mixed mode" consistency check does not insist on having 
FD on.

> 	if ((priv->ctrlmode & CAN_CTRLMODE_XL_TMS) && !can_is_canxl_skb(skb)) {
> 		netdev_info_once(dev,
> 				 "Classical CAN frames are not allowed under CAN XL's TMS mode\n");
> 		goto invalid_skb;
> 	}

Disabling CC & FD traffic with TMS on resp. ERR_SIG off is addressed in 
my patch:

[PATCH b4/canxl-netlink v2] can: drop unsupported CAN frames on socket 
and netdev level

https://lore.kernel.org/linux-can/20251103185336.32772-1-socketcan@hartkopp.net/T/#u

TMS on resp. ERR_SIG off urges FD to be off. And with this condition CC 
traffic is also disabled by that patch.

> My current assumption is that this is possible.

No.

> But the standard being
> not crystal clear on that point, I want to double check this with you!

Done ;-)

Best regards,
Oliver

> ---
>   drivers/net/can/dev/dev.c        |  2 ++
>   drivers/net/can/dev/netlink.c    | 52 +++++++++++++++++++++++++++++++++++++---
>   include/uapi/linux/can/netlink.h |  1 +
>   3 files changed, 52 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
> index 32f11db88295..1de5babcc4f3 100644
> --- a/drivers/net/can/dev/dev.c
> +++ b/drivers/net/can/dev/dev.c
> @@ -123,6 +123,8 @@ const char *can_get_ctrlmode_str(u32 ctrlmode)
>   		return "xl-tdc-auto";
>   	case CAN_CTRLMODE_XL_TDC_MANUAL:
>   		return "xl-tdc-manual";
> +	case CAN_CTRLMODE_XL_TMS:
> +		return "xl-tms";
>   	default:
>   		return "<unknown>";
>   	}
> diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
> index 2405f1265488..8afd2baa03cf 100644
> --- a/drivers/net/can/dev/netlink.c
> +++ b/drivers/net/can/dev/netlink.c
> @@ -181,6 +181,36 @@ static int can_validate_databittiming(struct nlattr *data[],
>   	return 0;
>   }
>   
> +static int can_validate_xl_flags(struct netlink_ext_ack *extack,
> +				 u32 masked_flags, u32 mask)
> +{
> +	if (masked_flags & CAN_CTRLMODE_XL) {
> +		if (!(mask & CAN_CTRLMODE_XL_TMS)) {
> +			NL_SET_ERR_MSG(extack, "Specify whether TMS is on or off");
> +			return -EOPNOTSUPP;
> +		}
> +		if (masked_flags & CAN_CTRLMODE_XL_TMS) {
> +			const u32 tms_conflicts_mask = CAN_CTRLMODE_FD |
> +				CAN_CTRLMODE_XL_TDC_MASK;
> +			u32 tms_conflicts = masked_flags & tms_conflicts_mask;
> +
> +			if (tms_conflicts) {
> +				NL_SET_ERR_MSG_FMT(extack,
> +						   "TMS and %s are mutually exclusive",
> +						   can_get_ctrlmode_str(tms_conflicts));
> +				return -EOPNOTSUPP;
> +			}
> +		}
> +	} else {
> +		if (mask & CAN_CTRLMODE_XL_TMS) {
> +			NL_SET_ERR_MSG(extack, "TMS requires CAN XL");
> +			return -EOPNOTSUPP;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
>   static int can_validate(struct nlattr *tb[], struct nlattr *data[],
>   			struct netlink_ext_ack *extack)
>   {
> @@ -201,6 +231,10 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
>   				       "Listen-only and restricted modes are mutually exclusive");
>   			return -EOPNOTSUPP;
>   		}
> +
> +		err = can_validate_xl_flags(extack, flags, cm->mask);
> +		if (err)
> +			return err;
>   	}
>   
>   	err = can_validate_bittiming(data, extack, IFLA_CAN_BITTIMING);
> @@ -227,7 +261,7 @@ static int can_ctrlmode_changelink(struct net_device *dev,
>   	struct can_priv *priv = netdev_priv(dev);
>   	struct can_ctrlmode *cm;
>   	const u32 xl_mandatory = CAN_CTRLMODE_RESTRICTED;
> -	u32 ctrlstatic, maskedflags, notsupp, ctrlstatic_missing, xl_missing;
> +	u32 ctrlstatic, maskedflags, deactivated, notsupp, ctrlstatic_missing, xl_missing;
>   
>   	if (!data[IFLA_CAN_CTRLMODE])
>   		return 0;
> @@ -239,6 +273,7 @@ static int can_ctrlmode_changelink(struct net_device *dev,
>   	cm = nla_data(data[IFLA_CAN_CTRLMODE]);
>   	ctrlstatic = can_get_static_ctrlmode(priv);
>   	maskedflags = cm->flags & cm->mask;
> +	deactivated = ~cm->flags & cm->mask;
>   	notsupp = maskedflags & ~(priv->ctrlmode_supported | ctrlstatic);
>   	ctrlstatic_missing = (maskedflags & ctrlstatic) ^ ctrlstatic;
>   	xl_missing = (priv->ctrlmode_supported & xl_mandatory) ^ xl_mandatory;
> @@ -268,11 +303,21 @@ static int can_ctrlmode_changelink(struct net_device *dev,
>   		return -EOPNOTSUPP;
>   	}
>   
> +	/* If FD was active and is not turned off, check for XL conflicts */
> +	if (priv->ctrlmode & CAN_CTRLMODE_FD & ~deactivated) {
> +		if (maskedflags & CAN_CTRLMODE_XL_TMS) {
> +			NL_SET_ERR_MSG(extack,
> +				       "TMS can not be activated while CAN FD is on");
> +			return -EOPNOTSUPP;
> +		}
> +	}
> +
>   	/* If a top dependency flag is provided, reset all its dependencies */
>   	if (cm->mask & CAN_CTRLMODE_FD)
>   		priv->ctrlmode &= ~CAN_CTRLMODE_FD_TDC_MASK;
>   	if (cm->mask & CAN_CTRLMODE_XL)
> -		priv->ctrlmode &= ~(CAN_CTRLMODE_XL_TDC_MASK);
> +		priv->ctrlmode &= ~(CAN_CTRLMODE_XL_TDC_MASK |
> +				    CAN_CTRLMODE_XL_TMS);
>   
>   	/* clear bits to be modified and copy the flag values */
>   	priv->ctrlmode &= ~cm->mask;
> @@ -404,7 +449,8 @@ static int can_dbt_changelink(struct net_device *dev, struct nlattr *data[],
>   	if (data[IFLA_CAN_CTRLMODE]) {
>   		struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
>   
> -		need_tdc_calc = !(cm->mask & tdc_mask);
> +		if (fd || !(priv->ctrlmode & CAN_CTRLMODE_XL_TMS))
> +			need_tdc_calc = !(cm->mask & tdc_mask);
>   	}
>   	if (data_tdc) {
>   		/* TDC parameters are provided: use them */
> diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netlink.h
> index c2c96c5978a8..ebafb091d80f 100644
> --- a/include/uapi/linux/can/netlink.h
> +++ b/include/uapi/linux/can/netlink.h
> @@ -107,6 +107,7 @@ struct can_ctrlmode {
>   #define CAN_CTRLMODE_XL			0x1000	/* CAN XL mode */
>   #define CAN_CTRLMODE_XL_TDC_AUTO	0x2000	/* XL transceiver automatically calculates TDCV */
>   #define CAN_CTRLMODE_XL_TDC_MANUAL	0x4000	/* XL TDCV is manually set up by user */
> +#define CAN_CTRLMODE_XL_TMS		0x8000	/* Transceiver Mode Switching */
>   
>   /*
>    * CAN device statistics
>
Re: [PATCH v2 05/10] can: netlink: add CAN_CTRLMODE_XL_TMS flag
Posted by Vincent Mailhol 3 months ago
Hello Oliver,

On 06/11/2025 at 09:42, Oliver Hartkopp wrote:
> Hello Vincent,
> 
> On 21.10.25 17:47, Vincent Mailhol wrote:
>> 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 CAN_CTRLMODE_XL_TMS flag to the list of the CAN control modes.
>>
>> In the netlink interface, each boolean option is in reality a tristate
>> in disguise: on, off or omitted. For the moment, TMS is implemented as
>> below:
>>
>>    - CAN_CTRLMODE_XL_TMS is set to false: TMS is disabled.
>>    - CAN_CTRLMODE_XL_TMS is set to true: TMS is enabled.
>>    - CAN_CTRLMODE_XL_TMS is omitted: return -EOPNOTSUPP.
> 
> I would propose to follow the usual pattern:
> 
> - TMS off (default)
> - TMS on (when selected on the command line)

OK. "TMS omitted" will be interpreted as "TMS off" in v2.

>> For most of the other control modes, omitting a flag default to the
>> option turned off. It could also be possible to provide a default
>> behaviour if the TMS flag is omitted (i.e. either default to TMS off
>> or on). However, it is not clear for the moment which default
>> behaviour is preferable. If the usage shows a clear trend (for example
>> if the vast majority of the users want TMS on by default), it is still
>> possible to revisit that choice in the future. Whereas once a default
>> option is provided, we can not change it back without breaking the
>> interface.
>>
>> As a corollary, for the moment, the users will be forced to specify
>> the TMS in the ip tool when using CAN XL.
>>
>> Add can_validate_xl_flags() to check the coherency of the TMS flag.
>> That function will be reused in upcoming changes to validate the other
>> CAN XL flags.
>>
>> Signed-off-by: Vincent Mailhol <mailhol@kernel.org>
>> ---
>> Question:
>>
>> Is it still possible to send Classical CAN frames when TMS is on? If
>> not, we need to also add this filter in can_dev_dropped_skb():
> 
> No.
> 
> I've now learned there are two "CANXL-only" modes:
> 
> 1. TMS on -> no CC/FD traffic
> 2. TMS off and ERR_SIG off -> no CC/FD traffic, because CC/FD require ERR_SIG on
> for a compliant transmission

I see. I was under the assumption that CC and FD could be used with error
signalling off in mixed mode. Thanks!

> And there is a "mixed-mode" with CC/FD/XL with TMS off ('ERR_SIG on' is default
> anyway).
> 
> This "mixed-mode" requires all bitrates for CC/FD/XL to be set and all these CAN
> protocols can be sent.

Why? Will your device reject the configuration if you omit the FD bitrate? I did
not see anything in this direction in the ISO standard.

Did you have any source for this? Maybe the CiA provided some clarification
which I am not aware of?


Yours sincerely,
Vincent Mailhol

Re: [PATCH v2 05/10] can: netlink: add CAN_CTRLMODE_XL_TMS flag
Posted by Oliver Hartkopp 3 months ago
Hi Vincent,

On 09.11.25 15:28, Vincent Mailhol wrote:
> Hello Oliver,
> 
> On 06/11/2025 at 09:42, Oliver Hartkopp wrote:
>> Hello Vincent,
>>
>> On 21.10.25 17:47, Vincent Mailhol wrote:
>>> 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 CAN_CTRLMODE_XL_TMS flag to the list of the CAN control modes.
>>>
>>> In the netlink interface, each boolean option is in reality a tristate
>>> in disguise: on, off or omitted. For the moment, TMS is implemented as
>>> below:
>>>
>>>     - CAN_CTRLMODE_XL_TMS is set to false: TMS is disabled.
>>>     - CAN_CTRLMODE_XL_TMS is set to true: TMS is enabled.
>>>     - CAN_CTRLMODE_XL_TMS is omitted: return -EOPNOTSUPP.
>>
>> I would propose to follow the usual pattern:
>>
>> - TMS off (default)
>> - TMS on (when selected on the command line)
> 
> OK. "TMS omitted" will be interpreted as "TMS off" in v2.
> 

Thx!

>>> For most of the other control modes, omitting a flag default to the
>>> option turned off. It could also be possible to provide a default
>>> behaviour if the TMS flag is omitted (i.e. either default to TMS off
>>> or on). However, it is not clear for the moment which default
>>> behaviour is preferable. If the usage shows a clear trend (for example
>>> if the vast majority of the users want TMS on by default), it is still
>>> possible to revisit that choice in the future. Whereas once a default
>>> option is provided, we can not change it back without breaking the
>>> interface.
>>>
>>> As a corollary, for the moment, the users will be forced to specify
>>> the TMS in the ip tool when using CAN XL.
>>>
>>> Add can_validate_xl_flags() to check the coherency of the TMS flag.
>>> That function will be reused in upcoming changes to validate the other
>>> CAN XL flags.
>>>
>>> Signed-off-by: Vincent Mailhol <mailhol@kernel.org>
>>> ---
>>> Question:
>>>
>>> Is it still possible to send Classical CAN frames when TMS is on? If
>>> not, we need to also add this filter in can_dev_dropped_skb():
>>
>> No.
>>
>> I've now learned there are two "CANXL-only" modes:
>>
>> 1. TMS on -> no CC/FD traffic
>> 2. TMS off and ERR_SIG off -> no CC/FD traffic, because CC/FD require ERR_SIG on
>> for a compliant transmission
> 
> I see. I was under the assumption that CC and FD could be used with error
> signalling off in mixed mode. Thanks!
> 
>> And there is a "mixed-mode" with CC/FD/XL with TMS off ('ERR_SIG on' is default
>> anyway).
>>
>> This "mixed-mode" requires all bitrates for CC/FD/XL to be set and all these CAN
>> protocols can be sent.
> 
> Why? Will your device reject the configuration if you omit the FD bitrate? I did
> not see anything in this direction in the ISO standard.
> 
> Did you have any source for this? Maybe the CiA provided some clarification
> which I am not aware of?

It wasn't clear to me either.

Please take a look into the X_CAN user manual here:

https://github.com/linux-can/can-doc/blob/master/x_can/xcan_user_manual_v350.pdf

1.5.5.3 Operating Mode

There you can see the valid (and invalid) modes & combinations.

When XL is on, FD also has to be on. Of course this is Bosch specific in 
the first place. But there are two modes (ERR_SIGNAL off either with TMS 
on or off) that are "CANXL-Only" which means no CC and no FD traffic as 
those need error-signalling. CAN XL is using the (CC) arbitration 
bitrate in this XL-only mode but CAN CC frames can not be sent.

I would recommend this CAN CiA Webinar from Dr. Arthur Mutter:
https://www.youtube.com/watch?v=OSEj6ISJKAM

As (only!) the CAN FD controllers are CAN XL tolerant (see video 
timestamp 18:53) the "mixed-mode" basically means "a mix of XL and FD 
controllers and protocols".

The fact that FD&XL controllers then can also send CC frames in this 
mixed-mode is just a side-effect IMO. The idea is FD & XL.

Therefore the two XL modes "XL-Only" and "mixed-mode" leads to FD on in 
the mixed-mode IMO. And this finally can be used in my "[PATCH 
b4/canxl-netlink v2] can: drop unsupported CAN frames on socket
and netdev level" patch.

Best regards,
Oliver