From nobody Mon Dec 1 23:03:14 2025 Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CB8CF3019A4 for ; Wed, 26 Nov 2025 10:17:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764152228; cv=none; b=SdcJJ1R0TXQ2G59FiCoJpVI7BftoKD+DMETBsvuVxXcFQh7FZhZIyMx1E2k1Uo1kXMHTohOrt9xwC8ymlv79dwn3zoIvHpJ2kvnpdNPCjWCiF9mFviWwmBVy1bZvH5ioKctr67LuXfESI7ZoSduoRrk7nm0edmhSaNfwkNo6vDU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764152228; c=relaxed/simple; bh=A7WTS7anSPZ6YLVdDadGHIINAL5yzAkq2g2WCt6lhp4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DY9upLDi2VT6hgBZsHj/coMnLkAklaNxbjwPLnZ4PHdsmg4Yw9n7L/gmihg5yS9rYFD0gOPL4j6QqCzrbDQNX/kiiBbnCnxyVqzAxFJ9PGEChGjU5k81eHbU8lQq4CzOsVyjALKHQVc4/JxSFQ+1TT10zcHwXGVaMLqkqsSgICU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1vOCZv-0000Qk-Dt; Wed, 26 Nov 2025 11:16:51 +0100 Received: from moin.white.stw.pengutronix.de ([2a0a:edc0:0:b01:1d::7b] helo=bjornoya.blackshift.org) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vOCZv-002aSh-0E; Wed, 26 Nov 2025 11:16:51 +0100 Received: from hardanger.blackshift.org (p54b152ce.dip0.t-ipconnect.de [84.177.82.206]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) (Authenticated sender: mkl-all@blackshift.org) by smtp.blackshift.org (Postfix) with ESMTPSA id C02974A88D6; Wed, 26 Nov 2025 10:16:50 +0000 (UTC) From: Marc Kleine-Budde Date: Wed, 26 Nov 2025 11:16:06 +0100 Subject: [PATCH can-next v8 05/17] can: netlink: add initial CAN XL support Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251126-canxl-v8-5-e7e3eb74f889@pengutronix.de> References: <20251126-canxl-v8-0-e7e3eb74f889@pengutronix.de> In-Reply-To: <20251126-canxl-v8-0-e7e3eb74f889@pengutronix.de> To: Marc Kleine-Budde , Vincent Mailhol , Oliver Hartkopp Cc: kernel@pengutronix.de, linux-can@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?St=C3=A9phane_Grosjean?= X-Mailer: b4 0.15-dev-a6db3 X-Developer-Signature: v=1; a=openpgp-sha256; l=12616; i=mkl@pengutronix.de; h=from:subject:message-id; bh=pGF0Wy9A8kQ3E4M42mvHQ/wbbHmZTOCn/dS8JuVSjYs=; b=owEBbQGS/pANAwAKAQx0Zd/5kJGcAcsmYgBpJtN7UQwO4e2W6K/augzchsq3aGCvjU5rkNgbm Xnd7ShNidKJATMEAAEKAB0WIQSf+wzYr2eoX/wVbPMMdGXf+ZCRnAUCaSbTewAKCRAMdGXf+ZCR nFARB/4yDkaQmWsh+T0VL39MBhJiFu5aXC3v1S3E35s0sBZR3BvppU8GVYiAnEOcA6fdPJGn3O6 NwuNbZPXtR80Th6O1Ijmq8Dk67vM2bxrdyL/Jm+9xaCL+n2kNEfwYOwxURFNeTrZZqHsktA2+hq /CGsowpohj9SmWGQYtoP7HLwAW2VtojB41xSybhZKeSrODPTfityvE82QqnY6T6Zz4eMVEcmR7q /rbvQuKJ2FY6xtkfH/kXP7UOfv8//d4IVpMwHNJN0XTW7Xs7L7OhatixqmjlT1X4cjnY0AnEaAl jABfVfemGZjlnXi3u+tT8StcagGmx/Yxo3EbiK4flGqbv2px X-Developer-Key: i=mkl@pengutronix.de; a=openpgp; fpr=C1400BA0B3989E6FBC7D5B5C2B5EE211C58AEA54 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: mkl@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org From: Vincent Mailhol 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 CAN XL netlink interface for all the features which are common with CAN FD. Any new CAN XL specific features are added later on. The first time CAN XL is activated, the MTU is set by default to CANXL_MAX_MTU. The user may then configure a custom MTU within the CANXL_MIN_MTU to CANXL_MAX_MTU range, in which case, the custom MTU value will be kept as long as CAN XL remains active. Signed-off-by: Vincent Mailhol Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- drivers/net/can/dev/dev.c | 14 +++++++- drivers/net/can/dev/netlink.c | 76 +++++++++++++++++++++++++++++++-----= ---- include/linux/can/bittiming.h | 6 ++-- include/linux/can/dev.h | 7 +++- include/uapi/linux/can/netlink.h | 7 ++++ 5 files changed, 90 insertions(+), 20 deletions(-) diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c index b6980d32e5b4..bdec2c52c8ec 100644 --- a/drivers/net/can/dev/dev.c +++ b/drivers/net/can/dev/dev.c @@ -117,6 +117,12 @@ const char *can_get_ctrlmode_str(u32 ctrlmode) return "TDC-MANUAL"; case CAN_CTRLMODE_RESTRICTED: return "RESTRICTED"; + case CAN_CTRLMODE_XL: + return "XL"; + case CAN_CTRLMODE_XL_TDC_AUTO: + return "XL-TDC-AUTO"; + case CAN_CTRLMODE_XL_TDC_MANUAL: + return "XL-TDC-MANUAL"; default: return ""; } @@ -350,7 +356,13 @@ void can_set_default_mtu(struct net_device *dev) { struct can_priv *priv =3D netdev_priv(dev); =20 - if (priv->ctrlmode & CAN_CTRLMODE_FD) { + if (priv->ctrlmode & CAN_CTRLMODE_XL) { + if (can_is_canxl_dev_mtu(dev->mtu)) + return; + dev->mtu =3D CANXL_MTU; + dev->min_mtu =3D CANXL_MIN_MTU; + dev->max_mtu =3D CANXL_MAX_MTU; + } else if (priv->ctrlmode & CAN_CTRLMODE_FD) { dev->mtu =3D CANFD_MTU; dev->min_mtu =3D CANFD_MTU; dev->max_mtu =3D CANFD_MTU; diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c index 87e731527dd7..fdd1fa7cf93a 100644 --- a/drivers/net/can/dev/netlink.c +++ b/drivers/net/can/dev/netlink.c @@ -2,7 +2,7 @@ /* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix * Copyright (C) 2006 Andrey Volkov, Varma Electronics * Copyright (C) 2008-2009 Wolfgang Grandegger - * Copyright (C) 2021 Vincent Mailhol + * Copyright (C) 2021-2025 Vincent Mailhol */ =20 #include @@ -22,6 +22,9 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + = 1] =3D { [IFLA_CAN_TERMINATION] =3D { .type =3D NLA_U16 }, [IFLA_CAN_TDC] =3D { .type =3D NLA_NESTED }, [IFLA_CAN_CTRLMODE_EXT] =3D { .type =3D NLA_NESTED }, + [IFLA_CAN_XL_DATA_BITTIMING] =3D { .len =3D sizeof(struct can_bittiming) = }, + [IFLA_CAN_XL_DATA_BITTIMING_CONST] =3D { .len =3D sizeof(struct can_bitti= ming_const) }, + [IFLA_CAN_XL_TDC] =3D { .type =3D NLA_NESTED }, }; =20 static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] =3D { @@ -70,7 +73,7 @@ static int can_validate_tdc(struct nlattr *data_tdc, return -EOPNOTSUPP; } =20 - /* If one of the CAN_CTRLMODE_TDC_* flag is set then TDC + /* If one of the CAN_CTRLMODE_{,XL}_TDC_* flags is set then TDC * must be set and vice-versa */ if ((tdc_auto || tdc_manual) && !data_tdc) { @@ -82,8 +85,8 @@ static int can_validate_tdc(struct nlattr *data_tdc, return -EOPNOTSUPP; } =20 - /* If providing TDC parameters, at least TDCO is needed. TDCV - * is needed if and only if CAN_CTRLMODE_TDC_MANUAL is set + /* If providing TDC parameters, at least TDCO is needed. TDCV is + * needed if and only if CAN_CTRLMODE_{,XL}_TDC_MANUAL is set */ if (data_tdc) { struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1]; @@ -126,10 +129,10 @@ static int can_validate_databittiming(struct nlattr *= data[], bool is_on; int err; =20 - /* Make sure that valid CAN FD configurations always consist of + /* Make sure that valid CAN FD/XL configurations always consist of * - nominal/arbitration bittiming * - data bittiming - * - control mode with CAN_CTRLMODE_FD set + * - control mode with CAN_CTRLMODE_{FD,XL} set * - TDC parameters are coherent (details in can_validate_tdc()) */ =20 @@ -139,7 +142,10 @@ static int can_validate_databittiming(struct nlattr *d= ata[], is_on =3D flags & CAN_CTRLMODE_FD; type =3D "FD"; } else { - return -EOPNOTSUPP; /* Place holder for CAN XL */ + data_tdc =3D data[IFLA_CAN_XL_TDC]; + tdc_flags =3D flags & CAN_CTRLMODE_XL_TDC_MASK; + is_on =3D flags & CAN_CTRLMODE_XL; + type =3D "XL"; } =20 if (is_on) { @@ -206,6 +212,11 @@ static int can_validate(struct nlattr *tb[], struct nl= attr *data[], if (err) return err; =20 + err =3D can_validate_databittiming(data, extack, + IFLA_CAN_XL_DATA_BITTIMING, flags); + if (err) + return err; + return 0; } =20 @@ -251,18 +262,26 @@ static int can_ctrlmode_changelink(struct net_device = *dev, /* If a top dependency flag is provided, reset all its dependencies */ if (cm->mask & CAN_CTRLMODE_FD) priv->ctrlmode &=3D ~CAN_CTRLMODE_FD_TDC_MASK; + if (cm->mask & CAN_CTRLMODE_XL) + priv->ctrlmode &=3D ~(CAN_CTRLMODE_XL_TDC_MASK); =20 /* clear bits to be modified and copy the flag values */ priv->ctrlmode &=3D ~cm->mask; priv->ctrlmode |=3D maskedflags; =20 - /* Wipe potential leftovers from previous CAN FD config */ + /* Wipe potential leftovers from previous CAN FD/XL config */ if (!(priv->ctrlmode & CAN_CTRLMODE_FD)) { memset(&priv->fd.data_bittiming, 0, sizeof(priv->fd.data_bittiming)); priv->ctrlmode &=3D ~CAN_CTRLMODE_FD_TDC_MASK; memset(&priv->fd.tdc, 0, sizeof(priv->fd.tdc)); } + if (!(priv->ctrlmode & CAN_CTRLMODE_XL)) { + memset(&priv->xl.data_bittiming, 0, + sizeof(priv->fd.data_bittiming)); + priv->ctrlmode &=3D ~CAN_CTRLMODE_XL_TDC_MASK; + memset(&priv->xl.tdc, 0, sizeof(priv->xl.tdc)); + } =20 can_set_default_mtu(dev); =20 @@ -337,7 +356,10 @@ static int can_dbt_changelink(struct net_device *dev, = struct nlattr *data[], dbt_params =3D &priv->fd; tdc_mask =3D CAN_CTRLMODE_FD_TDC_MASK; } else { - return -EOPNOTSUPP; /* Place holder for CAN XL */ + data_bittiming =3D data[IFLA_CAN_XL_DATA_BITTIMING]; + data_tdc =3D data[IFLA_CAN_XL_TDC]; + dbt_params =3D &priv->xl; + tdc_mask =3D CAN_CTRLMODE_XL_TDC_MASK; } =20 if (!data_bittiming) @@ -388,7 +410,7 @@ static int can_dbt_changelink(struct net_device *dev, s= truct nlattr *data[], */ can_calc_tdco(&dbt_params->tdc, dbt_params->tdc_const, &dbt, tdc_mask, &priv->ctrlmode, priv->ctrlmode_supported); - } /* else: both CAN_CTRLMODE_TDC_{AUTO,MANUAL} are explicitly + } /* else: both CAN_CTRLMODE_{,XL}_TDC_{AUTO,MANUAL} are explicitly * turned off. TDC is disabled: do nothing */ =20 @@ -493,6 +515,11 @@ static int can_changelink(struct net_device *dev, stru= ct nlattr *tb[], if (err) return err; =20 + /* CAN XL */ + err =3D can_dbt_changelink(dev, data, false, extack); + if (err) + return err; + if (data[IFLA_CAN_TERMINATION]) { const u16 termval =3D nla_get_u16(data[IFLA_CAN_TERMINATION]); const unsigned int num_term =3D priv->termination_const_cnt; @@ -560,14 +587,14 @@ static size_t can_data_bittiming_get_size(struct data= _bittiming_params *dbt_para { size_t size =3D 0; =20 - if (dbt_params->data_bittiming.bitrate) /* IFLA_CAN_DATA_BITTIMING */ + if (dbt_params->data_bittiming.bitrate) /* IFLA_CAN_{,XL}_DATA_BITTIMING= */ size +=3D nla_total_size(sizeof(dbt_params->data_bittiming)); - if (dbt_params->data_bittiming_const) /* IFLA_CAN_DATA_BITTIMING_CONST */ + if (dbt_params->data_bittiming_const) /* IFLA_CAN_{,XL}_DATA_BITTIMING_C= ONST */ size +=3D nla_total_size(sizeof(*dbt_params->data_bittiming_const)); - if (dbt_params->data_bitrate_const) /* IFLA_CAN_DATA_BITRATE_CONST */ + if (dbt_params->data_bitrate_const) /* IFLA_CAN_{,XL}_DATA_BITRATE_CONST= */ size +=3D nla_total_size(sizeof(*dbt_params->data_bitrate_const) * dbt_params->data_bitrate_const_cnt); - size +=3D can_tdc_get_size(dbt_params, tdc_flags);/* IFLA_CAN_TDC */ + size +=3D can_tdc_get_size(dbt_params, tdc_flags);/* IFLA_CAN_{,XL}_TDC */ =20 return size; } @@ -607,6 +634,9 @@ static size_t can_get_size(const struct net_device *dev) size +=3D can_data_bittiming_get_size(&priv->fd, priv->ctrlmode & CAN_CTRLMODE_FD_TDC_MASK); =20 + size +=3D can_data_bittiming_get_size(&priv->xl, + priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MASK); + return size; } =20 @@ -651,7 +681,9 @@ static int can_tdc_fill_info(struct sk_buff *skb, const= struct net_device *dev, tdc_is_enabled =3D can_fd_tdc_is_enabled(priv); tdc_manual =3D priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL; } else { - return -EOPNOTSUPP; /* Place holder for CAN XL */ + dbt_params =3D &priv->xl; + tdc_is_enabled =3D can_xl_tdc_is_enabled(priv); + tdc_manual =3D priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MANUAL; } tdc_const =3D dbt_params->tdc_const; tdc =3D &dbt_params->tdc; @@ -773,7 +805,19 @@ static int can_fill_info(struct sk_buff *skb, const st= ruct net_device *dev) =20 can_tdc_fill_info(skb, dev, IFLA_CAN_TDC) || =20 - can_ctrlmode_ext_fill_info(skb, priv) + can_ctrlmode_ext_fill_info(skb, priv) || + + can_bittiming_fill_info(skb, IFLA_CAN_XL_DATA_BITTIMING, + &priv->xl.data_bittiming) || + + can_bittiming_const_fill_info(skb, IFLA_CAN_XL_DATA_BITTIMING_CONST, + priv->xl.data_bittiming_const) || + + can_bitrate_const_fill_info(skb, IFLA_CAN_XL_DATA_BITRATE_CONST, + priv->xl.data_bitrate_const, + priv->xl.data_bitrate_const_cnt) || + + can_tdc_fill_info(skb, dev, IFLA_CAN_XL_TDC) ) =20 return -EMSGSIZE; diff --git a/include/linux/can/bittiming.h b/include/linux/can/bittiming.h index 3926c78b2222..b6cd2476ffd7 100644 --- a/include/linux/can/bittiming.h +++ b/include/linux/can/bittiming.h @@ -16,10 +16,12 @@ =20 #define CAN_CTRLMODE_FD_TDC_MASK \ (CAN_CTRLMODE_TDC_AUTO | CAN_CTRLMODE_TDC_MANUAL) +#define CAN_CTRLMODE_XL_TDC_MASK \ + (CAN_CTRLMODE_XL_TDC_AUTO | CAN_CTRLMODE_XL_TDC_MANUAL) #define CAN_CTRLMODE_TDC_AUTO_MASK \ - (CAN_CTRLMODE_TDC_AUTO) + (CAN_CTRLMODE_TDC_AUTO | CAN_CTRLMODE_XL_TDC_AUTO) #define CAN_CTRLMODE_TDC_MANUAL_MASK \ - (CAN_CTRLMODE_TDC_MANUAL) + (CAN_CTRLMODE_TDC_MANUAL | CAN_CTRLMODE_XL_TDC_MANUAL) =20 /* * struct can_tdc - CAN FD Transmission Delay Compensation parameters diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h index ab11c0e9111b..f15879bd818d 100644 --- a/include/linux/can/dev.h +++ b/include/linux/can/dev.h @@ -47,7 +47,7 @@ struct can_priv { =20 const struct can_bittiming_const *bittiming_const; struct can_bittiming bittiming; - struct data_bittiming_params fd; + struct data_bittiming_params fd, xl; unsigned int bitrate_const_cnt; const u32 *bitrate_const; u32 bitrate_max; @@ -85,6 +85,11 @@ static inline bool can_fd_tdc_is_enabled(const struct ca= n_priv *priv) return !!(priv->ctrlmode & CAN_CTRLMODE_FD_TDC_MASK); } =20 +static inline bool can_xl_tdc_is_enabled(const struct can_priv *priv) +{ + return !!(priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MASK); +} + static inline u32 can_get_static_ctrlmode(struct can_priv *priv) { return priv->ctrlmode & ~priv->ctrlmode_supported; diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netl= ink.h index fafd1cce4798..c2c96c5978a8 100644 --- a/include/uapi/linux/can/netlink.h +++ b/include/uapi/linux/can/netlink.h @@ -104,6 +104,9 @@ struct can_ctrlmode { #define CAN_CTRLMODE_TDC_AUTO 0x200 /* FD transceiver automatically calcu= lates TDCV */ #define CAN_CTRLMODE_TDC_MANUAL 0x400 /* FD TDCV is manually set up by us= er */ #define CAN_CTRLMODE_RESTRICTED 0x800 /* Restricted operation mode */ +#define CAN_CTRLMODE_XL 0x1000 /* CAN XL mode */ +#define CAN_CTRLMODE_XL_TDC_AUTO 0x2000 /* XL transceiver automatically ca= lculates TDCV */ +#define CAN_CTRLMODE_XL_TDC_MANUAL 0x4000 /* XL TDCV is manually set up by= user */ =20 /* * CAN device statistics @@ -139,6 +142,10 @@ enum { IFLA_CAN_BITRATE_MAX, IFLA_CAN_TDC, /* FD */ IFLA_CAN_CTRLMODE_EXT, + IFLA_CAN_XL_DATA_BITTIMING, + IFLA_CAN_XL_DATA_BITTIMING_CONST, + IFLA_CAN_XL_DATA_BITRATE_CONST, + IFLA_CAN_XL_TDC, =20 /* add new constants above here */ __IFLA_CAN_MAX, --=20 2.51.0