From nobody Mon Feb 9 04:44:37 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 97E283451C7; Tue, 21 Oct 2025 15:47:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061671; cv=none; b=a2JW0aM72Jmu6fm7p7UYDHqz5Xjx3CjR51AP7HolsxfeCldFY6by8gfrdEf/FoqzBrXpLeFZ9igBW0ZAYTh+W35GSg9wYqRQwglKhpRMk7UwdT0U49NW5ypir956FFnfOYKrFmuoEK9UFhHp8q1mxLed6dszDuJJKIiVRgOFQ8M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061671; c=relaxed/simple; bh=yloHVT/ZWbwsMdentgq3wkJfJDSHxtJH/8vBDr2zvH0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=flRkD98oZrFWvws2RHmfwOBbZJdbGJLoLJAX5URGoMgr8pPw9GxgGB7nwedt015odzQPo6zstKpjUd+JYp9g8M/AAjN/blRhR3mW+p/o4rTLTDCSwZLcY8TMBdk/jJpDEF4esqQKh6ZHcqlx/uFBceedMd2JyaEzK7UBx/hkqC4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pCiVa+qy; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="pCiVa+qy" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C4A42C4CEF5; Tue, 21 Oct 2025 15:47:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761061671; bh=yloHVT/ZWbwsMdentgq3wkJfJDSHxtJH/8vBDr2zvH0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=pCiVa+qyjSv3Zic1X1H0Ej2RTae+/7SlKzt0iMWsMNXEBw8vXJsG3HW2G5S0M0MTH XXYPe08W/TMjWNK5j5R+FEdYypKXFgF6PmT7EJSKAAydRhlASrtQ40FbqZuyyeI53s 9/ioUhKnyY/RRIvRhJMfOlIBD0vGuUORcJeNL6j2z8Cs3tIKsO3W6Lmd0sFsMXwLB/ Zfw73uo+fWtlT6tg5ITfl5s6+uFwbPyoG+lm9qhgS+sn6LtOrtXkUkJcQzy/ShObxf /HLWZaAF8EOv+ppgpkuOU14dGeZ2ITJHgURm6QSBoNgQ+VmPMuf2LMUJxXXBJPWjv8 6MsoDgJTjXIPg== From: Vincent Mailhol Date: Tue, 21 Oct 2025 17:47:01 +0200 Subject: [PATCH v2 01/10] can: bittiming: apply NL_SET_ERR_MSG() to can_calc_bittiming() 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: <20251021-canxl-netlink-v2-1-8b8f58257ab6@kernel.org> References: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> In-Reply-To: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> To: Marc Kleine-Budde , Oliver Hartkopp Cc: Vincent Mailhol , =?utf-8?q?St=C3=A9phane_Grosjean?= , Robert Nawrath , Minh Le , Duy Nguyen , linux-can@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=1133; i=mailhol@kernel.org; h=from:subject:message-id; bh=yloHVT/ZWbwsMdentgq3wkJfJDSHxtJH/8vBDr2zvH0=; b=owGbwMvMwCV2McXO4Xp97WbG02pJDBnfVzP7H3P+of8xdP3kmSnOv3fOYnDcIXb/XVVN2vXrO 1amizfod5SyMIhxMciKKbIsK+fkVugo9A479NcSZg4rE8gQBi5OAZjIkhuMDPPq5Bbur3yftXj/ iuT7JX8EZur6imxrj4++X6b5LTKn6icjw7F5KjPu3rGQ9fL99artyS7pxMipPImx618Kr08oWny knxMA X-Developer-Key: i=mailhol@kernel.org; a=openpgp; fpr=ED8F700574E67F20E574E8E2AB5FEB886DBB99C2 When CONFIG_CAN_CALC_BITTIMING is disabled, the can_calc_bittiming() functions can not be used and the user needs to provide all the bittiming parameters. Currently, can_calc_bittiming() prints an error message to the kernel log. Instead use NL_SET_ERR_MSG() to make it return the error message through the netlink interface so that the user can directly see it. Signed-off-by: Vincent Mailhol --- Changelog: v1 -> v2: - New patch. --- include/linux/can/bittiming.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/can/bittiming.h b/include/linux/can/bittiming.h index d30816dd93c7..3926c78b2222 100644 --- a/include/linux/can/bittiming.h +++ b/include/linux/can/bittiming.h @@ -141,7 +141,7 @@ static inline int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt, const struct can_bittiming_const *btc, struct netlink_ext_ack *extack) { - netdev_err(dev, "bit-timing calculation not available\n"); + NL_SET_ERR_MSG(extack, "bit-timing calculation not available\n"); return -EINVAL; } =20 --=20 2.51.0 From nobody Mon Feb 9 04:44:37 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 BBC3E345745; Tue, 21 Oct 2025 15:47:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061672; cv=none; b=Jz066HhExsRfUb2QiDB63efph+Ntrw/SP1kK+53Qt2CklkRteHylSo1UgFcuDUEWUkCPx52/NEhmNhT4xrvdVLbya4PHoXgA1spuig2XAELxaCFZMNc7d+zypVnMId8sPJGULQ66fUB6VK64q45IaeGQ5gj3fThbcgleqvnAf/k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061672; c=relaxed/simple; bh=scjXXTT0e+4ezgrthuEqjLN50AjGyZwgsF4n5XZ73B8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VZYZeDsI0GvM6F7H/iAPbrvbtCccvbTf1PQh+Fj8QoR9BwYgGKDhACC5n5Ijbjxy6ax+y1idynASOuh992FSSevl6qp9jkRQr0TTJTxWYb9hMk0TeV0GUfsFLXxRx/MTBmOvlzR3wk2hwR4cpbSiVhtEK+vZrApZmzQsHTXG3vw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pMCg31+e; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="pMCg31+e" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5F8F1C116C6; Tue, 21 Oct 2025 15:47:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761061672; bh=scjXXTT0e+4ezgrthuEqjLN50AjGyZwgsF4n5XZ73B8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=pMCg31+ekrgrx66bI9BiNlbkZk1HnIqDGM0tzpd956/5XhLQnHwYFcWYopNgzrUp7 o9TOD+2t+7rWXDNqJ0Th1aBGZBw2p3LKN46OJEMUPWWYspAzGGlKyPB60e9I+5bqzv K6YdD/iBIW2xwX1aa4R0A54Fzxo0KtMWiDB9YGuk1NBxrduGPJscLwO0dcHbaUR6n1 UkI6lMIF0N+1Ybdqpd4vrTXGBcI+Rl5G9+/0BH8V0Lo9Jgf1SwlLZLu85+/guwoKgc LdwjyXnRz5x5pH3EJ+taIvWVkVVSV959STH4Jz8yWc96CgH8Jpuno806WO5XLVGm0v iWTohvL5pv8Rg== From: Vincent Mailhol Date: Tue, 21 Oct 2025 17:47:02 +0200 Subject: [PATCH v2 02/10] can: dev: can_dev_dropped_skb: drop CAN FD skbs if FD is off 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: <20251021-canxl-netlink-v2-2-8b8f58257ab6@kernel.org> References: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> In-Reply-To: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> To: Marc Kleine-Budde , Oliver Hartkopp Cc: Vincent Mailhol , =?utf-8?q?St=C3=A9phane_Grosjean?= , Robert Nawrath , Minh Le , Duy Nguyen , linux-can@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=2234; i=mailhol@kernel.org; h=from:subject:message-id; bh=scjXXTT0e+4ezgrthuEqjLN50AjGyZwgsF4n5XZ73B8=; b=owGbwMvMwCV2McXO4Xp97WbG02pJDBnfV7PdEk7K4GbVWhbOvv1zV7yl4M/MxQzFyz+4979xu bEo4P3JjlIWBjEuBlkxRZZl5ZzcCh2F3mGH/lrCzGFlAhnCwMUpABOZms/IcLjDj0Np6YSunboq 3lf9El+HNvzNyIlyiaqZm+5Uv19lAcMfvgVb2F3DVM9feZhSflhc91NYlTBL7LWgF6/WqrxmEnj MBgA= X-Developer-Key: i=mailhol@kernel.org; a=openpgp; fpr=ED8F700574E67F20E574E8E2AB5FEB886DBB99C2 Currently, the CAN FD skb validation logic is based on the MTU: the interface is deemed FD capable if and only if its MTU is greater or equal to CANFD_MTU. This logic is showing its limit with the introduction of CAN XL. For example, consider the two scenarios below: 1. An interface configured with CAN FD on and CAN XL on 2. An interface configured with CAN FD off and CAN XL on In those two scenarios, the interfaces would have the same MTU: CANXL_MTU making it impossible to differentiate which one has CAN FD turned on and which one has it off. Because of the limitation, the only non-UAPI-breaking workaround is to do the check at the device level using the can_priv->ctrlmode flags. Unfortunately, the virtual interfaces (vcan, vxcan), which do not have a can_priv, are left behind. Add a check on the CAN_CTRLMODE_FD flag in can_dev_dropped_skb() and drop FD frames whenever the feature is turned off. Signed-off-by: Vincent Mailhol --- Changelog: RFC -> v1: - add an netdev_info_once() message. - this was sent as a standalone patch for discussion, it is now integrated in the CAN XL series. Link: https://lore.kernel.org/linux-can/20250907080504.598419-2-mailhol@k= ernel.org/ --- include/linux/can/dev.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h index 0fe8f80f223e..d59b283c981a 100644 --- a/include/linux/can/dev.h +++ b/include/linux/can/dev.h @@ -103,12 +103,20 @@ static inline bool can_dev_dropped_skb(struct net_dev= ice *dev, struct sk_buff *s if (priv->ctrlmode & CAN_CTRLMODE_LISTENONLY) { netdev_info_once(dev, "interface in listen only mode, dropping skb\n"); - kfree_skb(skb); - dev->stats.tx_dropped++; - return true; + goto invalid_skb; + } + + if (!(priv->ctrlmode & CAN_CTRLMODE_FD) && can_is_canfd_skb(skb)) { + netdev_info_once(dev, "CAN FD is disabled, dropping skb\n"); + goto invalid_skb; } =20 return can_dropped_invalid_skb(dev, skb); + +invalid_skb: + kfree_skb(skb); + dev->stats.tx_dropped++; + return true; } =20 void can_setup(struct net_device *dev); --=20 2.51.0 From nobody Mon Feb 9 04:44:37 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 9B5CF345738; Tue, 21 Oct 2025 15:47:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061674; cv=none; b=OrcbeOMy4MIP8AjuM+lghXESXSKLQDdfiHXzyT+hoJOzn/oxBjKBzvdFUzrReiWmpEvZrxyZ6fAun5ldWvU2YpOyJJyRFM3gmnXyeUdDqhFDWXvTtSoCfRmKNqDUKitNhmddEDnV5pTVjkeTfJ4oGXEgJpRmwGAEle/TUC2gBuA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061674; c=relaxed/simple; bh=tFf4+lXAeNYZli+rs0K7DqOchcgv+8Puazp7794X2kk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VpBj87WxvBT2orFv4PN04LHya3BuGLShmAvP7/5zjXoE7F1Cfd52Nj0vWaIY3unp6R6GIhplqikx/RXyK1cis2+NGUie33X/0PsWEnd6bpMPW9KIItZFu+o6nIf7hj2dr3AFTSdLP3MoJW2s3v8roznyy3stl5HgMDP7D3rYX30= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=masuvJsH; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="masuvJsH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EE9ADC4CEF1; Tue, 21 Oct 2025 15:47:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761061674; bh=tFf4+lXAeNYZli+rs0K7DqOchcgv+8Puazp7794X2kk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=masuvJsHagDvLpX83zJoXOXO4UkHSn3VTjxUqKmDlpZ1j0mJQk3eZcXVkM0zp6CFc sEbhM6SeMmV+HO95T3JICHOIsODUE/U1knp0STiWZ5Xv1YmfLXMtkKqnsKgB4IJBg1 uekhOWmbKlpeciNPu51Lf8AJwO272REXv4QjvO0qm71+Bu7nSj3xkAMZlDzma75W6M B8G0Uzm61A1mNPhWaGi0WlTTyWMRQnZH3nE/y2VE8gM0H4MAZtyPRlYV3iAa2mSe/a mMlh+uV2WfnhZs7DQn1WVL9/biDgvHFp4hEgWh06Mvc5MAC5cM/g+zkgT1mTFxQWq0 tMJsxVefawn3A== From: Vincent Mailhol Date: Tue, 21 Oct 2025 17:47:03 +0200 Subject: [PATCH v2 03/10] can: netlink: add CAN_CTRLMODE_RESTRICTED 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: <20251021-canxl-netlink-v2-3-8b8f58257ab6@kernel.org> References: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> In-Reply-To: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> To: Marc Kleine-Budde , Oliver Hartkopp Cc: Vincent Mailhol , =?utf-8?q?St=C3=A9phane_Grosjean?= , Robert Nawrath , Minh Le , Duy Nguyen , linux-can@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=5265; i=mailhol@kernel.org; h=from:subject:message-id; bh=tFf4+lXAeNYZli+rs0K7DqOchcgv+8Puazp7794X2kk=; b=owGbwMvMwCV2McXO4Xp97WbG02pJDBnfV3O4cPA5zOTwFBRcnB3qs/Pp70LhtO/9l1umpS09f 4Q5evuyjlIWBjEuBlkxRZZl5ZzcCh2F3mGH/lrCzGFlAhnCwMUpABMp8Wb4K39s+e9tLDvvWa3S ZPG/njh3M2vLhokZ3r8r7afIxjJef87w3+0wv+E8hsicbTaLN4jGGC45rttht0ru43sntn3B61p 2MwMA X-Developer-Key: i=mailhol@kernel.org; a=openpgp; fpr=ED8F700574E67F20E574E8E2AB5FEB886DBB99C2 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. A second niche exception is that the node may still send a data frame containing a time reference message if the node is a primary time provider, but because the time provider feature is not yet implemented in the kernel, this second exception is not relevant to us at the moment. Add the CAN_CTRLMODE_RESTRICTED control mode flag and update the can_dev_dropped_skb() helper function accordingly. Finally, bail out if both CAN_CTRLMODE_LISTENONLY and CAN_CTRLMODE_RESTRICTED are provided. Signed-off-by: Vincent Mailhol --- drivers/net/can/dev/dev.c | 2 ++ drivers/net/can/dev/netlink.c | 7 ++++++ include/linux/can/dev.h | 50 +++++++++++++++++++++---------------= ---- include/uapi/linux/can/netlink.h | 1 + 4 files changed, 36 insertions(+), 24 deletions(-) diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c index 0cc3d008adb3..3377afb6f1c4 100644 --- a/drivers/net/can/dev/dev.c +++ b/drivers/net/can/dev/dev.c @@ -115,6 +115,8 @@ const char *can_get_ctrlmode_str(u32 ctrlmode) return "fd-tdc-auto"; case CAN_CTRLMODE_TDC_MANUAL: return "fd-tdc-manual"; + case CAN_CTRLMODE_RESTRICTED: + return "restricted-operation"; default: return ""; } diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c index 0591406b6f32..f44b5dffa176 100644 --- a/drivers/net/can/dev/netlink.c +++ b/drivers/net/can/dev/netlink.c @@ -188,6 +188,13 @@ static int can_validate(struct nlattr *tb[], struct nl= attr *data[], struct can_ctrlmode *cm =3D nla_data(data[IFLA_CAN_CTRLMODE]); =20 flags =3D cm->flags & cm->mask; + + if ((flags & CAN_CTRLMODE_LISTENONLY) && + (flags & CAN_CTRLMODE_RESTRICTED)) { + NL_SET_ERR_MSG(extack, + "Listen-only and restricted modes are mutually exclusive"); + return -EOPNOTSUPP; + } } =20 err =3D can_validate_bittiming(data, extack, IFLA_CAN_BITTIMING); diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h index d59b283c981a..9de8fde3ec9d 100644 --- a/include/linux/can/dev.h +++ b/include/linux/can/dev.h @@ -95,30 +95,6 @@ static inline bool can_is_canxl_dev_mtu(unsigned int mtu) return (mtu >=3D CANXL_MIN_MTU && mtu <=3D CANXL_MAX_MTU); } =20 -/* drop skb if it does not contain a valid CAN frame for sending */ -static inline bool can_dev_dropped_skb(struct net_device *dev, struct sk_b= uff *skb) -{ - struct can_priv *priv =3D netdev_priv(dev); - - if (priv->ctrlmode & CAN_CTRLMODE_LISTENONLY) { - netdev_info_once(dev, - "interface in listen only mode, dropping skb\n"); - goto invalid_skb; - } - - if (!(priv->ctrlmode & CAN_CTRLMODE_FD) && can_is_canfd_skb(skb)) { - netdev_info_once(dev, "CAN FD is disabled, dropping skb\n"); - goto invalid_skb; - } - - return can_dropped_invalid_skb(dev, skb); - -invalid_skb: - kfree_skb(skb); - dev->stats.tx_dropped++; - return true; -} - void can_setup(struct net_device *dev); =20 struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb= _max, @@ -150,6 +126,32 @@ void can_bus_off(struct net_device *dev); const char *can_get_state_str(const enum can_state state); const char *can_get_ctrlmode_str(u32 ctrlmode); =20 +/* drop skb if it does not contain a valid CAN frame for sending */ +static inline bool can_dev_dropped_skb(struct net_device *dev, struct sk_b= uff *skb) +{ + struct can_priv *priv =3D netdev_priv(dev); + u32 silent_mode =3D priv->ctrlmode & (CAN_CTRLMODE_LISTENONLY | + CAN_CTRLMODE_RESTRICTED); + + if (silent_mode) { + netdev_info_once(dev, "interface in %s mode, dropping skb\n", + can_get_ctrlmode_str(silent_mode)); + goto invalid_skb; + } + + if (!(priv->ctrlmode & CAN_CTRLMODE_FD) && can_is_canfd_skb(skb)) { + netdev_info_once(dev, "CAN FD is disabled, dropping skb\n"); + goto invalid_skb; + } + + return can_dropped_invalid_skb(dev, skb); + +invalid_skb: + kfree_skb(skb); + dev->stats.tx_dropped++; + return true; +} + void can_state_get_by_berr_counter(const struct net_device *dev, const struct can_berr_counter *bec, enum can_state *tx_state, diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netl= ink.h index ef62f56eaaef..fafd1cce4798 100644 --- a/include/uapi/linux/can/netlink.h +++ b/include/uapi/linux/can/netlink.h @@ -103,6 +103,7 @@ struct can_ctrlmode { #define CAN_CTRLMODE_CC_LEN8_DLC 0x100 /* Classic CAN DLC option */ #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 */ =20 /* * CAN device statistics --=20 2.51.0 From nobody Mon Feb 9 04:44:37 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 5B0CD345CCB; Tue, 21 Oct 2025 15:47:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061676; cv=none; b=EPjiiYa711nOgukuU4dGLfZ14oQBj4HGvmrXzwC+ri1RjMyEyYxo1bczA2oMkEWrdb0ihuNAqrn/73b3LlUoar1EEYcyARZY8cuSO7C2ZqW6PRU0oB2XSDFHwDLughEY9ypIlgYdvuPtstXHlNg4XaB5XP75OlZfAx6Q2/ii/FY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061676; c=relaxed/simple; bh=ZaZgYQ11fV16hUuQKZ4WnEyWy+zlR0rVY3aLY/HuHfU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kGeDTl5z0hy2Ld6jA36dVty+blL0dSNb+/HpILmLwG7s3e8RMLoKSdMFVMU81W5UgTowPBsl/uYx4FLhUvN6da0ehS0twHOvWC423YVO2IojTqqga6PLRolLkUNoZ/jJPzIhWSvBfXcZKi/w+Z8NGBQtuuFdM6ByfMuw4x/xevM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dDzgCvct; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="dDzgCvct" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 88BA0C4CEF7; Tue, 21 Oct 2025 15:47:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761061675; bh=ZaZgYQ11fV16hUuQKZ4WnEyWy+zlR0rVY3aLY/HuHfU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=dDzgCvctFlP8TXxs1ey80pfb9LLh8JgyCofhqArUQZ9oBnXqovWunbwKWBf9RJFZC 3jk0MvzwbTWVYAYj+B3lrPQNrj1y3RQb27PSTrT7o1/5hCAoJ2oh5lsUq6acM5whUl Wcw0ZpnJ6btQvrzFMd1/kQ00YliXRRCZmXcnPX2UJrmwqvN8eZ/hahzXym9RhUIPpO M4h/lKoIfAxxdBxUGMzTFsXd4sah/0VrAU8ASQN4W7GbSCh4vlKnavsDd0psqBjrKH rFUL/P7W4gHeQMJDrtXOPGBgbxyPJV/jbzcjh74Bxf/P6jcNkGMG4lY07G6acgpzeS SHpDzT4pseNUg== From: Vincent Mailhol Date: Tue, 21 Oct 2025 17:47:04 +0200 Subject: [PATCH v2 04/10] 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: <20251021-canxl-netlink-v2-4-8b8f58257ab6@kernel.org> References: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> In-Reply-To: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> To: Marc Kleine-Budde , Oliver Hartkopp Cc: Vincent Mailhol , =?utf-8?q?St=C3=A9phane_Grosjean?= , Robert Nawrath , Minh Le , Duy Nguyen , linux-can@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=14038; i=mailhol@kernel.org; h=from:subject:message-id; bh=ZaZgYQ11fV16hUuQKZ4WnEyWy+zlR0rVY3aLY/HuHfU=; b=owGbwMvMwCV2McXO4Xp97WbG02pJDBnfV3Ofs1ByMzRRj3j2dv6LfbPEi0TVbYRU8xVOs8b9b dx6XVu5o5SFQYyLQVZMkWVZOSe3Qkehd9ihv5Ywc1iZQIYwcHEKwERalBkZOkxi59mEGzJ+1opj u3rseqDmvXeveng4BFrzbRXXMvZIMTIc3SOou/Rq46YFP5ZGxJ5Ps7/2NDl7Ou+nafJHDQQy6mI 5AQ== X-Developer-Key: i=mailhol@kernel.org; a=openpgp; fpr=ED8F700574E67F20E574E8E2AB5FEB886DBB99C2 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. Add a check that CAN XL capable nodes correctly provide CAN_CTRLMODE_RESTRIC_OP as mandated by ISO 11898-1:2024 =C2=A76.6.19. 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_MIN_MTU range, in which case, the custom MTU value will be kept as long as CAN XL remains active. Signed-off-by: Vincent Mailhol --- Changelog: RFC -> v1: - Correctly wipe out the CAN XL data bittiming and TDC parameters when switching CAN_CTRLMODE_XL off. - Add one level on nesting for xl parameters so that: - bittiming are under priv->xl.data_bittiming{,_const}=C2=A8 - pwm are under priv->xl.pwm{,_const} - Many other code refactors. --- drivers/net/can/dev/dev.c | 14 ++++++- drivers/net/can/dev/netlink.c | 87 ++++++++++++++++++++++++++++++++----= ---- include/linux/can/bittiming.h | 6 ++- include/linux/can/dev.h | 7 +++- include/uapi/linux/can/netlink.h | 7 ++++ 5 files changed, 100 insertions(+), 21 deletions(-) diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c index 3377afb6f1c4..32f11db88295 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 "fd-tdc-manual"; case CAN_CTRLMODE_RESTRICTED: return "restricted-operation"; + 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 f44b5dffa176..2405f1265488 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 @@ -215,7 +226,8 @@ static int can_ctrlmode_changelink(struct net_device *d= ev, { struct can_priv *priv =3D netdev_priv(dev); struct can_ctrlmode *cm; - u32 ctrlstatic, maskedflags, notsupp, ctrlstatic_missing; + const u32 xl_mandatory =3D CAN_CTRLMODE_RESTRICTED; + u32 ctrlstatic, maskedflags, notsupp, ctrlstatic_missing, xl_missing; =20 if (!data[IFLA_CAN_CTRLMODE]) return 0; @@ -229,6 +241,7 @@ static int can_ctrlmode_changelink(struct net_device *d= ev, maskedflags =3D cm->flags & cm->mask; notsupp =3D maskedflags & ~(priv->ctrlmode_supported | ctrlstatic); ctrlstatic_missing =3D (maskedflags & ctrlstatic) ^ ctrlstatic; + xl_missing =3D (priv->ctrlmode_supported & xl_mandatory) ^ xl_mandatory; =20 if (notsupp) { NL_SET_ERR_MSG_FMT(extack, @@ -248,21 +261,36 @@ static int can_ctrlmode_changelink(struct net_device = *dev, return -EOPNOTSUPP; } =20 + if ((priv->ctrlmode_supported & CAN_CTRLMODE_XL) && xl_missing) { + NL_SET_ERR_MSG_FMT(extack, + "bad device: CAN XL capable nodes must support the %s mode", + can_get_ctrlmode_str(xl_missing)); + return -EOPNOTSUPP; + } + /* 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 +365,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 +419,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 @@ -491,6 +522,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; @@ -558,14 +594,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; } @@ -605,6 +641,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 @@ -649,7 +688,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; @@ -771,7 +812,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 9de8fde3ec9d..945c16743702 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 From nobody Mon Feb 9 04:44:37 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 A14FA3451A2; Tue, 21 Oct 2025 15:47:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061677; cv=none; b=NinT8JtRgQO2lmWYcNlDz+EV6lwpV1ZflyLWLTwtdsh4Xxutza2QHioa/bpZY5WBkiJTnyU0RCM3+jl7Ax/5N09pLIwr5ynsOvWHU8b1Hc0IbACR/VQZrGQhq7piv3kkgvfCzSDNZQceOPB8jjYLTVhidzDG0VwHdhmqEtw4n3k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061677; c=relaxed/simple; bh=KxWfStPCsdAJffcmrXgkN/o73wm2RB31sl71hbd/rIo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Cgo4x+AIRKqyYbjeZZEM9JXM2AHefceLf7LGGp9IoDi5SKF4nQ6M58KpRJSxV3ySGUg5A+jtjsGy/OzmkJ5ibma9WyrQ7Fd27lo4izkpPkhhX73PsE390yrbBqPlgswE/XAWDXRbahKveRFNomr/D9rXpgHyyxtFyYD05xEcW1c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Yjr8X3gn; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Yjr8X3gn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 42EC3C4CEF1; Tue, 21 Oct 2025 15:47:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761061677; bh=KxWfStPCsdAJffcmrXgkN/o73wm2RB31sl71hbd/rIo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Yjr8X3gnrA+d1f4BEDdbVedEJHhAy+Cnd3AW9dMAkBk6/bEFjjVJcWOAD4ykxrrQB JvFGLGfrHkSm69m0Kc/sPu8uxtXKb70LY4elleaYjhl2wVZ+Wee18EzVdlm3HHIcsI nZpSpBgsYxBF2GNLOialKnednEaed3GLq0IwX6XSUI+ec/zI6sS4ZZz5lTK1kixXCw Ne4llz7TUWIiQ/uCepE0G7KyCoixttAPk+EsqLocU0vJNvOOlb1Csv2LEN4hgmTEZl MvJZ/vpseMFL44v3K2lX7gaq09JBYKPSbvwUEN+a2sEdsx7XXnZCkrTM3fGmXgIT1o dg/zcUwNQ/GMQ== From: Vincent Mailhol Date: Tue, 21 Oct 2025 17:47:05 +0200 Subject: [PATCH v2 05/10] can: netlink: add CAN_CTRLMODE_XL_TMS flag 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: <20251021-canxl-netlink-v2-5-8b8f58257ab6@kernel.org> References: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> In-Reply-To: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> To: Marc Kleine-Budde , Oliver Hartkopp Cc: Vincent Mailhol , =?utf-8?q?St=C3=A9phane_Grosjean?= , Robert Nawrath , Minh Le , Duy Nguyen , linux-can@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=7104; i=mailhol@kernel.org; h=from:subject:message-id; bh=KxWfStPCsdAJffcmrXgkN/o73wm2RB31sl71hbd/rIo=; b=owGbwMvMwCV2McXO4Xp97WbG02pJDBnfV/MvnWriYrbDXsDm5dv8Ryms3s0ac4xecpQqa335s rPwUpBVRykLgxgXg6yYIsuyck5uhY5C77BDfy1h5rAygQxh4OIUgIlML2P4w+0k/vuh5DpTYYXu yPN3AsRa1C65BmyJfnL55vMzfGdX6TD8lZ695VnrnzcP/t3dWMb6kdMupuTrwqIO7bJvD5nDU5s DeQE= X-Developer-Key: i=mailhol@kernel.org; a=openpgp; fpr=ED8F700574E67F20E574E8E2AB5FEB886DBB99C2 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. 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 --- 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(): 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; } My current assumption is that this is possible. But the standard being not crystal clear on that point, I want to double check this with you! --- 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 ""; } 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 *d= ata[], return 0; } =20 +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 =3D CAN_CTRLMODE_FD | + CAN_CTRLMODE_XL_TDC_MASK; + u32 tms_conflicts =3D 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 nl= attr *data[], "Listen-only and restricted modes are mutually exclusive"); return -EOPNOTSUPP; } + + err =3D can_validate_xl_flags(extack, flags, cm->mask); + if (err) + return err; } =20 err =3D can_validate_bittiming(data, extack, IFLA_CAN_BITTIMING); @@ -227,7 +261,7 @@ static int can_ctrlmode_changelink(struct net_device *d= ev, struct can_priv *priv =3D netdev_priv(dev); struct can_ctrlmode *cm; const u32 xl_mandatory =3D CAN_CTRLMODE_RESTRICTED; - u32 ctrlstatic, maskedflags, notsupp, ctrlstatic_missing, xl_missing; + u32 ctrlstatic, maskedflags, deactivated, notsupp, ctrlstatic_missing, xl= _missing; =20 if (!data[IFLA_CAN_CTRLMODE]) return 0; @@ -239,6 +273,7 @@ static int can_ctrlmode_changelink(struct net_device *d= ev, cm =3D nla_data(data[IFLA_CAN_CTRLMODE]); ctrlstatic =3D can_get_static_ctrlmode(priv); maskedflags =3D cm->flags & cm->mask; + deactivated =3D ~cm->flags & cm->mask; notsupp =3D maskedflags & ~(priv->ctrlmode_supported | ctrlstatic); ctrlstatic_missing =3D (maskedflags & ctrlstatic) ^ ctrlstatic; xl_missing =3D (priv->ctrlmode_supported & xl_mandatory) ^ xl_mandatory; @@ -268,11 +303,21 @@ static int can_ctrlmode_changelink(struct net_device = *dev, return -EOPNOTSUPP; } =20 + /* 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 &=3D ~CAN_CTRLMODE_FD_TDC_MASK; if (cm->mask & CAN_CTRLMODE_XL) - priv->ctrlmode &=3D ~(CAN_CTRLMODE_XL_TDC_MASK); + priv->ctrlmode &=3D ~(CAN_CTRLMODE_XL_TDC_MASK | + CAN_CTRLMODE_XL_TMS); =20 /* clear bits to be modified and copy the flag values */ priv->ctrlmode &=3D ~cm->mask; @@ -404,7 +449,8 @@ static int can_dbt_changelink(struct net_device *dev, s= truct nlattr *data[], if (data[IFLA_CAN_CTRLMODE]) { struct can_ctrlmode *cm =3D nla_data(data[IFLA_CAN_CTRLMODE]); =20 - need_tdc_calc =3D !(cm->mask & tdc_mask); + if (fd || !(priv->ctrlmode & CAN_CTRLMODE_XL_TMS)) + need_tdc_calc =3D !(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/netl= ink.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 ca= lculates 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 */ =20 /* * CAN device statistics --=20 2.51.0 From nobody Mon Feb 9 04:44:37 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 9084B346777; Tue, 21 Oct 2025 15:47:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061679; cv=none; b=PrhFVoR8oRBLd2M9HyFXg6MOgeld96X+/Vk3Rl1K7R+AEMrwL3YJ1zazt5yNsCdrhV/kvjzLsN5NXlRRciYl4x73txuDx18JXUFf/E5l8ZXiUDBk22CNMCPrXPcJOQZWE4xQi8oYhWM0zOyhhcTbCo9zmwwwKG/490AuxyW9J+A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061679; c=relaxed/simple; bh=98gYOgiiHJ0nKbOHOeoQpgkidZg0DRmEDM+Th+DWzcM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jcjFKUbj/Pd6n1kJj40loGlTmpFYSbMx6yi+uL2kMCpGXa40/JBGptkMZNSEL4hk2x4IgHwsaq5xVflnULG/l0p4jJvtqQlE/kQPG+PE+8o/1X+ExIYnfrUQPmuh+AiFQ7ZPJvsc7ED3x90/t+4yfn/9db2VDFJwjKqsPVBmaXI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Fv9gMyIn; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Fv9gMyIn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D2262C4CEF1; Tue, 21 Oct 2025 15:47:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761061679; bh=98gYOgiiHJ0nKbOHOeoQpgkidZg0DRmEDM+Th+DWzcM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Fv9gMyInBRvVirCn/sd9GLcmIimu3h86EHdK1zk31uaRmNPEyAKcvpNkzoMTQn1mB 8LBeQJGYQJTDGR1s2/qo6jrQs5vNGlh4S8KTntAZUs8uySzYvC+5gzhvQrVMihaFvP +lribjxFfj2ySsGcr/Y6dJB6/yB0ycBteY3Nmrqwo6+C/GA1KBKD9f9R+dE9nO5A9R 2lDDeduMxJiOvW3j4dyboS0jypqnQc11bS2Cf7lPlwjLeO+B92jKiQ2MruVvR5ZMET feHESJ7XOHLBfq3LR/5fHGZL7GkZA6bt5ljbhxggpLO4u5AUyr7L+XjdaXiEYyb6qw qu5oWsB8VIRPQ== From: Vincent Mailhol Date: Tue, 21 Oct 2025 17:47:06 +0200 Subject: [PATCH v2 06/10] can: netlink: add CAN_CTRLMODE_XL_ERR_SIGNAL 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: <20251021-canxl-netlink-v2-6-8b8f58257ab6@kernel.org> References: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> In-Reply-To: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> To: Marc Kleine-Budde , Oliver Hartkopp Cc: Vincent Mailhol , =?utf-8?q?St=C3=A9phane_Grosjean?= , Robert Nawrath , Minh Le , Duy Nguyen , linux-can@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=5152; i=mailhol@kernel.org; h=from:subject:message-id; bh=98gYOgiiHJ0nKbOHOeoQpgkidZg0DRmEDM+Th+DWzcM=; b=owGbwMvMwCV2McXO4Xp97WbG02pJDBnfVwtJGbxb7+9ofaNjueTtnjdVoudW1lbzFcQ82NHGu y1SQkq4o5SFQYyLQVZMkWVZOSe3Qkehd9ihv5Ywc1iZQIYwcHEKwEQ4PBj+OzhYX5/sLXPn4D8/ BqOTVldq5u1abP+tjk2nXv7RmeC9eowMZ3Ujz3N8nrxwb8vCZbHO90K010uc4uD8IqoxdfmSxEv WjAA= X-Developer-Key: i=mailhol@kernel.org; a=openpgp; fpr=ED8F700574E67F20E574E8E2AB5FEB886DBB99C2 Classical CAN and CAN FD must generate error frames on the CAN bus when detecting a protocol violation. CAN XL's error signaling is different and works as follows: - In interoperability mode (both FD and XL), error signaling must be on. - When operating a CAN controller in CAN XL only mode but with TMS off, the user can decide whether the error signalling is enabled or disabled. - On the contrary, when using TMS, error signalling must be off. Introduce the new CAN_CTRLMODE_XL_ERR_SIGNAL control mode. This new option is only made available for CAN XL, so despite the error signalling being always on for Classical CAN and CAN FD, forbid the use of this flag when CAN XL is off. If the user provides the error signalling flag, check its validity. If the flag is omitted, activate error signalling by default whenever possible. This is summarized in below table: CAN_CTRLMODE_XL_ERR_SIGNAL ------------------------------------------- CC/FD option not available CC/FD/XL on XL TMS off configurable (default on) XL TMS on off Suggested-by: Oliver Hartkopp Link: https://lore.kernel.org/linux-can/20250527195625.65252-9-socketcan@ha= rtkopp.net/ Signed-off-by: Vincent Mailhol Reviewed-by: Oliver Hartkopp --- drivers/net/can/dev/dev.c | 2 ++ drivers/net/can/dev/netlink.c | 29 +++++++++++++++++++++++++++-- include/uapi/linux/can/netlink.h | 1 + 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c index 1de5babcc4f3..0c16d0174f7f 100644 --- a/drivers/net/can/dev/dev.c +++ b/drivers/net/can/dev/dev.c @@ -125,6 +125,8 @@ const char *can_get_ctrlmode_str(u32 ctrlmode) return "xl-tdc-manual"; case CAN_CTRLMODE_XL_TMS: return "xl-tms"; + case CAN_CTRLMODE_XL_ERR_SIGNAL: + return "xl-error-signalling"; default: return ""; } diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c index 8afd2baa03cf..6126b191fea0 100644 --- a/drivers/net/can/dev/netlink.c +++ b/drivers/net/can/dev/netlink.c @@ -191,7 +191,8 @@ static int can_validate_xl_flags(struct netlink_ext_ack= *extack, } if (masked_flags & CAN_CTRLMODE_XL_TMS) { const u32 tms_conflicts_mask =3D CAN_CTRLMODE_FD | - CAN_CTRLMODE_XL_TDC_MASK; + CAN_CTRLMODE_XL_TDC_MASK | + CAN_CTRLMODE_XL_ERR_SIGNAL; u32 tms_conflicts =3D masked_flags & tms_conflicts_mask; =20 if (tms_conflicts) { @@ -201,11 +202,23 @@ static int can_validate_xl_flags(struct netlink_ext_a= ck *extack, return -EOPNOTSUPP; } } + if ((masked_flags & CAN_CTRLMODE_FD) && + (mask & CAN_CTRLMODE_XL_ERR_SIGNAL) && + !(masked_flags & CAN_CTRLMODE_XL_ERR_SIGNAL)) { + NL_SET_ERR_MSG(extack, + "When using both CAN FD and XL, error signalling must be on"); + return -EOPNOTSUPP; + } } else { if (mask & CAN_CTRLMODE_XL_TMS) { NL_SET_ERR_MSG(extack, "TMS requires CAN XL"); return -EOPNOTSUPP; } + if (mask & CAN_CTRLMODE_XL_ERR_SIGNAL) { + NL_SET_ERR_MSG(extack, + "Error signalling is only configurable with CAN XL"); + return -EOPNOTSUPP; + } } =20 return 0; @@ -310,6 +323,11 @@ static int can_ctrlmode_changelink(struct net_device *= dev, "TMS can not be activated while CAN FD is on"); return -EOPNOTSUPP; } + if (deactivated & CAN_CTRLMODE_XL_ERR_SIGNAL) { + NL_SET_ERR_MSG(extack, + "Error signalling can not be deactivated while CAN FD is on"); + return -EOPNOTSUPP; + } } =20 /* If a top dependency flag is provided, reset all its dependencies */ @@ -317,12 +335,19 @@ static int can_ctrlmode_changelink(struct net_device = *dev, priv->ctrlmode &=3D ~CAN_CTRLMODE_FD_TDC_MASK; if (cm->mask & CAN_CTRLMODE_XL) priv->ctrlmode &=3D ~(CAN_CTRLMODE_XL_TDC_MASK | - CAN_CTRLMODE_XL_TMS); + CAN_CTRLMODE_XL_TMS | + CAN_CTRLMODE_XL_ERR_SIGNAL); =20 /* clear bits to be modified and copy the flag values */ priv->ctrlmode &=3D ~cm->mask; priv->ctrlmode |=3D maskedflags; =20 + /* If omitted, set error signalling on if possible */ + if ((maskedflags & CAN_CTRLMODE_XL) && + !(cm->mask & CAN_CTRLMODE_XL_ERR_SIGNAL) && + !(priv->ctrlmode & CAN_CTRLMODE_XL_TMS)) + priv->ctrlmode |=3D CAN_CTRLMODE_XL_ERR_SIGNAL; + /* Wipe potential leftovers from previous CAN FD/XL config */ if (!(priv->ctrlmode & CAN_CTRLMODE_FD)) { memset(&priv->fd.data_bittiming, 0, diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netl= ink.h index ebafb091d80f..30d446921dc4 100644 --- a/include/uapi/linux/can/netlink.h +++ b/include/uapi/linux/can/netlink.h @@ -108,6 +108,7 @@ struct can_ctrlmode { #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 */ #define CAN_CTRLMODE_XL_TMS 0x8000 /* Transceiver Mode Switching */ +#define CAN_CTRLMODE_XL_ERR_SIGNAL 0x10000 /* XL error signalling */ =20 /* * CAN device statistics --=20 2.51.0 From nobody Mon Feb 9 04:44:37 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 0A01D34679C; Tue, 21 Oct 2025 15:48:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061681; cv=none; b=hds0tIjsS7VXL7O6yom5RVbikkGeY+f5iQnF0gbYsAsdJES5HYwpHfdiTd5Guk2RcdRbmHX4opoize3d/ZKcphFJgZ02lcGvoNn7M6a6ZMtZuMVcmVg7TpPXAssklA4HOO0Vr7v40sbpYkYEzTu1RDSN7c1vCATBXmgGtQ9r58Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061681; c=relaxed/simple; bh=jqPIZ4JH4079BiKqtXFd7rgeu/2WGWT6odzHltrlX/4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fTjgLPN0JAwUa9YUK1sQ3hbzQt17Db3Yd1o0QRL4YBIa11ZD+W7dn7HA6WQl26KFILHfzMlOtFB6uMvXq/qYI4xQxA0Gztvw0D1nsPiQc3GIKO2lJZzoKQG8qUAioNMylCNzL3mM/LodbG3Bc1+eb/HxMAIhE/vg/y8gXNJeVtw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pJpUFmW0; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="pJpUFmW0" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6DC0DC116D0; Tue, 21 Oct 2025 15:47:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761061680; bh=jqPIZ4JH4079BiKqtXFd7rgeu/2WGWT6odzHltrlX/4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=pJpUFmW0SFdbVFEa0RuMhPM6JN0LgatD5u0bvcYNagfYMVpjvVSQt1LPU66YDGrhd aZ2vwg//vSbdsYOrurB+JPUj/6VHwE/oBMH87IeqjOpVapBGObVEDdAWxb/QFw3FTJ EqqvzmwO0UxGNlcqP5EnrAC8/y4S7xcWctrlf9TaeHfPjrWUFkq8vcyODO5l4KpkiE iPNukQaCsN34bJp/vaBeLUwP6+b67sBjvvYqkFSIEMYaHrGLLu/tjdccB57sI6/eex VwnAba9Ko+WPDexGsJC13JKHbSIVDBPo/KLNiPDKX9KNWW22FkyxK57/Z0JRyYhs/R CVoCWrzAcDNjA== From: Vincent Mailhol Date: Tue, 21 Oct 2025 17:47:07 +0200 Subject: [PATCH v2 07/10] can: bittiming: add PWM parameters 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: <20251021-canxl-netlink-v2-7-8b8f58257ab6@kernel.org> References: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> In-Reply-To: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> To: Marc Kleine-Budde , Oliver Hartkopp Cc: Vincent Mailhol , =?utf-8?q?St=C3=A9phane_Grosjean?= , Robert Nawrath , Minh Le , Duy Nguyen , linux-can@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=3173; i=mailhol@kernel.org; h=from:subject:message-id; bh=jqPIZ4JH4079BiKqtXFd7rgeu/2WGWT6odzHltrlX/4=; b=owGbwMvMwCV2McXO4Xp97WbG02pJDBnfV4vO8mZa7LRmYyjrUd+zBu4Pjrbc6hRfazk1OnSVx +fsgm/POkpZGMS4GGTFFFmWlXNyK3QUeocd+msJM4eVCWQIAxenAEyEaw7D/5istqCytKn5sxoO nZuYt8PsvZtmm0bJzwYjhflvzC5Ib2P4Z3PV+7zcCdOgOeumbF6z98hync504RKzhZUb52o7fAl v4wAA X-Developer-Key: i=mailhol@kernel.org; a=openpgp; fpr=ED8F700574E67F20E574E8E2AB5FEB886DBB99C2 In CAN XL, higher data bit rates require the CAN transceiver to switch its operation mode to use Pulse-Width Modulation (PWM) transmission mode instead of the classic dominant/recessive transmission mode. The PWM parameters are: - PWMS: pulse width modulation short phase - PWML: pulse width modulation long phase - PWMO: pulse width modulation offset CiA 612-2 specifies PWMS and PWML to be at least 1 (arguably, PWML shall be at least 2 to respect the PWMS < PWML rule). PWMO's minimum is expected to always be zero. It is added more for consistency than anything else. Add struct can_pwm_const so that the different devices can provide their minimum and maximum values. When TMS is on, the runtime PWMS, PWML and PWMO are needed (either calculated or provided by the user): add struct can_pwm to store these. TDC and PWM can not be used at the same time (TDC can only be used when TMS is off and PWM only when TMS is on). struct can_pwm is thus put together with struct can_tdc inside a union to save some space. The netlink logic will be added in an upcoming change. Signed-off-by: Vincent Mailhol --- include/linux/can/bittiming.h | 41 +++++++++++++++++++++++++++++++++++++++= -- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/include/linux/can/bittiming.h b/include/linux/can/bittiming.h index b6cd2476ffd7..967d76689c4f 100644 --- a/include/linux/can/bittiming.h +++ b/include/linux/can/bittiming.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (c) 2020 Pengutronix, Marc Kleine-Budde - * Copyright (c) 2021 Vincent Mailhol + * Copyright (c) 2021-2025 Vincent Mailhol */ =20 #ifndef _CAN_BITTIMING_H @@ -120,11 +120,48 @@ struct can_tdc_const { u32 tdcf_max; }; =20 +/* + * struct can_pwm - CAN Pulse-Width Modulation (PWM) parameters + * + * @pwms: pulse width modulation short phase + * @pwml: pulse width modulation long phase + * @pwmo: pulse width modulation offset + */ +struct can_pwm { + u32 pwms; + u32 pwml; + u32 pwmo; +}; + +/* + * struct can_pwm - CAN hardware-dependent constants for Pulse-Width + * Modulation (PWM) + * + * @pwms_min: PWM short phase minimum value. Must be at least 1. + * @pwms_max: PWM short phase maximum value + * @pwml_min: PWM long phase minimum value. Must be at least 1. + * @pwml_max: PWM long phase maximum value + * @pwmo_min: PWM offset phase minimum value + * @pwmo_max: PWM offset phase maximum value + */ +struct can_pwm_const { + u32 pwms_min; + u32 pwms_max; + u32 pwml_min; + u32 pwml_max; + u32 pwmo_min; + u32 pwmo_max; +}; + struct data_bittiming_params { const struct can_bittiming_const *data_bittiming_const; struct can_bittiming data_bittiming; const struct can_tdc_const *tdc_const; - struct can_tdc tdc; + const struct can_pwm_const *pwm_const; + union { + struct can_tdc tdc; + struct can_pwm pwm; + }; const u32 *data_bitrate_const; unsigned int data_bitrate_const_cnt; int (*do_set_data_bittiming)(struct net_device *dev); --=20 2.51.0 From nobody Mon Feb 9 04:44:37 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 B1882347FC6; Tue, 21 Oct 2025 15:48:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061682; cv=none; b=JnE+3nmwKGJZcE1/6JFVu2Kahx8YdSlNIeegbGHlsR3cqBzROSEvvvJgt6VtqHsaDZY9pBaL0cvHRJlWKUf2KLGRtEvIJ+TrUK+r3LyI/L3tbJ1DrIWz4DmygIrSUgBVtr600dVzAQ2VQRFrb6eBK0y/ifn6GVfjTOHEbAP+j2A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061682; c=relaxed/simple; bh=wgyZ2odVA967H9e2n7Zm+24TtnChkr4ICKvWxS8dJ4w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=h8JO1HeJmaXtlzqKsmQOarFj7lrs13bAjag8fcSnlURvwVa5YAXUq9G++JPZ42XSYd0yIzHs153z25FCnfMTEmy0VQxKh6Hz5Heo0QuDuD3ZOgVxuVg9TKln5/Gbws6cyVL1OccqrwDdAMaxh2o/5yBoADDQjD3ATGtwe4o9E0A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=A4mtj3Wv; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="A4mtj3Wv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 09E4AC4CEF1; Tue, 21 Oct 2025 15:48:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761061682; bh=wgyZ2odVA967H9e2n7Zm+24TtnChkr4ICKvWxS8dJ4w=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=A4mtj3WvdBPjLfHsF68+78UlIieSp5rcTAMo5stNwvfRxWnbpWPGCcAxmlM/+0wwo muvJQ1iDa1ienju8XIGfn1o/z487fnZfrKdc362sc0nGHxWdPLlO2CQJrgmQ5Qel0c 0wUOBdCxpMmz2oAM2lS7qY4pf9qAdZsDvQFYE/LhR5eK7Ti62pUIL+RUCyPwogbziD KBD9MOnYry5tPjsBb7T3WEMgx2eswlgvxh0Sc4hzq6bfpEZYDpzgv8cuQ7hj6vbG+K dIG6kNkOmjfXC38dqmPpBj990VQcW+WvSQCkK2YZK0KbtS29irKvbKhxP1teTyRPOW QsorVfOMYcyJQ== From: Vincent Mailhol Date: Tue, 21 Oct 2025 17:47:08 +0200 Subject: [PATCH v2 08/10] can: bittiming: add PWM validation 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: <20251021-canxl-netlink-v2-8-8b8f58257ab6@kernel.org> References: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> In-Reply-To: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> To: Marc Kleine-Budde , Oliver Hartkopp Cc: Vincent Mailhol , =?utf-8?q?St=C3=A9phane_Grosjean?= , Robert Nawrath , Minh Le , Duy Nguyen , linux-can@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=5186; i=mailhol@kernel.org; h=from:subject:message-id; bh=wgyZ2odVA967H9e2n7Zm+24TtnChkr4ICKvWxS8dJ4w=; b=owGbwMvMwCV2McXO4Xp97WbG02pJDBnfV0tyB39KXbOKgTG/d4+wWHzSXY0nWlOkpgRVZrp1l 5cvYWToKGVhEONikBVTZFlWzsmt0FHoHXboryXMHFYmkCEMXJwCMJEpsYwMb3I+LmDSa62UXm8p /TrkYtKP9Rm7WhNlDgofv7fEIsHkLyPDKzPvTQf2caddfDvB8vLmj2weuwOjlgfY6azf+HBNSPR CBgA= X-Developer-Key: i=mailhol@kernel.org; a=openpgp; fpr=ED8F700574E67F20E574E8E2AB5FEB886DBB99C2 Add can_validate_pwm() to validate the values pwms, pwml and pwml. Error messages are added to each of the checks to inform the user on what went wrong. Refer to those error messages to understand the validation logic. The boundary values CAN_PWM_DECODE_NS (the transceiver minimum decoding margin) and CAN_PWM_NS_MAX (the maximum PWM symbol duration) are hardcoded for the moment. Note that a transceiver capable of bitrates higher than 20 Mbps may be able to handle a CAN_PWM_DECODE_NS below 5 ns. If such transceivers become commercially available, this code could be revisited to make this parameter configurable. For now, leave it static. Signed-off-by: Vincent Mailhol --- drivers/net/can/dev/bittiming.c | 63 +++++++++++++++++++++++++++++++++++++= ++++ include/linux/can/bittiming.h | 22 ++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/drivers/net/can/dev/bittiming.c b/drivers/net/can/dev/bittimin= g.c index 0b93900b1dfa..730b1b254460 100644 --- a/drivers/net/can/dev/bittiming.c +++ b/drivers/net/can/dev/bittiming.c @@ -2,6 +2,7 @@ /* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix * Copyright (C) 2006 Andrey Volkov, Varma Electronics * Copyright (C) 2008-2009 Wolfgang Grandegger + * Copyright (c) 2025 Vincent Mailhol */ =20 #include @@ -151,3 +152,65 @@ int can_get_bittiming(const struct net_device *dev, st= ruct can_bittiming *bt, =20 return -EINVAL; } + +int can_validate_pwm_bittiming(const struct net_device *dev, + const struct can_pwm *pwm, + struct netlink_ext_ack *extack) +{ + const struct can_priv *priv =3D netdev_priv(dev); + u32 xl_bit_time_tqmin =3D can_bit_time_tqmin(&priv->xl.data_bittiming); + u32 nom_bit_time_tqmin =3D can_bit_time_tqmin(&priv->bittiming); + u32 pwms_ns =3D can_tqmin_to_ns(pwm->pwms, priv->clock.freq); + u32 pwml_ns =3D can_tqmin_to_ns(pwm->pwml, priv->clock.freq); + + if (pwms_ns + pwml_ns > CAN_PWM_NS_MAX) { + NL_SET_ERR_MSG_FMT(extack, + "The PWM symbol duration: %u ns may no exceed %u ns", + pwms_ns + pwml_ns, CAN_PWM_NS_MAX); + return -EINVAL; + } + + if (pwms_ns < CAN_PWM_DECODE_NS) { + NL_SET_ERR_MSG_FMT(extack, + "PWMS: %u ns shall be at least %u ns", + pwms_ns, CAN_PWM_DECODE_NS); + return -EINVAL; + } + + if (pwm->pwms >=3D pwm->pwml) { + NL_SET_ERR_MSG_FMT(extack, + "PWMS: %u tqmin shall be smaller than PWML: %u tqmin", + pwm->pwms, pwm->pwml); + return -EINVAL; + } + + if (pwml_ns - pwms_ns < 2 * CAN_PWM_DECODE_NS) { + NL_SET_ERR_MSG_FMT(extack, + "At least %u ns shall separate PWMS: %u ns from PMWL: %u ns", + 2 * CAN_PWM_DECODE_NS, pwms_ns, pwml_ns); + return -EINVAL; + } + + if (xl_bit_time_tqmin % (pwm->pwms + pwm->pwml) !=3D 0) { + NL_SET_ERR_MSG_FMT(extack, + "PWM duration: %u tqmin does not divide XL's bit time: %u tqmin", + pwm->pwms + pwm->pwml, xl_bit_time_tqmin); + return -EINVAL; + } + + if (pwm->pwmo >=3D pwm->pwms + pwm->pwml) { + NL_SET_ERR_MSG_FMT(extack, + "PWMO: %u tqmin can not be greater than PWMS + PWML: %u tqmin", + pwm->pwmo, pwm->pwms + pwm->pwml); + return -EINVAL; + } + + if (nom_bit_time_tqmin % (pwm->pwms + pwm->pwml) !=3D pwm->pwmo) { + NL_SET_ERR_MSG_FMT(extack, + "Can not assemble nominal bit time: %u tqmin out of PWMS + PMWL and= PWMO", + nom_bit_time_tqmin); + return -EINVAL; + } + + return 0; +} diff --git a/include/linux/can/bittiming.h b/include/linux/can/bittiming.h index 967d76689c4f..2504fafc72e4 100644 --- a/include/linux/can/bittiming.h +++ b/include/linux/can/bittiming.h @@ -87,6 +87,11 @@ struct can_tdc { u32 tdcf; }; =20 +/* The transceiver decoding margin corresponds to t_Decode in ISO 11898-2 = */ +#define CAN_PWM_DECODE_NS 5 +/* Maximum PWM symbol duration. Corresponds to t_SymbolNom_MAX - t_Decode = */ +#define CAN_PWM_NS_MAX (205 - CAN_PWM_DECODE_NS) + /* * struct can_tdc_const - CAN hardware-dependent constant for * Transmission Delay Compensation @@ -203,6 +208,10 @@ int can_get_bittiming(const struct net_device *dev, st= ruct can_bittiming *bt, const unsigned int bitrate_const_cnt, struct netlink_ext_ack *extack); =20 +int can_validate_pwm_bittiming(const struct net_device *dev, + const struct can_pwm *pwm, + struct netlink_ext_ack *extack); + /* * can_get_relative_tdco() - TDCO relative to the sample point * @@ -245,4 +254,17 @@ static inline unsigned int can_bit_time(const struct c= an_bittiming *bt) return CAN_SYNC_SEG + bt->prop_seg + bt->phase_seg1 + bt->phase_seg2; } =20 +/* Duration of one bit in minimum time quantum */ +static inline unsigned int can_bit_time_tqmin(const struct can_bittiming *= bt) +{ + return can_bit_time(bt) * bt->brp; +} + +/* Convert a duration from minimum a minimum time quantum to nano seconds = */ +static inline u32 can_tqmin_to_ns(u32 tqmin, u32 clock_freq) +{ + return DIV_U64_ROUND_CLOSEST(mul_u32_u32(tqmin, NSEC_PER_SEC), + clock_freq); +} + #endif /* !_CAN_BITTIMING_H */ --=20 2.51.0 From nobody Mon Feb 9 04:44:37 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 533AF34679C; Tue, 21 Oct 2025 15:48:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061685; cv=none; b=bH5BlXRrLHoC/cYcQ+wf+UJWBqw5MzL9EavoHskdOpy1zDc2sGWVGUEIEZsJI2zPZmrnebITPpnQ4jUjtARNZqUAc6RzP/u90WBl9sIb0kTN1+TG4scWXDbM3s16F41aepS5MMF70eU6+M2d1oXmMZ2a4kV/gd+yiEImVf3pRMU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061685; c=relaxed/simple; bh=mVFqzFxcb+boKPfg1i+RH9Yu/gUe3nKXtP+IWXh80W4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WKi2wlUvkKg6VSDomEgNt5eFUgIsZB80eeTYN4XoyVgYho+uh1WdSPTmcLd/lUpOZClxx/asp+6X3JmPrVF6ugcRpxRPVtbNHqk4ZQQ1xyQhbTNgwEb9gphTi4EPmacONNHhhxaekaP4/xSrwdxteOG8TNxakr6TkodZbAR6Qvw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=P6eBMCot; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="P6eBMCot" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 98EFDC4CEF5; Tue, 21 Oct 2025 15:48:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761061683; bh=mVFqzFxcb+boKPfg1i+RH9Yu/gUe3nKXtP+IWXh80W4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=P6eBMCotcEEqj+2CnwMbes843BJksVZLP1qUVDCkrqbozxfHYy3lPEAwTzdPn/Rcx lH18voE6l5nLS6Ss7qeL+aP+tK6KhoAIj6IPPiQ498ZOUgsq3SX86A3+L8KZViWK0e mp177WhticlSY6r5sbZUvRdYONWzok45t7N0nDZ9+lgZeiwfoQZL7UMKZFptTIAWtF nfiK+AxQ0ECI6jagjoU9Qki2wAcZWAjBZfOT8bJngBTMgDVHBxWOIJVysHvf9F9eFN n6LN15I0R2UXe7Ed0Mt5tpGlHFSHLcadRo+xzUzGzgnvq1K4D+g30w2YB9TarZYkGM fbKzwpAXKR4lQ== From: Vincent Mailhol Date: Tue, 21 Oct 2025 17:47:09 +0200 Subject: [PATCH v2 09/10] can: calc_bittiming: add PWM calculation 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: <20251021-canxl-netlink-v2-9-8b8f58257ab6@kernel.org> References: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> In-Reply-To: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> To: Marc Kleine-Budde , Oliver Hartkopp Cc: Vincent Mailhol , =?utf-8?q?St=C3=A9phane_Grosjean?= , Robert Nawrath , Minh Le , Duy Nguyen , linux-can@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=4177; i=mailhol@kernel.org; h=from:subject:message-id; bh=mVFqzFxcb+boKPfg1i+RH9Yu/gUe3nKXtP+IWXh80W4=; b=owGbwMvMwCV2McXO4Xp97WbG02pJDBnfV8sYTBHr9JnGLxkWu+Ztip72gxlcV/n8VIs15W4xu fss8fnXUcrCIMbFICumyLKsnJNboaPQO+zQX0uYOaxMIEMYuDgFYCKXdzD805ZM3N935V72luji 5ZMsDkZlMueIuhZMvpot0V355I3OTYa/EudT/NnvHIkuPSZvk1ypbHjInTcwd4qa1V5TRYGX5+4 zAgA= X-Developer-Key: i=mailhol@kernel.org; a=openpgp; fpr=ED8F700574E67F20E574E8E2AB5FEB886DBB99C2 Perform the PWM calculation according to CiA recommendations. Note that for databitrates greater than 5 MBPS, tqmin is less than CAN_PWM_NS_MAX (which is defined to 200 nano seconds), consequently, the result of the division: DIV_ROUND_UP(xl_ns, CAN_PWM_NS_MAX) is one and thus the for loop automatically stops on the first iteration giving a single PWM symbol per bit as expected. Because of that, there is no actual need for a separate conditional branch for when the databitrate is greater than 5 MBPS. Signed-off-by: Vincent Mailhol --- Changelog: v1 -> v2: - Add a return statement to can_calc_tdco() when CONFIG_CAN_CALC_BITTIMING is not set. This fixes a warning as reported by the kernel test robot: Link: https://lore.kernel.org/linux-can/202510140553.qo3f0I9s-lkp@i= ntel.com/ While at it, add an error message. --- drivers/net/can/dev/calc_bittiming.c | 36 ++++++++++++++++++++++++++++++++= ++++ include/linux/can/bittiming.h | 10 ++++++++++ 2 files changed, 46 insertions(+) diff --git a/drivers/net/can/dev/calc_bittiming.c b/drivers/net/can/dev/cal= c_bittiming.c index 394d6974f481..268ec6fa7c49 100644 --- a/drivers/net/can/dev/calc_bittiming.c +++ b/drivers/net/can/dev/calc_bittiming.c @@ -2,6 +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-2025 Vincent Mailhol */ =20 #include @@ -198,3 +199,38 @@ void can_calc_tdco(struct can_tdc *tdc, const struct c= an_tdc_const *tdc_const, *ctrlmode |=3D tdc_auto; } } + +int can_calc_pwm(struct net_device *dev, struct netlink_ext_ack *extack) +{ + struct can_priv *priv =3D netdev_priv(dev); + const struct can_pwm_const *pwm_const =3D priv->xl.pwm_const; + struct can_pwm *pwm =3D &priv->xl.pwm; + u32 xl_tqmin =3D can_bit_time_tqmin(&priv->xl.data_bittiming); + u32 xl_ns =3D can_tqmin_to_ns(xl_tqmin, priv->clock.freq); + u32 nom_tqmin =3D can_bit_time_tqmin(&priv->bittiming); + int pwm_per_bit_max =3D xl_tqmin / (pwm_const->pwms_min + pwm_const->pwml= _min); + int pwm_per_bit; + u32 pwm_tqmin; + + /* For 5 MB/s databitrate or greater, xl_ns < CAN_PWM_NS_MAX + * giving us a pwm_per_bit of 1 and the loop immediately breaks + */ + for (pwm_per_bit =3D DIV_ROUND_UP(xl_ns, CAN_PWM_NS_MAX); + pwm_per_bit <=3D pwm_per_bit_max; pwm_per_bit++) + if (xl_tqmin % pwm_per_bit =3D=3D 0) + break; + + if (pwm_per_bit > pwm_per_bit_max) { + NL_SET_ERR_MSG_FMT(extack, + "Can not divide the XL data phase's bit time: %u tqmin into multipl= e PWM symbols", + xl_tqmin); + return -EINVAL; + } + + pwm_tqmin =3D xl_tqmin / pwm_per_bit; + pwm->pwms =3D DIV_ROUND_UP_POW2(pwm_tqmin, 4); + pwm->pwml =3D pwm_tqmin - pwm->pwms; + pwm->pwmo =3D nom_tqmin % pwm_tqmin; + + return 0; +} diff --git a/include/linux/can/bittiming.h b/include/linux/can/bittiming.h index 2504fafc72e4..726d909e87ce 100644 --- a/include/linux/can/bittiming.h +++ b/include/linux/can/bittiming.h @@ -180,6 +180,8 @@ int can_calc_bittiming(const struct net_device *dev, st= ruct can_bittiming *bt, void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_co= nst, const struct can_bittiming *dbt, u32 tdc_mask, u32 *ctrlmode, u32 ctrlmode_supported); + +int can_calc_pwm(struct net_device *dev, struct netlink_ext_ack *extack); #else /* !CONFIG_CAN_CALC_BITTIMING */ static inline int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt, @@ -195,6 +197,14 @@ can_calc_tdco(struct can_tdc *tdc, const struct can_td= c_const *tdc_const, u32 tdc_mask, u32 *ctrlmode, u32 ctrlmode_supported) { } + +static inline int +can_calc_pwm(struct net_device *dev, struct netlink_ext_ack *extack) +{ + NL_SET_ERR_MSG(extack, + "bit-timing calculation not available: manually provide PWML and = PWMS\n"); + return -EINVAL; +} #endif /* CONFIG_CAN_CALC_BITTIMING */ =20 void can_sjw_set_default(struct can_bittiming *bt); --=20 2.51.0 From nobody Mon Feb 9 04:44:37 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 1028F3451C1; Tue, 21 Oct 2025 15:48:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061687; cv=none; b=sd+uU0HI5nVSKZZomYxGyq952mGMIhDGC8cQQpeuRJqd0Cprx6c+kja4YMZdrdNzxwmfB5k17DQ+kqsQJYQKFejSCms6fWMqrI+lPG5FuRWFF3xdMLC+B3easadJVlF/8NZKDaWs1JzDQp1wOagEheEgrNnrFCPy73Ff3IIQzyY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761061687; c=relaxed/simple; bh=gXYfP5X4tBU6CNSprVfgck0ziAcxe5xeelY9/xwNMx0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=m8dZczW+L2Ru5O3tCw225li1Xd86ZIQ+ByQlys0htEb1iIhsL0iaNN+y0i3PwkVtiXGiSlEC00fAf0e2e1JE07KGIWcS4K+6KXupFtpqp8G3i7DRqrgX3+4v9jFqa+yYPv8O+MKlWWCnerZqU6WTlJSSqeIsBrWVTMtnQoTkWCE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FjYdPy9l; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FjYdPy9l" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 33923C113D0; Tue, 21 Oct 2025 15:48:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761061685; bh=gXYfP5X4tBU6CNSprVfgck0ziAcxe5xeelY9/xwNMx0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=FjYdPy9l0n631y8HIRypnAgIJ9qM0R0m05+EZzsg05jibcG48mPKGmrnyq4jmM60e 6a+kk8GBkJgjLIHD40MjwKYcmKP276IsK03telJBLl8u20LA4Utxgy+OSWZqUcwUf3 GxCw7AYvk48n+A8gc7Y+39MEvtJCrGM7nmQEVMFdvl3DJAhNJ8GlIrc6OHx4cRHZYR 6ykBs2sIj1e3Cn2wZpUSaPVoprz5c9bAokCAbXHXT7ncYUj1H978SV+WZ4R0qPrJPa on2ACGRcCpwS8MZizlzXPmVzDpEc31kBMfnGoVe8LJgRxM4FqPppiIIssIxt1cZR0U CoHSAPQTmZtLw== From: Vincent Mailhol Date: Tue, 21 Oct 2025 17:47:10 +0200 Subject: [PATCH v2 10/10] can: netlink: add PWM netlink interface 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: <20251021-canxl-netlink-v2-10-8b8f58257ab6@kernel.org> References: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> In-Reply-To: <20251021-canxl-netlink-v2-0-8b8f58257ab6@kernel.org> To: Marc Kleine-Budde , Oliver Hartkopp Cc: Vincent Mailhol , =?utf-8?q?St=C3=A9phane_Grosjean?= , Robert Nawrath , Minh Le , Duy Nguyen , linux-can@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=11959; i=mailhol@kernel.org; h=from:subject:message-id; bh=gXYfP5X4tBU6CNSprVfgck0ziAcxe5xeelY9/xwNMx0=; b=owGbwMvMwCV2McXO4Xp97WbG02pJDBnfV8t7lQgolB+uP3bo+ga/ry2C3pU+31niDere+Kkos bwVmDipo5SFQYyLQVZMkWVZOSe3Qkehd9ihv5Ywc1iZQIYwcHEKwEQcDBj+1+559mDP29nLeCcE BcpdLtDjP/giKs/qyQ13F29rXrmuEEaGSeG+R7/zLVNki3FtYJXkYrkU9U5tYvbrC29VzZ961yr wAQA= X-Developer-Key: i=mailhol@kernel.org; a=openpgp; fpr=ED8F700574E67F20E574E8E2AB5FEB886DBB99C2 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, define 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. IFLA_CAN_PWM_PWM*_MIN and IFLA_CAN_PWM_PWM*_MAX define the range of allowed values and will match the value statically configured by the device in struct can_pwm_const. IFLA_CAN_PWM_PWM* match the runtime values stored in struct can_pwm. Those parameters may only be configured when the tms mode is on. If the PWMS, PWML and PWMO parameters are provided, check that all the needed parameters are present using can_validate_pwm(), then check their value using can_validate_pwm_bittiming(). PWMO defaults to zero if omitted. Otherwise, if CAN_CTRLMODE_XL_TMS is true but none of the PWM parameters are provided, calculate them using can_calc_pwm(). Signed-off-by: Vincent Mailhol --- drivers/net/can/dev/netlink.c | 192 +++++++++++++++++++++++++++++++++++= +++- include/uapi/linux/can/netlink.h | 25 +++++ 2 files changed, 215 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c index 6126b191fea0..7f6d853fc550 100644 --- a/drivers/net/can/dev/netlink.c +++ b/drivers/net/can/dev/netlink.c @@ -25,6 +25,7 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + = 1] =3D { [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 }, + [IFLA_CAN_XL_PWM] =3D { .type =3D NLA_NESTED }, }; =20 static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] =3D { @@ -39,6 +40,18 @@ static const struct nla_policy can_tdc_policy[IFLA_CAN_T= DC_MAX + 1] =3D { [IFLA_CAN_TDC_TDCF] =3D { .type =3D NLA_U32 }, }; =20 +static const struct nla_policy can_pwm_policy[IFLA_CAN_PWM_MAX + 1] =3D { + [IFLA_CAN_PWM_PWMS_MIN] =3D { .type =3D NLA_U32 }, + [IFLA_CAN_PWM_PWMS_MAX] =3D { .type =3D NLA_U32 }, + [IFLA_CAN_PWM_PWML_MIN] =3D { .type =3D NLA_U32 }, + [IFLA_CAN_PWM_PWML_MAX] =3D { .type =3D NLA_U32 }, + [IFLA_CAN_PWM_PWMO_MIN] =3D { .type =3D NLA_U32 }, + [IFLA_CAN_PWM_PWMO_MAX] =3D { .type =3D NLA_U32 }, + [IFLA_CAN_PWM_PWMS] =3D { .type =3D NLA_U32 }, + [IFLA_CAN_PWM_PWML] =3D { .type =3D NLA_U32 }, + [IFLA_CAN_PWM_PWMO] =3D { .type =3D NLA_U32 }, +}; + static int can_validate_bittiming(struct nlattr *data[], struct netlink_ext_ack *extack, int ifla_can_bittiming) @@ -119,6 +132,40 @@ static int can_validate_tdc(struct nlattr *data_tdc, return 0; } =20 +static int can_validate_pwm(struct nlattr *data[], + struct netlink_ext_ack *extack, u32 flags) +{ + struct nlattr *tb_pwm[IFLA_CAN_PWM_MAX + 1]; + int err; + + if (!data[IFLA_CAN_XL_PWM]) + return 0; + + if (!(flags & CAN_CTRLMODE_XL_TMS)) { + NL_SET_ERR_MSG(extack, "PWM requires TMS"); + return -EOPNOTSUPP; + } + + err =3D nla_parse_nested(tb_pwm, IFLA_CAN_PWM_MAX, data[IFLA_CAN_XL_PWM], + can_pwm_policy, extack); + if (err) + return err; + + if (!tb_pwm[IFLA_CAN_PWM_PWMS] !=3D !tb_pwm[IFLA_CAN_PWM_PWML]) { + NL_SET_ERR_MSG(extack, + "Provide either both PWMS and PWML, or none for automic calculat= ion"); + return -EOPNOTSUPP; + } + + if (tb_pwm[IFLA_CAN_PWM_PWMO] && + (!tb_pwm[IFLA_CAN_PWM_PWMS] || !tb_pwm[IFLA_CAN_PWM_PWML])) { + NL_SET_ERR_MSG(extack, "PWMO requires both PWMS and PWML"); + return -EOPNOTSUPP; + } + + return 0; +} + static int can_validate_databittiming(struct nlattr *data[], struct netlink_ext_ack *extack, int ifla_can_data_bittiming, u32 flags) @@ -264,6 +311,10 @@ static int can_validate(struct nlattr *tb[], struct nl= attr *data[], if (err) return err; =20 + err =3D can_validate_pwm(data, extack, flags); + if (err) + return err; + return 0; } =20 @@ -360,6 +411,7 @@ static int can_ctrlmode_changelink(struct net_device *d= ev, sizeof(priv->fd.data_bittiming)); priv->ctrlmode &=3D ~CAN_CTRLMODE_XL_TDC_MASK; memset(&priv->xl.tdc, 0, sizeof(priv->xl.tdc)); + memset(&priv->xl.pwm, 0, sizeof(priv->xl.pwm)); } =20 can_set_default_mtu(dev); @@ -506,6 +558,76 @@ static int can_dbt_changelink(struct net_device *dev, = struct nlattr *data[], return 0; } =20 +static int can_pwm_changelink(struct net_device *dev, + const struct nlattr *pwm_nla, + struct netlink_ext_ack *extack) +{ + struct can_priv *priv =3D netdev_priv(dev); + const struct can_pwm_const *pwm_const =3D priv->xl.pwm_const; + struct nlattr *tb_pwm[IFLA_CAN_PWM_MAX + 1]; + struct can_pwm pwm =3D { 0 }; + int err; + + if (!(priv->ctrlmode & CAN_CTRLMODE_XL_TMS)) + return 0; + + if (!pwm_const) { + NL_SET_ERR_MSG(extack, "The device does not support PWM"); + return -EOPNOTSUPP; + } + + if (!pwm_nla) + return can_calc_pwm(dev, extack); + + err =3D nla_parse_nested(tb_pwm, IFLA_CAN_PWM_MAX, pwm_nla, + can_pwm_policy, extack); + if (err) + return err; + + if (tb_pwm[IFLA_CAN_PWM_PWMS]) { + pwm.pwms =3D nla_get_u32(tb_pwm[IFLA_CAN_PWM_PWMS]); + if (pwm.pwms < pwm_const->pwms_min || + pwm.pwms > pwm_const->pwms_max) { + NL_SET_ERR_MSG_FMT(extack, + "PWMS: %u tqmin is out of range: %u...%u", + pwm.pwms, pwm_const->pwms_min, + pwm_const->pwms_max); + return -EINVAL; + } + } + + if (tb_pwm[IFLA_CAN_PWM_PWML]) { + pwm.pwml =3D nla_get_u32(tb_pwm[IFLA_CAN_PWM_PWML]); + if (pwm.pwml < pwm_const->pwml_min || + pwm.pwml > pwm_const->pwml_max) { + NL_SET_ERR_MSG_FMT(extack, + "PWML: %u tqmin is out of range: %u...%u", + pwm.pwml, pwm_const->pwml_min, + pwm_const->pwml_max); + return -EINVAL; + } + } + + if (tb_pwm[IFLA_CAN_PWM_PWMO]) { + pwm.pwmo =3D nla_get_u32(tb_pwm[IFLA_CAN_PWM_PWMO]); + if (pwm.pwmo < pwm_const->pwmo_min || + pwm.pwmo > pwm_const->pwmo_max) { + NL_SET_ERR_MSG_FMT(extack, + "PWMO: %u tqmin is out of range: %u...%u", + pwm.pwmo, pwm_const->pwmo_min, + pwm_const->pwmo_max); + return -EINVAL; + } + } + + err =3D can_validate_pwm_bittiming(dev, &pwm, extack); + if (err) + return err; + + priv->xl.pwm =3D pwm; + return 0; +} + static int can_changelink(struct net_device *dev, struct nlattr *tb[], struct nlattr *data[], struct netlink_ext_ack *extack) @@ -595,6 +717,9 @@ static int can_changelink(struct net_device *dev, struc= t nlattr *tb[], =20 /* CAN XL */ err =3D can_dbt_changelink(dev, data, false, extack); + if (err) + return err; + err =3D can_pwm_changelink(dev, data[IFLA_CAN_XL_PWM], extack); if (err) return err; =20 @@ -683,6 +808,30 @@ static size_t can_ctrlmode_ext_get_size(void) nla_total_size(sizeof(u32)); /* IFLA_CAN_CTRLMODE_SUPPORTED */ } =20 +static size_t can_pwm_get_size(const struct can_pwm_const *pwm_const, + bool pwm_on) +{ + size_t size; + + if (!pwm_const || !pwm_on) + return 0; + + size =3D nla_total_size(0); /* nest IFLA_CAN_PWM */ + + size +=3D nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMS_MIN */ + size +=3D nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMS_MAX */ + size +=3D nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWML_MIN */ + size +=3D nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWML_MAX */ + size +=3D nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMO_MIN */ + size +=3D nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMO_MAX */ + + size +=3D nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMS */ + size +=3D nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWML */ + size +=3D nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMO */ + + return size; +} + static size_t can_get_size(const struct net_device *dev) { struct can_priv *priv =3D netdev_priv(dev); @@ -714,6 +863,8 @@ static size_t can_get_size(const struct net_device *dev) =20 size +=3D can_data_bittiming_get_size(&priv->xl, priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MASK); + size +=3D can_pwm_get_size(priv->xl.pwm_const, /* IFLA_CAN_XL_PWM */ + priv->ctrlmode & CAN_CTRLMODE_XL_TMS); =20 return size; } @@ -812,6 +963,42 @@ static int can_tdc_fill_info(struct sk_buff *skb, cons= t struct net_device *dev, return -EMSGSIZE; } =20 +static int can_pwm_fill_info(struct sk_buff *skb, const struct can_priv *p= riv) +{ + const struct can_pwm_const *pwm_const =3D priv->xl.pwm_const; + const struct can_pwm *pwm =3D &priv->xl.pwm; + struct nlattr *nest; + + if (!pwm_const) + return 0; + + nest =3D nla_nest_start(skb, IFLA_CAN_XL_PWM); + if (!nest) + return -EMSGSIZE; + + if (nla_put_u32(skb, IFLA_CAN_PWM_PWMS_MIN, pwm_const->pwms_min) || + nla_put_u32(skb, IFLA_CAN_PWM_PWMS_MAX, pwm_const->pwms_max) || + nla_put_u32(skb, IFLA_CAN_PWM_PWML_MIN, pwm_const->pwml_min) || + nla_put_u32(skb, IFLA_CAN_PWM_PWML_MAX, pwm_const->pwml_max) || + nla_put_u32(skb, IFLA_CAN_PWM_PWMO_MIN, pwm_const->pwmo_min) || + nla_put_u32(skb, IFLA_CAN_PWM_PWMO_MAX, pwm_const->pwmo_max)) + goto err_cancel; + + if (priv->ctrlmode & CAN_CTRLMODE_XL_TMS) { + if (nla_put_u32(skb, IFLA_CAN_PWM_PWMS, pwm->pwms) || + nla_put_u32(skb, IFLA_CAN_PWM_PWML, pwm->pwml) || + nla_put_u32(skb, IFLA_CAN_PWM_PWMO, pwm->pwmo)) + goto err_cancel; + } + + nla_nest_end(skb, nest); + return 0; + +err_cancel: + nla_nest_cancel(skb, nest); + return -EMSGSIZE; +} + static int can_ctrlmode_ext_fill_info(struct sk_buff *skb, const struct can_priv *priv) { @@ -895,9 +1082,10 @@ static int can_fill_info(struct sk_buff *skb, const s= truct net_device *dev) priv->xl.data_bitrate_const, priv->xl.data_bitrate_const_cnt) || =20 - can_tdc_fill_info(skb, dev, IFLA_CAN_XL_TDC) - ) + can_tdc_fill_info(skb, dev, IFLA_CAN_XL_TDC) || =20 + can_pwm_fill_info(skb, priv) + ) return -EMSGSIZE; =20 return 0; diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netl= ink.h index 30d446921dc4..4497e3b4210f 100644 --- a/include/uapi/linux/can/netlink.h +++ b/include/uapi/linux/can/netlink.h @@ -5,6 +5,7 @@ * Definitions for the CAN netlink interface * * Copyright (c) 2009 Wolfgang Grandegger + * Copyright (c) 2021-2025 Vincent Mailhol * * This program is free software; you can redistribute it and/or modify * it under the terms of the version 2 of the GNU General Public License @@ -148,6 +149,7 @@ enum { IFLA_CAN_XL_DATA_BITTIMING_CONST, IFLA_CAN_XL_DATA_BITRATE_CONST, IFLA_CAN_XL_TDC, + IFLA_CAN_XL_PWM, =20 /* add new constants above here */ __IFLA_CAN_MAX, @@ -189,6 +191,29 @@ enum { IFLA_CAN_CTRLMODE_MAX =3D __IFLA_CAN_CTRLMODE - 1 }; =20 +/* + * CAN FD/XL Pulse-Width Modulation (PWM) + * + * Please refer to struct can_pwm_const and can_pwm in + * include/linux/can/bittiming.h for further details. + */ +enum { + IFLA_CAN_PWM_UNSPEC, + IFLA_CAN_PWM_PWMS_MIN, /* u32 */ + IFLA_CAN_PWM_PWMS_MAX, /* u32 */ + IFLA_CAN_PWM_PWML_MIN, /* u32 */ + IFLA_CAN_PWM_PWML_MAX, /* u32 */ + IFLA_CAN_PWM_PWMO_MIN, /* u32 */ + IFLA_CAN_PWM_PWMO_MAX, /* u32 */ + IFLA_CAN_PWM_PWMS, /* u32 */ + IFLA_CAN_PWM_PWML, /* u32 */ + IFLA_CAN_PWM_PWMO, /* u32 */ + + /* add new constants above here */ + __IFLA_CAN_PWM, + IFLA_CAN_PWM_MAX =3D __IFLA_CAN_PWM - 1 +}; + /* u16 termination range: 1..65535 Ohms */ #define CAN_TERMINATION_DISABLED 0 =20 --=20 2.51.0