linux-can.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 01/11] can: dev: add struct data_bittiming_params to group FD parameters
@ 2025-05-27 19:56 Oliver Hartkopp
  2025-05-27 19:56 ` [PATCH 02/11] can: netlink: replace tabulation by space in assignment Oliver Hartkopp
                   ` (9 more replies)
  0 siblings, 10 replies; 22+ messages in thread
From: Oliver Hartkopp @ 2025-05-27 19:56 UTC (permalink / raw)
  To: linux-can; +Cc: Vincent Mailhol, Oliver Hartkopp

From: Vincent Mailhol <mailhol.vincent@wanadoo.fr>

This is a preparation patch for the introduction of CAN XL.

CAN FD and CAN XL uses similar bittiming parameters. Add one level of
nesting for all the CAN FD parameters. Typically:

  priv->can.data_bittiming;

becomes:

  priv->can.fd.data_bittiming;

This way, the CAN XL equivalent (to be introduced later) would be:

  priv->can.xl.data_bittiming;

Add the new struct data_bittiming_params which contains all the data
bittiming parameters, including the TDC and the callback functions.

This done, all the drivers are updated to make use of the new layout.

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
 drivers/net/can/ctucanfd/ctucanfd_base.c      |  8 +-
 drivers/net/can/dev/dev.c                     | 12 +--
 drivers/net/can/dev/netlink.c                 | 74 +++++++++----------
 drivers/net/can/flexcan/flexcan-core.c        |  4 +-
 drivers/net/can/ifi_canfd/ifi_canfd.c         | 10 +--
 drivers/net/can/kvaser_pciefd.c               |  6 +-
 drivers/net/can/m_can/m_can.c                 |  8 +-
 drivers/net/can/peak_canfd/peak_canfd.c       |  6 +-
 drivers/net/can/rcar/rcar_canfd.c             |  4 +-
 .../net/can/rockchip/rockchip_canfd-core.c    |  4 +-
 .../can/rockchip/rockchip_canfd-timestamp.c   |  2 +-
 .../net/can/spi/mcp251xfd/mcp251xfd-core.c    | 10 +--
 drivers/net/can/usb/esd_usb.c                 |  6 +-
 drivers/net/can/usb/etas_es58x/es58x_core.c   |  4 +-
 drivers/net/can/usb/etas_es58x/es58x_fd.c     |  6 +-
 drivers/net/can/usb/gs_usb.c                  |  8 +-
 drivers/net/can/usb/kvaser_usb/kvaser_usb.h   |  2 +-
 .../net/can/usb/kvaser_usb/kvaser_usb_core.c  |  6 +-
 drivers/net/can/usb/peak_usb/pcan_usb_core.c  |  6 +-
 drivers/net/can/xilinx_can.c                  | 16 ++--
 include/linux/can/dev.h                       | 28 ++++---
 21 files changed, 117 insertions(+), 113 deletions(-)

diff --git a/drivers/net/can/ctucanfd/ctucanfd_base.c b/drivers/net/can/ctucanfd/ctucanfd_base.c
index f65c1a1e05cc..bf6398772960 100644
--- a/drivers/net/can/ctucanfd/ctucanfd_base.c
+++ b/drivers/net/can/ctucanfd/ctucanfd_base.c
@@ -273,11 +273,11 @@ static int ctucan_set_bittiming(struct net_device *ndev)
  * Return: 0 on success, -%EPERM on error
  */
 static int ctucan_set_data_bittiming(struct net_device *ndev)
 {
 	struct ctucan_priv *priv = netdev_priv(ndev);
-	struct can_bittiming *dbt = &priv->can.data_bittiming;
+	struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
 
 	/* Note that dbt may be modified here */
 	return ctucan_set_btr(ndev, dbt, false);
 }
 
@@ -288,11 +288,11 @@ static int ctucan_set_data_bittiming(struct net_device *ndev)
  * Return: 0 on success, -%EPERM if controller is enabled
  */
 static int ctucan_set_secondary_sample_point(struct net_device *ndev)
 {
 	struct ctucan_priv *priv = netdev_priv(ndev);
-	struct can_bittiming *dbt = &priv->can.data_bittiming;
+	struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
 	int ssp_offset = 0;
 	u32 ssp_cfg = 0; /* No SSP by default */
 
 	if (CTU_CAN_FD_ENABLED(priv)) {
 		netdev_err(ndev, "BUG! Cannot set SSP - CAN is enabled\n");
@@ -1356,16 +1356,16 @@ int ctucan_probe_common(struct device *dev, void __iomem *addr, int irq, unsigne
 	spin_lock_init(&priv->tx_lock);
 	INIT_LIST_HEAD(&priv->peers_on_pdev);
 	priv->ntxbufs = ntxbufs;
 	priv->dev = dev;
 	priv->can.bittiming_const = &ctu_can_fd_bit_timing_max;
-	priv->can.data_bittiming_const = &ctu_can_fd_bit_timing_data_max;
+	priv->can.fd.data_bittiming_const = &ctu_can_fd_bit_timing_data_max;
 	priv->can.do_set_mode = ctucan_do_set_mode;
 
 	/* Needed for timing adjustment to be performed as soon as possible */
 	priv->can.do_set_bittiming = ctucan_set_bittiming;
-	priv->can.do_set_data_bittiming = ctucan_set_data_bittiming;
+	priv->can.fd.do_set_data_bittiming = ctucan_set_data_bittiming;
 
 	priv->can.do_get_berr_counter = ctucan_get_berr_counter;
 	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK
 					| CAN_CTRLMODE_LISTENONLY
 					| CAN_CTRLMODE_FD
diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
index 5ec3170b896a..ea8c807af4d8 100644
--- a/drivers/net/can/dev/dev.c
+++ b/drivers/net/can/dev/dev.c
@@ -402,12 +402,12 @@ int open_candev(struct net_device *dev)
 		return -EINVAL;
 	}
 
 	/* For CAN FD the data bitrate has to be >= the arbitration bitrate */
 	if ((priv->ctrlmode & CAN_CTRLMODE_FD) &&
-	    (!priv->data_bittiming.bitrate ||
-	     priv->data_bittiming.bitrate < priv->bittiming.bitrate)) {
+	    (!priv->fd.data_bittiming.bitrate ||
+	     priv->fd.data_bittiming.bitrate < priv->bittiming.bitrate)) {
 		netdev_err(dev, "incorrect/missing data bit-timing\n");
 		return -EINVAL;
 	}
 
 	/* Switch carrier on if device was stopped while in bus-off state */
@@ -541,20 +541,20 @@ int register_candev(struct net_device *dev)
 		return -EINVAL;
 
 	if (!priv->bitrate_const != !priv->bitrate_const_cnt)
 		return -EINVAL;
 
-	if (!priv->data_bitrate_const != !priv->data_bitrate_const_cnt)
+	if (!priv->fd.data_bitrate_const != !priv->fd.data_bitrate_const_cnt)
 		return -EINVAL;
 
 	/* We only support either fixed bit rates or bit timing const. */
-	if ((priv->bitrate_const || priv->data_bitrate_const) &&
-	    (priv->bittiming_const || priv->data_bittiming_const))
+	if ((priv->bitrate_const || priv->fd.data_bitrate_const) &&
+	    (priv->bittiming_const || priv->fd.data_bittiming_const))
 		return -EINVAL;
 
 	if (!can_bittiming_const_valid(priv->bittiming_const) ||
-	    !can_bittiming_const_valid(priv->data_bittiming_const))
+	    !can_bittiming_const_valid(priv->fd.data_bittiming_const))
 		return -EINVAL;
 
 	if (!priv->termination_const) {
 		err = can_get_termination(dev);
 		if (err)
diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
index f1db9b7ffd4d..a36842ace084 100644
--- a/drivers/net/can/dev/netlink.c
+++ b/drivers/net/can/dev/netlink.c
@@ -139,11 +139,11 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
 static int can_tdc_changelink(struct can_priv *priv, const struct nlattr *nla,
 			      struct netlink_ext_ack *extack)
 {
 	struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1];
 	struct can_tdc tdc = { 0 };
-	const struct can_tdc_const *tdc_const = priv->tdc_const;
+	const struct can_tdc_const *tdc_const = priv->fd.tdc_const;
 	int err;
 
 	if (!tdc_const || !can_tdc_is_enabled(priv))
 		return -EOPNOTSUPP;
 
@@ -177,11 +177,11 @@ static int can_tdc_changelink(struct can_priv *priv, const struct nlattr *nla,
 			return -EINVAL;
 
 		tdc.tdcf = tdcf;
 	}
 
-	priv->tdc = tdc;
+	priv->fd.tdc = tdc;
 
 	return 0;
 }
 
 static int can_changelink(struct net_device *dev, struct nlattr *tb[],
@@ -226,14 +226,14 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 		/* CAN_CTRLMODE_FD can only be set when driver supports FD */
 		if (priv->ctrlmode & CAN_CTRLMODE_FD) {
 			dev->mtu = CANFD_MTU;
 		} else {
 			dev->mtu = CAN_MTU;
-			memset(&priv->data_bittiming, 0,
-			       sizeof(priv->data_bittiming));
+			memset(&priv->fd.data_bittiming, 0,
+			       sizeof(priv->fd.data_bittiming));
 			priv->ctrlmode &= ~CAN_CTRLMODE_TDC_MASK;
-			memset(&priv->tdc, 0, sizeof(priv->tdc));
+			memset(&priv->fd.tdc, 0, sizeof(priv->fd.tdc));
 		}
 
 		tdc_mask = cm->mask & CAN_CTRLMODE_TDC_MASK;
 		/* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually
 		 * exclusive: make sure to turn the other one off
@@ -310,20 +310,20 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 		/* Calculate bittiming parameters based on
 		 * data_bittiming_const if set, otherwise pass bitrate
 		 * directly via do_set_bitrate(). Bail out if neither
 		 * is given.
 		 */
-		if (!priv->data_bittiming_const && !priv->do_set_data_bittiming &&
-		    !priv->data_bitrate_const)
+		if (!priv->fd.data_bittiming_const && !priv->fd.do_set_data_bittiming &&
+		    !priv->fd.data_bitrate_const)
 			return -EOPNOTSUPP;
 
 		memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]),
 		       sizeof(dbt));
 		err = can_get_bittiming(dev, &dbt,
-					priv->data_bittiming_const,
-					priv->data_bitrate_const,
-					priv->data_bitrate_const_cnt,
+					priv->fd.data_bittiming_const,
+					priv->fd.data_bitrate_const,
+					priv->fd.data_bitrate_const_cnt,
 					extack);
 		if (err)
 			return err;
 
 		if (priv->bitrate_max && dbt.bitrate > priv->bitrate_max) {
@@ -331,11 +331,11 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 					   "CANFD data bitrate %u bps surpasses transceiver capabilities of %u bps",
 					   dbt.bitrate, priv->bitrate_max);
 			return -EINVAL;
 		}
 
-		memset(&priv->tdc, 0, sizeof(priv->tdc));
+		memset(&priv->fd.tdc, 0, sizeof(priv->fd.tdc));
 		if (data[IFLA_CAN_TDC]) {
 			/* TDC parameters are provided: use them */
 			err = can_tdc_changelink(priv, data[IFLA_CAN_TDC],
 						 extack);
 			if (err) {
@@ -344,21 +344,21 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 			}
 		} else if (!tdc_mask) {
 			/* Neither of TDC parameters nor TDC flags are
 			 * provided: do calculation
 			 */
-			can_calc_tdco(&priv->tdc, priv->tdc_const, &dbt,
+			can_calc_tdco(&priv->fd.tdc, priv->fd.tdc_const, &dbt,
 				      &priv->ctrlmode, priv->ctrlmode_supported);
 		} /* else: both CAN_CTRLMODE_TDC_{AUTO,MANUAL} are explicitly
 		   * turned off. TDC is disabled: do nothing
 		   */
 
-		memcpy(&priv->data_bittiming, &dbt, sizeof(dbt));
+		memcpy(&priv->fd.data_bittiming, &dbt, sizeof(dbt));
 
-		if (priv->do_set_data_bittiming) {
+		if (priv->fd.do_set_data_bittiming) {
 			/* Finally, set the bit-timing registers */
-			err = priv->do_set_data_bittiming(dev);
+			err = priv->fd.do_set_data_bittiming(dev);
 			if (err)
 				return err;
 		}
 	}
 
@@ -392,31 +392,31 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 static size_t can_tdc_get_size(const struct net_device *dev)
 {
 	struct can_priv *priv = netdev_priv(dev);
 	size_t size;
 
-	if (!priv->tdc_const)
+	if (!priv->fd.tdc_const)
 		return 0;
 
 	size = nla_total_size(0);			/* nest IFLA_CAN_TDC */
 	if (priv->ctrlmode_supported & CAN_CTRLMODE_TDC_MANUAL) {
 		size += nla_total_size(sizeof(u32));	/* IFLA_CAN_TDCV_MIN */
 		size += nla_total_size(sizeof(u32));	/* IFLA_CAN_TDCV_MAX */
 	}
 	size += nla_total_size(sizeof(u32));		/* IFLA_CAN_TDCO_MIN */
 	size += nla_total_size(sizeof(u32));		/* IFLA_CAN_TDCO_MAX */
-	if (priv->tdc_const->tdcf_max) {
+	if (priv->fd.tdc_const->tdcf_max) {
 		size += nla_total_size(sizeof(u32));	/* IFLA_CAN_TDCF_MIN */
 		size += nla_total_size(sizeof(u32));	/* IFLA_CAN_TDCF_MAX */
 	}
 
 	if (can_tdc_is_enabled(priv)) {
 		if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL ||
-		    priv->do_get_auto_tdcv)
+		    priv->fd.do_get_auto_tdcv)
 			size += nla_total_size(sizeof(u32));	/* IFLA_CAN_TDCV */
 		size += nla_total_size(sizeof(u32));		/* IFLA_CAN_TDCO */
-		if (priv->tdc_const->tdcf_max)
+		if (priv->fd.tdc_const->tdcf_max)
 			size += nla_total_size(sizeof(u32));	/* IFLA_CAN_TDCF */
 	}
 
 	return size;
 }
@@ -440,25 +440,25 @@ static size_t can_get_size(const struct net_device *dev)
 	size += nla_total_size(sizeof(u32));			/* IFLA_CAN_STATE */
 	size += nla_total_size(sizeof(struct can_ctrlmode));	/* IFLA_CAN_CTRLMODE */
 	size += nla_total_size(sizeof(u32));			/* IFLA_CAN_RESTART_MS */
 	if (priv->do_get_berr_counter)				/* IFLA_CAN_BERR_COUNTER */
 		size += nla_total_size(sizeof(struct can_berr_counter));
-	if (priv->data_bittiming.bitrate)			/* IFLA_CAN_DATA_BITTIMING */
+	if (priv->fd.data_bittiming.bitrate)			/* IFLA_CAN_DATA_BITTIMING */
 		size += nla_total_size(sizeof(struct can_bittiming));
-	if (priv->data_bittiming_const)				/* IFLA_CAN_DATA_BITTIMING_CONST */
+	if (priv->fd.data_bittiming_const)			/* IFLA_CAN_DATA_BITTIMING_CONST */
 		size += nla_total_size(sizeof(struct can_bittiming_const));
 	if (priv->termination_const) {
 		size += nla_total_size(sizeof(priv->termination));		/* IFLA_CAN_TERMINATION */
 		size += nla_total_size(sizeof(*priv->termination_const) *	/* IFLA_CAN_TERMINATION_CONST */
 				       priv->termination_const_cnt);
 	}
 	if (priv->bitrate_const)				/* IFLA_CAN_BITRATE_CONST */
 		size += nla_total_size(sizeof(*priv->bitrate_const) *
 				       priv->bitrate_const_cnt);
-	if (priv->data_bitrate_const)				/* IFLA_CAN_DATA_BITRATE_CONST */
-		size += nla_total_size(sizeof(*priv->data_bitrate_const) *
-				       priv->data_bitrate_const_cnt);
+	if (priv->fd.data_bitrate_const)			/* IFLA_CAN_DATA_BITRATE_CONST */
+		size += nla_total_size(sizeof(*priv->fd.data_bitrate_const) *
+				       priv->fd.data_bitrate_const_cnt);
 	size += sizeof(priv->bitrate_max);			/* IFLA_CAN_BITRATE_MAX */
 	size += can_tdc_get_size(dev);				/* IFLA_CAN_TDC */
 	size += can_ctrlmode_ext_get_size();			/* IFLA_CAN_CTRLMODE_EXT */
 
 	return size;
@@ -466,12 +466,12 @@ static size_t can_get_size(const struct net_device *dev)
 
 static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev)
 {
 	struct nlattr *nest;
 	struct can_priv *priv = netdev_priv(dev);
-	struct can_tdc *tdc = &priv->tdc;
-	const struct can_tdc_const *tdc_const = priv->tdc_const;
+	struct can_tdc *tdc = &priv->fd.tdc;
+	const struct can_tdc_const *tdc_const = priv->fd.tdc_const;
 
 	if (!tdc_const)
 		return 0;
 
 	nest = nla_nest_start(skb, IFLA_CAN_TDC);
@@ -495,12 +495,12 @@ static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev)
 		int err = -EINVAL;
 
 		if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL) {
 			tdcv = tdc->tdcv;
 			err = 0;
-		} else if (priv->do_get_auto_tdcv) {
-			err = priv->do_get_auto_tdcv(dev, &tdcv);
+		} else if (priv->fd.do_get_auto_tdcv) {
+			err = priv->fd.do_get_auto_tdcv(dev, &tdcv);
 		}
 		if (!err && nla_put_u32(skb, IFLA_CAN_TDC_TDCV, tdcv))
 			goto err_cancel;
 		if (nla_put_u32(skb, IFLA_CAN_TDC_TDCO, tdc->tdco))
 			goto err_cancel;
@@ -562,18 +562,18 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
 
 	    (priv->do_get_berr_counter &&
 	     !priv->do_get_berr_counter(dev, &bec) &&
 	     nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)) ||
 
-	    (priv->data_bittiming.bitrate &&
+	    (priv->fd.data_bittiming.bitrate &&
 	     nla_put(skb, IFLA_CAN_DATA_BITTIMING,
-		     sizeof(priv->data_bittiming), &priv->data_bittiming)) ||
+		     sizeof(priv->fd.data_bittiming), &priv->fd.data_bittiming)) ||
 
-	    (priv->data_bittiming_const &&
+	    (priv->fd.data_bittiming_const &&
 	     nla_put(skb, IFLA_CAN_DATA_BITTIMING_CONST,
-		     sizeof(*priv->data_bittiming_const),
-		     priv->data_bittiming_const)) ||
+		     sizeof(*priv->fd.data_bittiming_const),
+		     priv->fd.data_bittiming_const)) ||
 
 	    (priv->termination_const &&
 	     (nla_put_u16(skb, IFLA_CAN_TERMINATION, priv->termination) ||
 	      nla_put(skb, IFLA_CAN_TERMINATION_CONST,
 		      sizeof(*priv->termination_const) *
@@ -584,15 +584,15 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
 	     nla_put(skb, IFLA_CAN_BITRATE_CONST,
 		     sizeof(*priv->bitrate_const) *
 		     priv->bitrate_const_cnt,
 		     priv->bitrate_const)) ||
 
-	    (priv->data_bitrate_const &&
+	    (priv->fd.data_bitrate_const &&
 	     nla_put(skb, IFLA_CAN_DATA_BITRATE_CONST,
-		     sizeof(*priv->data_bitrate_const) *
-		     priv->data_bitrate_const_cnt,
-		     priv->data_bitrate_const)) ||
+		     sizeof(*priv->fd.data_bitrate_const) *
+		     priv->fd.data_bitrate_const_cnt,
+		     priv->fd.data_bitrate_const)) ||
 
 	    (nla_put(skb, IFLA_CAN_BITRATE_MAX,
 		     sizeof(priv->bitrate_max),
 		     &priv->bitrate_max)) ||
 
diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
index 6d80c341b26f..06d5d35fc1b5 100644
--- a/drivers/net/can/flexcan/flexcan-core.c
+++ b/drivers/net/can/flexcan/flexcan-core.c
@@ -1224,11 +1224,11 @@ static void flexcan_set_bittiming_ctrl(const struct net_device *dev)
 
 static void flexcan_set_bittiming_cbt(const struct net_device *dev)
 {
 	struct flexcan_priv *priv = netdev_priv(dev);
 	struct can_bittiming *bt = &priv->can.bittiming;
-	struct can_bittiming *dbt = &priv->can.data_bittiming;
+	struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
 	struct flexcan_regs __iomem *regs = priv->regs;
 	u32 reg_cbt, reg_fdctrl;
 
 	/* CBT */
 	/* CBT[EPSEG1] is 5 bit long and CBT[EPROPSEG] is 6 bit
@@ -2237,11 +2237,11 @@ static int flexcan_probe(struct platform_device *pdev)
 
 	if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SUPPORT_FD) {
 		priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD |
 			CAN_CTRLMODE_FD_NON_ISO;
 		priv->can.bittiming_const = &flexcan_fd_bittiming_const;
-		priv->can.data_bittiming_const =
+		priv->can.fd.data_bittiming_const =
 			&flexcan_fd_data_bittiming_const;
 	} else {
 		priv->can.bittiming_const = &flexcan_bittiming_const;
 	}
 
diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c
index c86b57d47085..2eeee65f606f 100644
--- a/drivers/net/can/ifi_canfd/ifi_canfd.c
+++ b/drivers/net/can/ifi_canfd/ifi_canfd.c
@@ -667,11 +667,11 @@ static const struct can_bittiming_const ifi_canfd_bittiming_const = {
 
 static void ifi_canfd_set_bittiming(struct net_device *ndev)
 {
 	struct ifi_canfd_priv *priv = netdev_priv(ndev);
 	const struct can_bittiming *bt = &priv->can.bittiming;
-	const struct can_bittiming *dbt = &priv->can.data_bittiming;
+	const struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
 	u16 brp, sjw, tseg1, tseg2, tdc;
 
 	/* Configure bit timing */
 	brp = bt->brp - 2;
 	sjw = bt->sjw - 1;
@@ -998,14 +998,14 @@ static int ifi_canfd_plat_probe(struct platform_device *pdev)
 
 	priv->can.state = CAN_STATE_STOPPED;
 
 	priv->can.clock.freq = readl(addr + IFI_CANFD_CANCLOCK);
 
-	priv->can.bittiming_const	= &ifi_canfd_bittiming_const;
-	priv->can.data_bittiming_const	= &ifi_canfd_bittiming_const;
-	priv->can.do_set_mode		= ifi_canfd_set_mode;
-	priv->can.do_get_berr_counter	= ifi_canfd_get_berr_counter;
+	priv->can.bittiming_const = &ifi_canfd_bittiming_const;
+	priv->can.fd.data_bittiming_const = &ifi_canfd_bittiming_const;
+	priv->can.do_set_mode = ifi_canfd_set_mode;
+	priv->can.do_get_berr_counter = ifi_canfd_get_berr_counter;
 
 	/* IFI CANFD can do both Bosch FD and ISO FD */
 	priv->can.ctrlmode = CAN_CTRLMODE_FD;
 
 	/* IFI CANFD can do both Bosch FD and ISO FD */
diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c
index cf0d51805272..4022eb2e1a7d 100644
--- a/drivers/net/can/kvaser_pciefd.c
+++ b/drivers/net/can/kvaser_pciefd.c
@@ -854,11 +854,11 @@ static int kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can *can, bool data)
 	unsigned long irq_flags;
 	int ret;
 	struct can_bittiming *bt;
 
 	if (data)
-		bt = &can->can.data_bittiming;
+		bt = &can->can.fd.data_bittiming;
 	else
 		bt = &can->can.bittiming;
 
 	btrn = FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_TSEG2_MASK, bt->phase_seg2 - 1) |
 	       FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_TSEG1_MASK, bt->prop_seg + bt->phase_seg1 - 1) |
@@ -989,13 +989,13 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
 		can->echo_idx = 0;
 		spin_lock_init(&can->echo_lock);
 		spin_lock_init(&can->lock);
 
 		can->can.bittiming_const = &kvaser_pciefd_bittiming_const;
-		can->can.data_bittiming_const = &kvaser_pciefd_bittiming_const;
+		can->can.fd.data_bittiming_const = &kvaser_pciefd_bittiming_const;
 		can->can.do_set_bittiming = kvaser_pciefd_set_nominal_bittiming;
-		can->can.do_set_data_bittiming = kvaser_pciefd_set_data_bittiming;
+		can->can.fd.do_set_data_bittiming = kvaser_pciefd_set_data_bittiming;
 		can->can.do_set_mode = kvaser_pciefd_set_mode;
 		can->can.do_get_berr_counter = kvaser_pciefd_get_berr_counter;
 		can->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY |
 					      CAN_CTRLMODE_FD |
 					      CAN_CTRLMODE_FD_NON_ISO |
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index c2c116ce1087..6c656bfdb323 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -1370,11 +1370,11 @@ static const struct can_bittiming_const m_can_data_bittiming_const_31X = {
 
 static int m_can_set_bittiming(struct net_device *dev)
 {
 	struct m_can_classdev *cdev = netdev_priv(dev);
 	const struct can_bittiming *bt = &cdev->can.bittiming;
-	const struct can_bittiming *dbt = &cdev->can.data_bittiming;
+	const struct can_bittiming *dbt = &cdev->can.fd.data_bittiming;
 	u16 brp, sjw, tseg1, tseg2;
 	u32 reg_btp;
 
 	brp = bt->brp - 1;
 	sjw = bt->sjw - 1;
@@ -1736,25 +1736,25 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
 		/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.x */
 		err = can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
 		if (err)
 			return err;
 		cdev->can.bittiming_const = &m_can_bittiming_const_30X;
-		cdev->can.data_bittiming_const = &m_can_data_bittiming_const_30X;
+		cdev->can.fd.data_bittiming_const = &m_can_data_bittiming_const_30X;
 		break;
 	case 31:
 		/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.1.x */
 		err = can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
 		if (err)
 			return err;
 		cdev->can.bittiming_const = &m_can_bittiming_const_31X;
-		cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
+		cdev->can.fd.data_bittiming_const = &m_can_data_bittiming_const_31X;
 		break;
 	case 32:
 	case 33:
 		/* Support both MCAN version v3.2.x and v3.3.0 */
 		cdev->can.bittiming_const = &m_can_bittiming_const_31X;
-		cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
+		cdev->can.fd.data_bittiming_const = &m_can_data_bittiming_const_31X;
 
 		niso = m_can_niso_supported(cdev);
 		if (niso < 0)
 			return niso;
 		if (niso)
diff --git a/drivers/net/can/peak_canfd/peak_canfd.c b/drivers/net/can/peak_canfd/peak_canfd.c
index 28f3fd805273..77292afaed22 100644
--- a/drivers/net/can/peak_canfd/peak_canfd.c
+++ b/drivers/net/can/peak_canfd/peak_canfd.c
@@ -622,11 +622,11 @@ static int peak_canfd_set_bittiming(struct net_device *ndev)
 
 static int peak_canfd_set_data_bittiming(struct net_device *ndev)
 {
 	struct peak_canfd_priv *priv = netdev_priv(ndev);
 
-	return pucan_set_timing_fast(priv, &priv->can.data_bittiming);
+	return pucan_set_timing_fast(priv, &priv->can.fd.data_bittiming);
 }
 
 static int peak_canfd_close(struct net_device *ndev)
 {
 	struct peak_canfd_priv *priv = netdev_priv(ndev);
@@ -811,16 +811,16 @@ struct net_device *alloc_peak_canfd_dev(int sizeof_priv, int index,
 	priv = netdev_priv(ndev);
 
 	/* complete now socket-can initialization side */
 	priv->can.state = CAN_STATE_STOPPED;
 	priv->can.bittiming_const = &peak_canfd_nominal_const;
-	priv->can.data_bittiming_const = &peak_canfd_data_const;
+	priv->can.fd.data_bittiming_const = &peak_canfd_data_const;
 
 	priv->can.do_set_mode = peak_canfd_set_mode;
 	priv->can.do_get_berr_counter = peak_canfd_get_berr_counter;
 	priv->can.do_set_bittiming = peak_canfd_set_bittiming;
-	priv->can.do_set_data_bittiming = peak_canfd_set_data_bittiming;
+	priv->can.fd.do_set_data_bittiming = peak_canfd_set_data_bittiming;
 	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
 				       CAN_CTRLMODE_LISTENONLY |
 				       CAN_CTRLMODE_3_SAMPLES |
 				       CAN_CTRLMODE_FD |
 				       CAN_CTRLMODE_FD_NON_ISO |
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index aa3df0d05b85..7b7eb0df0d72 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -1302,11 +1302,11 @@ static irqreturn_t rcar_canfd_channel_interrupt(int irq, void *dev_id)
 static void rcar_canfd_set_bittiming(struct net_device *dev)
 {
 	struct rcar_canfd_channel *priv = netdev_priv(dev);
 	struct rcar_canfd_global *gpriv = priv->gpriv;
 	const struct can_bittiming *bt = &priv->can.bittiming;
-	const struct can_bittiming *dbt = &priv->can.data_bittiming;
+	const struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
 	u16 brp, sjw, tseg1, tseg2;
 	u32 cfg;
 	u32 ch = priv->channel;
 
 	/* Nominal bit timing settings */
@@ -1781,11 +1781,11 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch,
 		}
 	}
 
 	if (gpriv->fdmode) {
 		priv->can.bittiming_const = &rcar_canfd_nom_bittiming_const;
-		priv->can.data_bittiming_const =
+		priv->can.fd.data_bittiming_const =
 			&rcar_canfd_data_bittiming_const;
 
 		/* Controller starts in CAN FD only mode */
 		err = can_set_static_ctrlmode(ndev, CAN_CTRLMODE_FD);
 		if (err)
diff --git a/drivers/net/can/rockchip/rockchip_canfd-core.c b/drivers/net/can/rockchip/rockchip_canfd-core.c
index c3fb3176ce42..046f0a0ae4d4 100644
--- a/drivers/net/can/rockchip/rockchip_canfd-core.c
+++ b/drivers/net/can/rockchip/rockchip_canfd-core.c
@@ -116,11 +116,11 @@ static void rkcanfd_chip_set_work_mode(const struct rkcanfd_priv *priv)
 	rkcanfd_write(priv, RKCANFD_REG_MODE, priv->reg_mode_default);
 }
 
 static int rkcanfd_set_bittiming(struct rkcanfd_priv *priv)
 {
-	const struct can_bittiming *dbt = &priv->can.data_bittiming;
+	const struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
 	const struct can_bittiming *bt = &priv->can.bittiming;
 	u32 reg_nbt, reg_dbt, reg_tdc;
 	u32 tdco;
 
 	reg_nbt = FIELD_PREP(RKCANFD_REG_FD_NOMINAL_BITTIMING_SJW,
@@ -897,11 +897,11 @@ static int rkcanfd_probe(struct platform_device *pdev)
 	ndev->flags |= IFF_ECHO;
 
 	platform_set_drvdata(pdev, priv);
 	priv->can.clock.freq = clk_get_rate(priv->clks[0].clk);
 	priv->can.bittiming_const = &rkcanfd_bittiming_const;
-	priv->can.data_bittiming_const = &rkcanfd_data_bittiming_const;
+	priv->can.fd.data_bittiming_const = &rkcanfd_data_bittiming_const;
 	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
 		CAN_CTRLMODE_BERR_REPORTING;
 	priv->can.do_set_mode = rkcanfd_set_mode;
 	priv->can.do_get_berr_counter = rkcanfd_get_berr_counter;
 	priv->ndev = ndev;
diff --git a/drivers/net/can/rockchip/rockchip_canfd-timestamp.c b/drivers/net/can/rockchip/rockchip_canfd-timestamp.c
index 43d4b5721812..fa85a75be65a 100644
--- a/drivers/net/can/rockchip/rockchip_canfd-timestamp.c
+++ b/drivers/net/can/rockchip/rockchip_canfd-timestamp.c
@@ -37,11 +37,11 @@ static void rkcanfd_timestamp_work(struct work_struct *work)
 	schedule_delayed_work(&priv->timestamp, priv->work_delay_jiffies);
 }
 
 void rkcanfd_timestamp_init(struct rkcanfd_priv *priv)
 {
-	const struct can_bittiming *dbt = &priv->can.data_bittiming;
+	const struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
 	const struct can_bittiming *bt = &priv->can.bittiming;
 	struct cyclecounter *cc = &priv->cc;
 	u32 bitrate, div, reg, rate;
 	u64 work_delay_ns;
 	u64 max_cycles;
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
index c30b04f8fc0d..ac046645c7d6 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -525,11 +525,11 @@ static int mcp251xfd_chip_timestamp_init(const struct mcp251xfd_priv *priv)
 }
 
 static int mcp251xfd_set_bittiming(const struct mcp251xfd_priv *priv)
 {
 	const struct can_bittiming *bt = &priv->can.bittiming;
-	const struct can_bittiming *dbt = &priv->can.data_bittiming;
+	const struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
 	u32 tdcmod, val = 0;
 	int err;
 
 	/* CAN Control Register
 	 *
@@ -598,12 +598,12 @@ static int mcp251xfd_set_bittiming(const struct mcp251xfd_priv *priv)
 		tdcmod = MCP251XFD_REG_TDC_TDCMOD_MANUAL;
 	else
 		tdcmod = MCP251XFD_REG_TDC_TDCMOD_DISABLED;
 
 	val = FIELD_PREP(MCP251XFD_REG_TDC_TDCMOD_MASK, tdcmod) |
-		FIELD_PREP(MCP251XFD_REG_TDC_TDCV_MASK, priv->can.tdc.tdcv) |
-		FIELD_PREP(MCP251XFD_REG_TDC_TDCO_MASK, priv->can.tdc.tdco);
+		FIELD_PREP(MCP251XFD_REG_TDC_TDCV_MASK, priv->can.fd.tdc.tdcv) |
+		FIELD_PREP(MCP251XFD_REG_TDC_TDCO_MASK, priv->can.fd.tdc.tdco);
 
 	return regmap_write(priv->map_reg, MCP251XFD_REG_TDC, val);
 }
 
 static int mcp251xfd_chip_rx_int_enable(const struct mcp251xfd_priv *priv)
@@ -2102,12 +2102,12 @@ static int mcp251xfd_probe(struct spi_device *spi)
 	if (pll_enable)
 		priv->can.clock.freq *= MCP251XFD_OSC_PLL_MULTIPLIER;
 	priv->can.do_set_mode = mcp251xfd_set_mode;
 	priv->can.do_get_berr_counter = mcp251xfd_get_berr_counter;
 	priv->can.bittiming_const = &mcp251xfd_bittiming_const;
-	priv->can.data_bittiming_const = &mcp251xfd_data_bittiming_const;
-	priv->can.tdc_const = &mcp251xfd_tdc_const;
+	priv->can.fd.data_bittiming_const = &mcp251xfd_data_bittiming_const;
+	priv->can.fd.tdc_const = &mcp251xfd_tdc_const;
 	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
 		CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_BERR_REPORTING |
 		CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO |
 		CAN_CTRLMODE_CC_LEN8_DLC | CAN_CTRLMODE_TDC_AUTO |
 		CAN_CTRLMODE_TDC_MANUAL;
diff --git a/drivers/net/can/usb/esd_usb.c b/drivers/net/can/usb/esd_usb.c
index 03ad10b01867..27a3818885c2 100644
--- a/drivers/net/can/usb/esd_usb.c
+++ b/drivers/net/can/usb/esd_usb.c
@@ -1096,11 +1096,11 @@ static int esd_usb_3_set_bittiming(struct net_device *netdev)
 {
 	const struct can_bittiming_const *nom_btc = &esd_usb_3_nom_bittiming_const;
 	const struct can_bittiming_const *data_btc = &esd_usb_3_data_bittiming_const;
 	struct esd_usb_net_priv *priv = netdev_priv(netdev);
 	struct can_bittiming *nom_bt = &priv->can.bittiming;
-	struct can_bittiming *data_bt = &priv->can.data_bittiming;
+	struct can_bittiming *data_bt = &priv->can.fd.data_bittiming;
 	struct esd_usb_3_set_baudrate_msg_x *baud_x;
 	union esd_usb_msg *msg;
 	u16 flags = 0;
 	int err;
 
@@ -1216,13 +1216,13 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index)
 	switch (le16_to_cpu(dev->udev->descriptor.idProduct)) {
 	case ESD_USB_CANUSB3_PRODUCT_ID:
 		priv->can.clock.freq = ESD_USB_3_CAN_CLOCK;
 		priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
 		priv->can.bittiming_const = &esd_usb_3_nom_bittiming_const;
-		priv->can.data_bittiming_const = &esd_usb_3_data_bittiming_const;
+		priv->can.fd.data_bittiming_const = &esd_usb_3_data_bittiming_const;
 		priv->can.do_set_bittiming = esd_usb_3_set_bittiming;
-		priv->can.do_set_data_bittiming = esd_usb_3_set_bittiming;
+		priv->can.fd.do_set_data_bittiming = esd_usb_3_set_bittiming;
 		break;
 
 	case ESD_USB_CANUSBM_PRODUCT_ID:
 		priv->can.clock.freq = ESD_USB_M_CAN_CLOCK;
 		priv->can.bittiming_const = &esd_usb_2_bittiming_const;
diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.c b/drivers/net/can/usb/etas_es58x/es58x_core.c
index 71f24dc0a927..db1acf6d504c 100644
--- a/drivers/net/can/usb/etas_es58x/es58x_core.c
+++ b/drivers/net/can/usb/etas_es58x/es58x_core.c
@@ -2057,12 +2057,12 @@ static int es58x_init_priv(struct es58x_device *es58x_dev,
 	priv->tx_urb = NULL;
 	priv->tx_can_msg_cnt = 0;
 
 	can->bittiming_const = param->bittiming_const;
 	if (param->ctrlmode_supported & CAN_CTRLMODE_FD) {
-		can->data_bittiming_const = param->data_bittiming_const;
-		can->tdc_const = param->tdc_const;
+		can->fd.data_bittiming_const = param->data_bittiming_const;
+		can->fd.tdc_const = param->tdc_const;
 	}
 	can->bitrate_max = param->bitrate_max;
 	can->clock = param->clock;
 	can->state = CAN_STATE_STOPPED;
 	can->ctrlmode_supported = param->ctrlmode_supported;
diff --git a/drivers/net/can/usb/etas_es58x/es58x_fd.c b/drivers/net/can/usb/etas_es58x/es58x_fd.c
index 84ffa1839bac..d924b053677b 100644
--- a/drivers/net/can/usb/etas_es58x/es58x_fd.c
+++ b/drivers/net/can/usb/etas_es58x/es58x_fd.c
@@ -425,16 +425,16 @@ static int es58x_fd_enable_channel(struct es58x_priv *priv)
 		tx_conf_msg.canfd_enabled = 1;
 	}
 
 	if (tx_conf_msg.canfd_enabled) {
 		es58x_fd_convert_bittiming(&tx_conf_msg.data_bittiming,
-					   &priv->can.data_bittiming);
+					   &priv->can.fd.data_bittiming);
 
 		if (can_tdc_is_enabled(&priv->can)) {
 			tx_conf_msg.tdc_enabled = 1;
-			tx_conf_msg.tdco = cpu_to_le16(priv->can.tdc.tdco);
-			tx_conf_msg.tdcf = cpu_to_le16(priv->can.tdc.tdcf);
+			tx_conf_msg.tdco = cpu_to_le16(priv->can.fd.tdc.tdco);
+			tx_conf_msg.tdcf = cpu_to_le16(priv->can.fd.tdc.tdcf);
 		}
 
 		conf_len = ES58X_FD_CANFD_CONF_LEN;
 	} else {
 		conf_len = ES58X_FD_CAN_CONF_LEN;
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index 3ccac6781b98..bb6335278e46 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -726,11 +726,11 @@ static int gs_usb_set_bittiming(struct net_device *netdev)
 }
 
 static int gs_usb_set_data_bittiming(struct net_device *netdev)
 {
 	struct gs_can *dev = netdev_priv(netdev);
-	struct can_bittiming *bt = &dev->can.data_bittiming;
+	struct can_bittiming *bt = &dev->can.fd.data_bittiming;
 	struct gs_device_bittiming dbt = {
 		.prop_seg = cpu_to_le32(bt->prop_seg),
 		.phase_seg1 = cpu_to_le32(bt->phase_seg1),
 		.phase_seg2 = cpu_to_le32(bt->phase_seg2),
 		.sjw = cpu_to_le32(bt->sjw),
@@ -1298,12 +1298,12 @@ static struct gs_can *gs_make_candev(unsigned int channel,
 	if (feature & GS_CAN_FEATURE_FD) {
 		dev->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
 		/* The data bit timing will be overwritten, if
 		 * GS_CAN_FEATURE_BT_CONST_EXT is set.
 		 */
-		dev->can.data_bittiming_const = &dev->bt_const;
-		dev->can.do_set_data_bittiming = gs_usb_set_data_bittiming;
+		dev->can.fd.data_bittiming_const = &dev->bt_const;
+		dev->can.fd.do_set_data_bittiming = gs_usb_set_data_bittiming;
 	}
 
 	if (feature & GS_CAN_FEATURE_TERMINATION) {
 		rc = gs_usb_get_termination(netdev, &dev->can.termination);
 		if (rc) {
@@ -1379,11 +1379,11 @@ static struct gs_can *gs_make_candev(unsigned int channel,
 		dev->data_bt_const.sjw_max = le32_to_cpu(bt_const_extended.dsjw_max);
 		dev->data_bt_const.brp_min = le32_to_cpu(bt_const_extended.dbrp_min);
 		dev->data_bt_const.brp_max = le32_to_cpu(bt_const_extended.dbrp_max);
 		dev->data_bt_const.brp_inc = le32_to_cpu(bt_const_extended.dbrp_inc);
 
-		dev->can.data_bittiming_const = &dev->data_bt_const;
+		dev->can.fd.data_bittiming_const = &dev->data_bt_const;
 	}
 
 	can_rx_offload_add_manual(netdev, &dev->offload, GS_NAPI_WEIGHT);
 	SET_NETDEV_DEV(netdev, &intf->dev);
 
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h
index 078496d9b7ba..f6c77eca9f43 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h
@@ -135,11 +135,11 @@ struct kvaser_usb_net_priv {
 /**
  * struct kvaser_usb_dev_ops - Device specific functions
  * @dev_set_mode:		used for can.do_set_mode
  * @dev_set_bittiming:		used for can.do_set_bittiming
  * @dev_get_busparams:		readback arbitration busparams
- * @dev_set_data_bittiming:	used for can.do_set_data_bittiming
+ * @dev_set_data_bittiming:	used for can.fd.do_set_data_bittiming
  * @dev_get_data_busparams:	readback data busparams
  * @dev_get_berr_counter:	used for can.do_get_berr_counter
  *
  * @dev_setup_endpoints:	setup USB in and out endpoints
  * @dev_init_card:		initialize card
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
index dcb0bcbe0565..daf42080f942 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
@@ -590,11 +590,11 @@ static int kvaser_usb_set_bittiming(struct net_device *netdev)
 static int kvaser_usb_set_data_bittiming(struct net_device *netdev)
 {
 	struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
 	struct kvaser_usb *dev = priv->dev;
 	const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
-	struct can_bittiming *dbt = &priv->can.data_bittiming;
+	struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
 	struct kvaser_usb_busparams busparams;
 	int tseg1 = dbt->prop_seg + dbt->phase_seg1;
 	int tseg2 = dbt->phase_seg2;
 	int sjw = dbt->sjw;
 	int err;
@@ -840,12 +840,12 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
 		priv->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
 
 	priv->can.ctrlmode_supported |= dev->card_data.ctrlmode_supported;
 
 	if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) {
-		priv->can.data_bittiming_const = dev->cfg->data_bittiming_const;
-		priv->can.do_set_data_bittiming = kvaser_usb_set_data_bittiming;
+		priv->can.fd.data_bittiming_const = dev->cfg->data_bittiming_const;
+		priv->can.fd.do_set_data_bittiming = kvaser_usb_set_data_bittiming;
 	}
 
 	netdev->flags |= IFF_ECHO;
 
 	netdev->netdev_ops = &kvaser_usb_netdev_ops;
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
index 59f7cd8ceb39..117637b9b995 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
@@ -768,11 +768,11 @@ static int peak_usb_set_data_bittiming(struct net_device *netdev)
 {
 	struct peak_usb_device *dev = netdev_priv(netdev);
 	const struct peak_usb_adapter *pa = dev->adapter;
 
 	if (pa->dev_set_data_bittiming) {
-		struct can_bittiming *bt = &dev->can.data_bittiming;
+		struct can_bittiming *bt = &dev->can.fd.data_bittiming;
 		int err = pa->dev_set_data_bittiming(dev, bt);
 
 		if (err)
 			netdev_info(netdev,
 				    "couldn't set data bitrate (err %d)\n",
@@ -952,12 +952,12 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter,
 	dev->ep_msg_out = peak_usb_adapter->ep_msg_out[ctrl_idx];
 
 	dev->can.clock = peak_usb_adapter->clock;
 	dev->can.bittiming_const = peak_usb_adapter->bittiming_const;
 	dev->can.do_set_bittiming = peak_usb_set_bittiming;
-	dev->can.data_bittiming_const = peak_usb_adapter->data_bittiming_const;
-	dev->can.do_set_data_bittiming = peak_usb_set_data_bittiming;
+	dev->can.fd.data_bittiming_const = peak_usb_adapter->data_bittiming_const;
+	dev->can.fd.do_set_data_bittiming = peak_usb_set_data_bittiming;
 	dev->can.do_set_mode = peak_usb_set_mode;
 	dev->can.do_get_berr_counter = peak_usb_adapter->do_get_berr_counter;
 	dev->can.ctrlmode_supported = peak_usb_adapter->ctrlmode_supported;
 
 	netdev->netdev_ops = &peak_usb_netdev_ops;
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
index 436c0e4b0344..3f2e378199ab 100644
--- a/drivers/net/can/xilinx_can.c
+++ b/drivers/net/can/xilinx_can.c
@@ -479,11 +479,11 @@ static int set_reset_mode(struct net_device *ndev)
  */
 static int xcan_set_bittiming(struct net_device *ndev)
 {
 	struct xcan_priv *priv = netdev_priv(ndev);
 	struct can_bittiming *bt = &priv->can.bittiming;
-	struct can_bittiming *dbt = &priv->can.data_bittiming;
+	struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
 	u32 btr0, btr1;
 	u32 is_config_mode;
 
 	/* Check whether Xilinx CAN is in configuration mode.
 	 * It cannot set bit timing if Xilinx CAN is not in configuration mode.
@@ -515,14 +515,14 @@ static int xcan_set_bittiming(struct net_device *ndev)
 	    priv->devtype.cantype == XAXI_CANFD_2_0) {
 		/* Setting Baud Rate prescaler value in F_BRPR Register */
 		btr0 = dbt->brp - 1;
 		if (can_tdc_is_enabled(&priv->can)) {
 			if (priv->devtype.cantype == XAXI_CANFD)
-				btr0 |= FIELD_PREP(XCAN_BRPR_TDCO_MASK, priv->can.tdc.tdco) |
+				btr0 |= FIELD_PREP(XCAN_BRPR_TDCO_MASK, priv->can.fd.tdc.tdco) |
 					XCAN_BRPR_TDC_ENABLE;
 			else
-				btr0 |= FIELD_PREP(XCAN_2_BRPR_TDCO_MASK, priv->can.tdc.tdco) |
+				btr0 |= FIELD_PREP(XCAN_2_BRPR_TDCO_MASK, priv->can.fd.tdc.tdco) |
 					XCAN_BRPR_TDC_ENABLE;
 		}
 
 		/* Setting Time Segment 1 in BTR Register */
 		btr1 = dbt->prop_seg + dbt->phase_seg1 - 1;
@@ -1965,26 +1965,26 @@ static int xcan_probe(struct platform_device *pdev)
 	ret = reset_control_reset(priv->rstc);
 	if (ret)
 		goto err_free;
 
 	if (devtype->cantype == XAXI_CANFD) {
-		priv->can.data_bittiming_const =
+		priv->can.fd.data_bittiming_const =
 			&xcan_data_bittiming_const_canfd;
-		priv->can.tdc_const = &xcan_tdc_const_canfd;
+		priv->can.fd.tdc_const = &xcan_tdc_const_canfd;
 	}
 
 	if (devtype->cantype == XAXI_CANFD_2_0) {
-		priv->can.data_bittiming_const =
+		priv->can.fd.data_bittiming_const =
 			&xcan_data_bittiming_const_canfd2;
-		priv->can.tdc_const = &xcan_tdc_const_canfd2;
+		priv->can.fd.tdc_const = &xcan_tdc_const_canfd2;
 	}
 
 	if (devtype->cantype == XAXI_CANFD ||
 	    devtype->cantype == XAXI_CANFD_2_0) {
 		priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD |
 						CAN_CTRLMODE_TDC_AUTO;
-		priv->can.do_get_auto_tdcv = xcan_get_auto_tdcv;
+		priv->can.fd.do_get_auto_tdcv = xcan_get_auto_tdcv;
 	}
 
 	priv->reg_base = addr;
 	priv->tx_max = tx_max;
 	priv->devtype = *devtype;
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 23492213ea35..492d23bec7be 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -36,27 +36,33 @@ enum can_termination_gpio {
 	CAN_TERMINATION_GPIO_DISABLED = 0,
 	CAN_TERMINATION_GPIO_ENABLED,
 	CAN_TERMINATION_GPIO_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 u32 *data_bitrate_const;
+	unsigned int data_bitrate_const_cnt;
+	int (*do_set_data_bittiming)(struct net_device *dev);
+	int (*do_get_auto_tdcv)(const struct net_device *dev, u32 *tdcv);
+};
+
 /*
  * CAN common private data
  */
 struct can_priv {
 	struct net_device *dev;
 	struct can_device_stats can_stats;
 
-	const struct can_bittiming_const *bittiming_const,
-		*data_bittiming_const;
-	struct can_bittiming bittiming, data_bittiming;
-	const struct can_tdc_const *tdc_const;
-	struct can_tdc tdc;
-
+	const struct can_bittiming_const *bittiming_const;
+	struct can_bittiming bittiming;
+	struct data_bittiming_params fd;
 	unsigned int bitrate_const_cnt;
 	const u32 *bitrate_const;
-	const u32 *data_bitrate_const;
-	unsigned int data_bitrate_const_cnt;
 	u32 bitrate_max;
 	struct can_clock clock;
 
 	unsigned int termination_const_cnt;
 	const u16 *termination_const;
@@ -75,18 +81,16 @@ struct can_priv {
 
 	int restart_ms;
 	struct delayed_work restart_work;
 
 	int (*do_set_bittiming)(struct net_device *dev);
-	int (*do_set_data_bittiming)(struct net_device *dev);
 	int (*do_set_mode)(struct net_device *dev, enum can_mode mode);
 	int (*do_set_termination)(struct net_device *dev, u16 term);
 	int (*do_get_state)(const struct net_device *dev,
 			    enum can_state *state);
 	int (*do_get_berr_counter)(const struct net_device *dev,
 				   struct can_berr_counter *bec);
-	int (*do_get_auto_tdcv)(const struct net_device *dev, u32 *tdcv);
 };
 
 static inline bool can_tdc_is_enabled(const struct can_priv *priv)
 {
 	return !!(priv->ctrlmode & CAN_CTRLMODE_TDC_MASK);
@@ -112,15 +116,15 @@ static inline bool can_tdc_is_enabled(const struct can_priv *priv)
  *                           |                      |<->| relative TDCO
  *  |<------------- Secondary Sample Point ------------>|
  */
 static inline s32 can_get_relative_tdco(const struct can_priv *priv)
 {
-	const struct can_bittiming *dbt = &priv->data_bittiming;
+	const struct can_bittiming *dbt = &priv->fd.data_bittiming;
 	s32 sample_point_in_tc = (CAN_SYNC_SEG + dbt->prop_seg +
 				  dbt->phase_seg1) * dbt->brp;
 
-	return (s32)priv->tdc.tdco - sample_point_in_tc;
+	return (s32)priv->fd.tdc.tdco - sample_point_in_tc;
 }
 
 /* helper to define static CAN controller features at device creation time */
 static inline int __must_check can_set_static_ctrlmode(struct net_device *dev,
 						       u32 static_mode)
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 02/11] can: netlink: replace tabulation by space in assignment
  2025-05-27 19:56 [PATCH 01/11] can: dev: add struct data_bittiming_params to group FD parameters Oliver Hartkopp
@ 2025-05-27 19:56 ` Oliver Hartkopp
  2025-05-28  8:47   ` Marc Kleine-Budde
  2025-05-27 19:56 ` [PATCH 03/11] can: bittiming: rename CAN_CTRLMODE_TDC_MASK into CAN_CTRLMODE_FD_TDC_MASK Oliver Hartkopp
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 22+ messages in thread
From: Oliver Hartkopp @ 2025-05-27 19:56 UTC (permalink / raw)
  To: linux-can; +Cc: Vincent Mailhol

From: Vincent Mailhol <mailhol.vincent@wanadoo.fr>

commit cfd98c838cbe ("can: netlink: move '=' operators back to
previous line (checkpatch fix)") inadvertently introduced a tabulation
between the IFLA_CAN_DATA_BITTIMING_CONST array index and the equal
sign.

Remove it.

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
---
 drivers/net/can/dev/netlink.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
index a36842ace084..4ebd5181aea9 100644
--- a/drivers/net/can/dev/netlink.c
+++ b/drivers/net/can/dev/netlink.c
@@ -16,11 +16,11 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
 	[IFLA_CAN_BITTIMING] = { .len = sizeof(struct can_bittiming) },
 	[IFLA_CAN_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) },
 	[IFLA_CAN_CLOCK] = { .len = sizeof(struct can_clock) },
 	[IFLA_CAN_BERR_COUNTER] = { .len = sizeof(struct can_berr_counter) },
 	[IFLA_CAN_DATA_BITTIMING] = { .len = sizeof(struct can_bittiming) },
-	[IFLA_CAN_DATA_BITTIMING_CONST]	= { .len = sizeof(struct can_bittiming_const) },
+	[IFLA_CAN_DATA_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) },
 	[IFLA_CAN_TERMINATION] = { .type = NLA_U16 },
 	[IFLA_CAN_TDC] = { .type = NLA_NESTED },
 	[IFLA_CAN_CTRLMODE_EXT] = { .type = NLA_NESTED },
 };
 
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 03/11] can: bittiming: rename CAN_CTRLMODE_TDC_MASK into CAN_CTRLMODE_FD_TDC_MASK
  2025-05-27 19:56 [PATCH 01/11] can: dev: add struct data_bittiming_params to group FD parameters Oliver Hartkopp
  2025-05-27 19:56 ` [PATCH 02/11] can: netlink: replace tabulation by space in assignment Oliver Hartkopp
@ 2025-05-27 19:56 ` Oliver Hartkopp
  2025-05-27 19:56 ` [PATCH 04/11] can: bittiming: rename can_tdc_is_enabled() into can_fd_tdc_is_enabled() Oliver Hartkopp
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Oliver Hartkopp @ 2025-05-27 19:56 UTC (permalink / raw)
  To: linux-can; +Cc: Vincent Mailhol

From: Vincent Mailhol <mailhol.vincent@wanadoo.fr>

With the introduction of CAN XL, a new CAN_CTRLMODE_XL_TDC_MASK will
be introduced later on. Because CAN_CTRLMODE_TDC_MASK is not part of
the uapi, rename it to CAN_CTRLMODE_FD_TDC_MASK to make it more
explicit that this mask is meant for CAN FD.

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
---
 drivers/net/can/dev/calc_bittiming.c |  2 +-
 drivers/net/can/dev/netlink.c        | 12 ++++++------
 include/linux/can/bittiming.h        |  2 +-
 include/linux/can/dev.h              |  2 +-
 4 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/can/dev/calc_bittiming.c b/drivers/net/can/dev/calc_bittiming.c
index 3809c148fb88..a94bd67c670c 100644
--- a/drivers/net/can/dev/calc_bittiming.c
+++ b/drivers/net/can/dev/calc_bittiming.c
@@ -177,11 +177,11 @@ void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const,
 
 {
 	if (!tdc_const || !(ctrlmode_supported & CAN_CTRLMODE_TDC_AUTO))
 		return;
 
-	*ctrlmode &= ~CAN_CTRLMODE_TDC_MASK;
+	*ctrlmode &= ~CAN_CTRLMODE_FD_TDC_MASK;
 
 	/* As specified in ISO 11898-1 section 11.3.3 "Transmitter
 	 * delay compensation" (TDC) is only applicable if data BRP is
 	 * one or two.
 	 */
diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
index 4ebd5181aea9..08261cfcf6b2 100644
--- a/drivers/net/can/dev/netlink.c
+++ b/drivers/net/can/dev/netlink.c
@@ -65,16 +65,16 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
 	if (!data)
 		return 0;
 
 	if (data[IFLA_CAN_CTRLMODE]) {
 		struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
-		u32 tdc_flags = cm->flags & CAN_CTRLMODE_TDC_MASK;
+		u32 tdc_flags = cm->flags & CAN_CTRLMODE_FD_TDC_MASK;
 
 		is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD;
 
 		/* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually exclusive */
-		if (tdc_flags == CAN_CTRLMODE_TDC_MASK)
+		if (tdc_flags == CAN_CTRLMODE_FD_TDC_MASK)
 			return -EOPNOTSUPP;
 		/* If one of the CAN_CTRLMODE_TDC_* flag is set then
 		 * TDC must be set and vice-versa
 		 */
 		if (!!tdc_flags != !!data[IFLA_CAN_TDC])
@@ -228,20 +228,20 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 			dev->mtu = CANFD_MTU;
 		} else {
 			dev->mtu = CAN_MTU;
 			memset(&priv->fd.data_bittiming, 0,
 			       sizeof(priv->fd.data_bittiming));
-			priv->ctrlmode &= ~CAN_CTRLMODE_TDC_MASK;
+			priv->ctrlmode &= ~CAN_CTRLMODE_FD_TDC_MASK;
 			memset(&priv->fd.tdc, 0, sizeof(priv->fd.tdc));
 		}
 
-		tdc_mask = cm->mask & CAN_CTRLMODE_TDC_MASK;
+		tdc_mask = cm->mask & CAN_CTRLMODE_FD_TDC_MASK;
 		/* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually
 		 * exclusive: make sure to turn the other one off
 		 */
 		if (tdc_mask)
-			priv->ctrlmode &= cm->flags | ~CAN_CTRLMODE_TDC_MASK;
+			priv->ctrlmode &= cm->flags | ~CAN_CTRLMODE_FD_TDC_MASK;
 	}
 
 	if (data[IFLA_CAN_BITTIMING]) {
 		struct can_bittiming bt;
 
@@ -337,11 +337,11 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 		if (data[IFLA_CAN_TDC]) {
 			/* TDC parameters are provided: use them */
 			err = can_tdc_changelink(priv, data[IFLA_CAN_TDC],
 						 extack);
 			if (err) {
-				priv->ctrlmode &= ~CAN_CTRLMODE_TDC_MASK;
+				priv->ctrlmode &= ~CAN_CTRLMODE_FD_TDC_MASK;
 				return err;
 			}
 		} else if (!tdc_mask) {
 			/* Neither of TDC parameters nor TDC flags are
 			 * provided: do calculation
diff --git a/include/linux/can/bittiming.h b/include/linux/can/bittiming.h
index 9b8a9c39614b..5dfdbb63b1d5 100644
--- a/include/linux/can/bittiming.h
+++ b/include/linux/can/bittiming.h
@@ -12,11 +12,11 @@
 #define CAN_SYNC_SEG 1
 
 #define CAN_BITRATE_UNSET 0
 #define CAN_BITRATE_UNKNOWN (-1U)
 
-#define CAN_CTRLMODE_TDC_MASK					\
+#define CAN_CTRLMODE_FD_TDC_MASK				\
 	(CAN_CTRLMODE_TDC_AUTO | CAN_CTRLMODE_TDC_MANUAL)
 
 /*
  * struct can_tdc - CAN FD Transmission Delay Compensation parameters
  *
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 492d23bec7be..e492dfa8a472 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -91,11 +91,11 @@ struct can_priv {
 				   struct can_berr_counter *bec);
 };
 
 static inline bool can_tdc_is_enabled(const struct can_priv *priv)
 {
-	return !!(priv->ctrlmode & CAN_CTRLMODE_TDC_MASK);
+	return !!(priv->ctrlmode & CAN_CTRLMODE_FD_TDC_MASK);
 }
 
 /*
  * can_get_relative_tdco() - TDCO relative to the sample point
  *
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 04/11] can: bittiming: rename can_tdc_is_enabled() into can_fd_tdc_is_enabled()
  2025-05-27 19:56 [PATCH 01/11] can: dev: add struct data_bittiming_params to group FD parameters Oliver Hartkopp
  2025-05-27 19:56 ` [PATCH 02/11] can: netlink: replace tabulation by space in assignment Oliver Hartkopp
  2025-05-27 19:56 ` [PATCH 03/11] can: bittiming: rename CAN_CTRLMODE_TDC_MASK into CAN_CTRLMODE_FD_TDC_MASK Oliver Hartkopp
@ 2025-05-27 19:56 ` Oliver Hartkopp
  2025-05-27 19:56 ` [PATCH 05/11] can: netlink: can_changelink(): rename tdc_mask into fd_tdc_flag_provided Oliver Hartkopp
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Oliver Hartkopp @ 2025-05-27 19:56 UTC (permalink / raw)
  To: linux-can; +Cc: Vincent Mailhol

From: Vincent Mailhol <mailhol.vincent@wanadoo.fr>

With the introduction of CAN XL, a new can_xl_tdc_is_enabled() helper
function will be introduced later on. Rename can_tdc_is_enabled() into
can_fd_tdc_is_enabled() to make it more explicit that this helper is
meant for CAN FD.

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
---
 drivers/net/can/dev/netlink.c             | 6 +++---
 drivers/net/can/usb/etas_es58x/es58x_fd.c | 2 +-
 drivers/net/can/xilinx_can.c              | 2 +-
 include/linux/can/dev.h                   | 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
index 08261cfcf6b2..16b0f326c143 100644
--- a/drivers/net/can/dev/netlink.c
+++ b/drivers/net/can/dev/netlink.c
@@ -142,11 +142,11 @@ static int can_tdc_changelink(struct can_priv *priv, const struct nlattr *nla,
 	struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1];
 	struct can_tdc tdc = { 0 };
 	const struct can_tdc_const *tdc_const = priv->fd.tdc_const;
 	int err;
 
-	if (!tdc_const || !can_tdc_is_enabled(priv))
+	if (!tdc_const || !can_fd_tdc_is_enabled(priv))
 		return -EOPNOTSUPP;
 
 	err = nla_parse_nested(tb_tdc, IFLA_CAN_TDC_MAX, nla,
 			       can_tdc_policy, extack);
 	if (err)
@@ -407,11 +407,11 @@ static size_t can_tdc_get_size(const struct net_device *dev)
 	if (priv->fd.tdc_const->tdcf_max) {
 		size += nla_total_size(sizeof(u32));	/* IFLA_CAN_TDCF_MIN */
 		size += nla_total_size(sizeof(u32));	/* IFLA_CAN_TDCF_MAX */
 	}
 
-	if (can_tdc_is_enabled(priv)) {
+	if (can_fd_tdc_is_enabled(priv)) {
 		if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL ||
 		    priv->fd.do_get_auto_tdcv)
 			size += nla_total_size(sizeof(u32));	/* IFLA_CAN_TDCV */
 		size += nla_total_size(sizeof(u32));		/* IFLA_CAN_TDCO */
 		if (priv->fd.tdc_const->tdcf_max)
@@ -488,11 +488,11 @@ static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev)
 	if (tdc_const->tdcf_max &&
 	    (nla_put_u32(skb, IFLA_CAN_TDC_TDCF_MIN, tdc_const->tdcf_min) ||
 	     nla_put_u32(skb, IFLA_CAN_TDC_TDCF_MAX, tdc_const->tdcf_max)))
 		goto err_cancel;
 
-	if (can_tdc_is_enabled(priv)) {
+	if (can_fd_tdc_is_enabled(priv)) {
 		u32 tdcv;
 		int err = -EINVAL;
 
 		if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL) {
 			tdcv = tdc->tdcv;
diff --git a/drivers/net/can/usb/etas_es58x/es58x_fd.c b/drivers/net/can/usb/etas_es58x/es58x_fd.c
index d924b053677b..6476add1c105 100644
--- a/drivers/net/can/usb/etas_es58x/es58x_fd.c
+++ b/drivers/net/can/usb/etas_es58x/es58x_fd.c
@@ -427,11 +427,11 @@ static int es58x_fd_enable_channel(struct es58x_priv *priv)
 
 	if (tx_conf_msg.canfd_enabled) {
 		es58x_fd_convert_bittiming(&tx_conf_msg.data_bittiming,
 					   &priv->can.fd.data_bittiming);
 
-		if (can_tdc_is_enabled(&priv->can)) {
+		if (can_fd_tdc_is_enabled(&priv->can)) {
 			tx_conf_msg.tdc_enabled = 1;
 			tx_conf_msg.tdco = cpu_to_le16(priv->can.fd.tdc.tdco);
 			tx_conf_msg.tdcf = cpu_to_le16(priv->can.fd.tdc.tdcf);
 		}
 
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
index 3f2e378199ab..81baec8eb1e5 100644
--- a/drivers/net/can/xilinx_can.c
+++ b/drivers/net/can/xilinx_can.c
@@ -513,11 +513,11 @@ static int xcan_set_bittiming(struct net_device *ndev)
 
 	if (priv->devtype.cantype == XAXI_CANFD ||
 	    priv->devtype.cantype == XAXI_CANFD_2_0) {
 		/* Setting Baud Rate prescaler value in F_BRPR Register */
 		btr0 = dbt->brp - 1;
-		if (can_tdc_is_enabled(&priv->can)) {
+		if (can_fd_tdc_is_enabled(&priv->can)) {
 			if (priv->devtype.cantype == XAXI_CANFD)
 				btr0 |= FIELD_PREP(XCAN_BRPR_TDCO_MASK, priv->can.fd.tdc.tdco) |
 					XCAN_BRPR_TDC_ENABLE;
 			else
 				btr0 |= FIELD_PREP(XCAN_2_BRPR_TDCO_MASK, priv->can.fd.tdc.tdco) |
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index e492dfa8a472..9a92cbe5b2cb 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -89,11 +89,11 @@ struct can_priv {
 			    enum can_state *state);
 	int (*do_get_berr_counter)(const struct net_device *dev,
 				   struct can_berr_counter *bec);
 };
 
-static inline bool can_tdc_is_enabled(const struct can_priv *priv)
+static inline bool can_fd_tdc_is_enabled(const struct can_priv *priv)
 {
 	return !!(priv->ctrlmode & CAN_CTRLMODE_FD_TDC_MASK);
 }
 
 /*
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 05/11] can: netlink: can_changelink(): rename tdc_mask into fd_tdc_flag_provided
  2025-05-27 19:56 [PATCH 01/11] can: dev: add struct data_bittiming_params to group FD parameters Oliver Hartkopp
                   ` (2 preceding siblings ...)
  2025-05-27 19:56 ` [PATCH 04/11] can: bittiming: rename can_tdc_is_enabled() into can_fd_tdc_is_enabled() Oliver Hartkopp
@ 2025-05-27 19:56 ` Oliver Hartkopp
  2025-05-27 19:56 ` [PATCH 06/11] can: netlink: add CAN XL support Oliver Hartkopp
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Oliver Hartkopp @ 2025-05-27 19:56 UTC (permalink / raw)
  To: linux-can; +Cc: Vincent Mailhol

From: Vincent Mailhol <mailhol.vincent@wanadoo.fr>

The only purpose of the tdc_mask variable is to check whether or not
any tdc flags (CAN_CTRLMODE_TDC_{AUTO,MANUAL}) were provided. At this
point, the actual value of the flags do no matter any more because
these can be deduced from some other information.

Rename the tdc_mask variable into fd_tdc_flag_provided to make this
more explicit. Note that the fd_ prefix is added in preparation of the
introduction of CAN XL.

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
---
 drivers/net/can/dev/netlink.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
index 16b0f326c143..13826e8a707b 100644
--- a/drivers/net/can/dev/netlink.c
+++ b/drivers/net/can/dev/netlink.c
@@ -187,11 +187,11 @@ static int can_tdc_changelink(struct can_priv *priv, const struct nlattr *nla,
 static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 			  struct nlattr *data[],
 			  struct netlink_ext_ack *extack)
 {
 	struct can_priv *priv = netdev_priv(dev);
-	u32 tdc_mask = 0;
+	bool fd_tdc_flag_provided = false;
 	int err;
 
 	/* We need synchronization with dev->stop() */
 	ASSERT_RTNL();
 
@@ -232,15 +232,15 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 			       sizeof(priv->fd.data_bittiming));
 			priv->ctrlmode &= ~CAN_CTRLMODE_FD_TDC_MASK;
 			memset(&priv->fd.tdc, 0, sizeof(priv->fd.tdc));
 		}
 
-		tdc_mask = cm->mask & CAN_CTRLMODE_FD_TDC_MASK;
+		fd_tdc_flag_provided = cm->mask & CAN_CTRLMODE_FD_TDC_MASK;
 		/* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually
 		 * exclusive: make sure to turn the other one off
 		 */
-		if (tdc_mask)
+		if (fd_tdc_flag_provided)
 			priv->ctrlmode &= cm->flags | ~CAN_CTRLMODE_FD_TDC_MASK;
 	}
 
 	if (data[IFLA_CAN_BITTIMING]) {
 		struct can_bittiming bt;
@@ -340,11 +340,11 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 						 extack);
 			if (err) {
 				priv->ctrlmode &= ~CAN_CTRLMODE_FD_TDC_MASK;
 				return err;
 			}
-		} else if (!tdc_mask) {
+		} else if (!fd_tdc_flag_provided) {
 			/* Neither of TDC parameters nor TDC flags are
 			 * provided: do calculation
 			 */
 			can_calc_tdco(&priv->fd.tdc, priv->fd.tdc_const, &dbt,
 				      &priv->ctrlmode, priv->ctrlmode_supported);
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 06/11] can: netlink: add CAN XL support
  2025-05-27 19:56 [PATCH 01/11] can: dev: add struct data_bittiming_params to group FD parameters Oliver Hartkopp
                   ` (3 preceding siblings ...)
  2025-05-27 19:56 ` [PATCH 05/11] can: netlink: can_changelink(): rename tdc_mask into fd_tdc_flag_provided Oliver Hartkopp
@ 2025-05-27 19:56 ` Oliver Hartkopp
  2025-05-29  6:57   ` Marc Kleine-Budde
  2025-05-27 19:56 ` [PATCH 07/11] can: canxl: support Remote Request Substitution bit access Oliver Hartkopp
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 22+ messages in thread
From: Oliver Hartkopp @ 2025-05-27 19:56 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp

Based on the Vincent Mailhols CAN XL preparations patch set
"can: netlink: preparation before introduction of CAN XL"
https://lore.kernel.org/linux-can/20241112165118.586613-7-mailhol.vincent@wanadoo.fr/T/#t

Fixes from Oliver:
- add can_validate_tdc(data[IFLA_CAN_XL_TDC], ..) in can_validate()
- fix nested can_tdc_fill_info() to support CAN XL too
- fix copy/paste issue in CAN_CTRLMODE_XL_TDC_ definitions

Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
 drivers/net/can/dev/netlink.c    | 392 +++++++++++++++++++++----------
 drivers/net/can/xilinx_can.c     |  12 +-
 include/linux/can/bittiming.h    |   2 +
 include/linux/can/dev.h          |  13 +-
 include/uapi/linux/can/netlink.h |  21 +-
 5 files changed, 296 insertions(+), 144 deletions(-)

diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
index 13826e8a707b..1b798a7dcd64 100644
--- a/drivers/net/can/dev/netlink.c
+++ b/drivers/net/can/dev/netlink.c
@@ -20,10 +20,13 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
 	[IFLA_CAN_DATA_BITTIMING] = { .len = sizeof(struct can_bittiming) },
 	[IFLA_CAN_DATA_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) },
 	[IFLA_CAN_TERMINATION] = { .type = NLA_U16 },
 	[IFLA_CAN_TDC] = { .type = NLA_NESTED },
 	[IFLA_CAN_CTRLMODE_EXT] = { .type = NLA_NESTED },
+	[IFLA_CAN_XL_DATA_BITTIMING] = { .len = sizeof(struct can_bittiming) },
+	[IFLA_CAN_XL_DATA_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) },
+	[IFLA_CAN_XL_TDC] = { .type = NLA_NESTED },
 };
 
 static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = {
 	[IFLA_CAN_TDC_TDCV_MIN] = { .type = NLA_U32 },
 	[IFLA_CAN_TDC_TDCV_MAX] = { .type = NLA_U32 },
@@ -47,14 +50,60 @@ static int can_validate_bittiming(const struct can_bittiming *bt,
 	}
 
 	return 0;
 }
 
+static int can_validate_tdc(struct nlattr *data_tdc,
+			    bool tdc_auto, bool tdc_manual,
+			    struct netlink_ext_ack *extack)
+{
+	int err;
+
+	/* TDC is optional */
+	if (!data_tdc)
+		return 0;
+
+	/* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually exclusive */
+	if (tdc_auto == tdc_manual)
+		return -EOPNOTSUPP;
+
+	/* If one of the CAN_CTRLMODE_TDC_* flag is set then
+	 * TDC must be set and vice-versa
+	 */
+	if ((tdc_auto || tdc_manual) != !!data_tdc)
+		return -EOPNOTSUPP;
+
+	/* If providing TDC parameters, at least TDCO is needed. TDCV
+	 * is needed if and only if CAN_CTRLMODE_TDC_MANUAL is set
+	 */
+	if (!data_tdc) {
+		struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1];
+
+		err = nla_parse_nested(tb_tdc, IFLA_CAN_TDC_MAX,
+				       data_tdc, can_tdc_policy, extack);
+		if (err)
+			return err;
+
+		if (tb_tdc[IFLA_CAN_TDC_TDCV]) {
+			if (tdc_auto)
+				return -EOPNOTSUPP;
+		} else {
+			if (tdc_manual)
+				return -EOPNOTSUPP;
+		}
+
+		if (!tb_tdc[IFLA_CAN_TDC_TDCO])
+			return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
 static int can_validate(struct nlattr *tb[], struct nlattr *data[],
 			struct netlink_ext_ack *extack)
 {
-	bool is_can_fd = false;
+	bool is_can_fd = false, is_can_xl = false;
 	int err;
 
 	/* Make sure that valid CAN FD configurations always consist of
 	 * - nominal/arbitration bittiming
 	 * - data bittiming
@@ -65,88 +114,112 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
 	if (!data)
 		return 0;
 
 	if (data[IFLA_CAN_CTRLMODE]) {
 		struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
-		u32 tdc_flags = cm->flags & CAN_CTRLMODE_FD_TDC_MASK;
 
 		is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD;
+		is_can_xl = cm->flags & cm->mask & CAN_CTRLMODE_XL;
 
-		/* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually exclusive */
-		if (tdc_flags == CAN_CTRLMODE_FD_TDC_MASK)
-			return -EOPNOTSUPP;
-		/* If one of the CAN_CTRLMODE_TDC_* flag is set then
-		 * TDC must be set and vice-versa
-		 */
-		if (!!tdc_flags != !!data[IFLA_CAN_TDC])
-			return -EOPNOTSUPP;
-		/* If providing TDC parameters, at least TDCO is
-		 * needed. TDCV is needed if and only if
-		 * CAN_CTRLMODE_TDC_MANUAL is set
-		 */
-		if (data[IFLA_CAN_TDC]) {
-			struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1];
-
-			err = nla_parse_nested(tb_tdc, IFLA_CAN_TDC_MAX,
-					       data[IFLA_CAN_TDC],
-					       can_tdc_policy, extack);
-			if (err)
-				return err;
-
-			if (tb_tdc[IFLA_CAN_TDC_TDCV]) {
-				if (tdc_flags & CAN_CTRLMODE_TDC_AUTO)
-					return -EOPNOTSUPP;
-			} else {
-				if (tdc_flags & CAN_CTRLMODE_TDC_MANUAL)
-					return -EOPNOTSUPP;
-			}
-
-			if (!tb_tdc[IFLA_CAN_TDC_TDCO])
-				return -EOPNOTSUPP;
+		err = can_validate_tdc(data[IFLA_CAN_TDC],
+				       cm->flags & CAN_CTRLMODE_TDC_AUTO,
+				       cm->flags & CAN_CTRLMODE_TDC_MANUAL,
+				       extack);
+		if (err) {
+			NL_SET_ERR_MSG_FMT(extack,
+					   "TDC parameters are incorrect");
+			return err;
+		}
+		err = can_validate_tdc(data[IFLA_CAN_XL_TDC],
+				       cm->flags & CAN_CTRLMODE_XL_TDC_AUTO,
+				       cm->flags & CAN_CTRLMODE_XL_TDC_MANUAL,
+				       extack);
+		if (err) {
+			NL_SET_ERR_MSG_FMT(extack,
+					   "XL TDC parameters are incorrect");
+			return err;
 		}
 	}
 
 	if (data[IFLA_CAN_BITTIMING]) {
 		struct can_bittiming bt;
 
 		memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt));
 		err = can_validate_bittiming(&bt, extack);
-		if (err)
+		if (err) {
+			NL_SET_ERR_MSG_FMT(extack,
+					   "Nominal bittiming parameters are incorrect");
 			return err;
+		}
 	}
 
 	if (is_can_fd) {
-		if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_DATA_BITTIMING])
+		if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_DATA_BITTIMING]) {
+			NL_SET_ERR_MSG_FMT(extack,
+					   "Provide both nominal and FD data bittiming");
+			return -EOPNOTSUPP;
+		}
+	}
+	if (is_can_xl) {
+		if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_XL_DATA_BITTIMING]) {
+			NL_SET_ERR_MSG_FMT(extack,
+					   "Provide both nominal and XL data bittiming");
 			return -EOPNOTSUPP;
+		}
 	}
 
 	if (data[IFLA_CAN_DATA_BITTIMING] || data[IFLA_CAN_TDC]) {
-		if (!is_can_fd)
+		if (!is_can_fd) {
+			NL_SET_ERR_MSG_FMT(extack,
+					   "CAN FD is required to use FD data bittiming or FD TDC");
+			return -EOPNOTSUPP;
+		}
+	}
+	if (data[IFLA_CAN_XL_DATA_BITTIMING] || data[IFLA_CAN_XL_TDC]) {
+		if (!is_can_xl) {
+			NL_SET_ERR_MSG_FMT(extack,
+					   "CAN XL is required to use XL data bittiming or XL TDC");
 			return -EOPNOTSUPP;
+		}
 	}
 
 	if (data[IFLA_CAN_DATA_BITTIMING]) {
 		struct can_bittiming bt;
 
 		memcpy(&bt, nla_data(data[IFLA_CAN_DATA_BITTIMING]), sizeof(bt));
 		err = can_validate_bittiming(&bt, extack);
-		if (err)
+		if (err) {
+			NL_SET_ERR_MSG_FMT(extack,
+					   "FD data bittiming parameters are incorrect");
 			return err;
+		}
+	}
+	if (data[IFLA_CAN_XL_DATA_BITTIMING]) {
+		struct can_bittiming bt;
+
+		memcpy(&bt, nla_data(data[IFLA_CAN_XL_DATA_BITTIMING]), sizeof(bt));
+		err = can_validate_bittiming(&bt, extack);
+		if (err) {
+			NL_SET_ERR_MSG_FMT(extack,
+					   "FD data bittiming parameters are incorrect");
+			return err;
+		}
 	}
 
 	return 0;
 }
 
-static int can_tdc_changelink(struct can_priv *priv, const struct nlattr *nla,
+static int can_tdc_changelink(struct data_bittiming_params *dbt_params,
+			      bool tdc_is_enabled, const struct nlattr *nla,
 			      struct netlink_ext_ack *extack)
 {
 	struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1];
 	struct can_tdc tdc = { 0 };
-	const struct can_tdc_const *tdc_const = priv->fd.tdc_const;
+	const struct can_tdc_const *tdc_const = dbt_params->tdc_const;
 	int err;
 
-	if (!tdc_const || !can_fd_tdc_is_enabled(priv))
+	if (!tdc_const || !tdc_is_enabled)
 		return -EOPNOTSUPP;
 
 	err = nla_parse_nested(tb_tdc, IFLA_CAN_TDC_MAX, nla,
 			       can_tdc_policy, extack);
 	if (err)
@@ -177,21 +250,92 @@ static int can_tdc_changelink(struct can_priv *priv, const struct nlattr *nla,
 			return -EINVAL;
 
 		tdc.tdcf = tdcf;
 	}
 
-	priv->fd.tdc = tdc;
+	dbt_params->tdc = tdc;
+
+	return 0;
+}
+
+static int can_dbt_changelink(struct net_device *dev,
+			      struct nlattr *data_databittiming,
+			      struct data_bittiming_params *dbt_params,
+			      struct nlattr *data_tdc, bool tdc_flags_provided,
+			      bool tdc_is_enabled, u32 tdc_mask,
+			      struct netlink_ext_ack *extack)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	struct can_bittiming dbt;
+	int err;
+
+	if (!data_databittiming)
+		return 0;
+
+	/* Do not allow changing bittiming while running */
+	if (dev->flags & IFF_UP)
+		return -EBUSY;
+
+	/* Calculate bittiming parameters based on data_bittiming_const
+	 * if set, otherwise pass bitrate directly via do_set_bitrate().
+	 * Bail out if neither is given.
+	 */
+	if (!dbt_params->data_bittiming_const && !dbt_params->do_set_data_bittiming &&
+	    !dbt_params->data_bitrate_const)
+		return -EOPNOTSUPP;
+
+	memcpy(&dbt, nla_data(data_databittiming), sizeof(dbt));
+	err = can_get_bittiming(dev, &dbt, dbt_params->data_bittiming_const,
+				dbt_params->data_bitrate_const,
+				dbt_params->data_bitrate_const_cnt, extack);
+	if (err)
+		return err;
+
+	if (priv->bitrate_max && dbt.bitrate > priv->bitrate_max) {
+		NL_SET_ERR_MSG_FMT(extack,
+				   "CAN data bitrate %u bps surpasses transceiver capabilities of %u bps",
+				   dbt.bitrate, priv->bitrate_max);
+		return -EINVAL;
+	}
+
+	memset(&dbt_params->tdc, 0, sizeof(dbt_params->tdc));
+	if (data_tdc) {
+		/* TDC parameters are provided: use them */
+		err = can_tdc_changelink(dbt_params, tdc_is_enabled, data_tdc,
+					 extack);
+		if (err) {
+			priv->ctrlmode &= ~tdc_mask;
+			return err;
+		}
+	} else if (!tdc_flags_provided) {
+		/* Neither of TDC parameters nor TDC flags are provided:
+		 * do calculation
+		 */
+		can_calc_tdco(&dbt_params->tdc, dbt_params->tdc_const, &dbt,
+			      &priv->ctrlmode, priv->ctrlmode_supported);
+	} /* else: both CAN_CTRLMODE_TDC_{AUTO,MANUAL} are explicitly
+	   * turned off. TDC is disabled: do nothing
+	   */
+
+	memcpy(&dbt_params->data_bittiming, &dbt, sizeof(dbt));
+
+	if (dbt_params->do_set_data_bittiming) {
+		/* Finally, set the bit-timing registers */
+		err = dbt_params->do_set_data_bittiming(dev);
+		if (err)
+			return err;
+	}
 
 	return 0;
 }
 
 static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 			  struct nlattr *data[],
 			  struct netlink_ext_ack *extack)
 {
+	bool fd_tdc_flag_provided = false, xl_tdc_flag_provided = false;
 	struct can_priv *priv = netdev_priv(dev);
-	bool fd_tdc_flag_provided = false;
 	int err;
 
 	/* We need synchronization with dev->stop() */
 	ASSERT_RTNL();
 
@@ -221,27 +365,32 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 
 		/* clear bits to be modified and copy the flag values */
 		priv->ctrlmode &= ~cm->mask;
 		priv->ctrlmode |= maskedflags;
 
-		/* CAN_CTRLMODE_FD can only be set when driver supports FD */
-		if (priv->ctrlmode & CAN_CTRLMODE_FD) {
+		/* CAN_CTRLMODE_{FD,XL} can only be set when driver supports FD/XL */
+		if (priv->ctrlmode & CAN_CTRLMODE_XL) {
+			dev->mtu = CANXL_MAX_MTU;
+		} else if (priv->ctrlmode & CAN_CTRLMODE_FD) {
 			dev->mtu = CANFD_MTU;
 		} else {
 			dev->mtu = CAN_MTU;
 			memset(&priv->fd.data_bittiming, 0,
 			       sizeof(priv->fd.data_bittiming));
 			priv->ctrlmode &= ~CAN_CTRLMODE_FD_TDC_MASK;
 			memset(&priv->fd.tdc, 0, sizeof(priv->fd.tdc));
 		}
 
 		fd_tdc_flag_provided = cm->mask & CAN_CTRLMODE_FD_TDC_MASK;
-		/* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually
+		xl_tdc_flag_provided = cm->mask & CAN_CTRLMODE_XL_TDC_MASK;
+		/* CAN_CTRLMODE_(XL_)TDC_{AUTO,MANUAL} are mutually
 		 * exclusive: make sure to turn the other one off
 		 */
 		if (fd_tdc_flag_provided)
 			priv->ctrlmode &= cm->flags | ~CAN_CTRLMODE_FD_TDC_MASK;
+		if (xl_tdc_flag_provided)
+			priv->ctrlmode &= cm->flags | ~CAN_CTRLMODE_XL_TDC_MASK;
 	}
 
 	if (data[IFLA_CAN_BITTIMING]) {
 		struct can_bittiming bt;
 
@@ -298,71 +447,26 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 		err = can_restart_now(dev);
 		if (err)
 			return err;
 	}
 
-	if (data[IFLA_CAN_DATA_BITTIMING]) {
-		struct can_bittiming dbt;
-
-		/* Do not allow changing bittiming while running */
-		if (dev->flags & IFF_UP)
-			return -EBUSY;
-
-		/* Calculate bittiming parameters based on
-		 * data_bittiming_const if set, otherwise pass bitrate
-		 * directly via do_set_bitrate(). Bail out if neither
-		 * is given.
-		 */
-		if (!priv->fd.data_bittiming_const && !priv->fd.do_set_data_bittiming &&
-		    !priv->fd.data_bitrate_const)
-			return -EOPNOTSUPP;
-
-		memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]),
-		       sizeof(dbt));
-		err = can_get_bittiming(dev, &dbt,
-					priv->fd.data_bittiming_const,
-					priv->fd.data_bitrate_const,
-					priv->fd.data_bitrate_const_cnt,
-					extack);
-		if (err)
-			return err;
-
-		if (priv->bitrate_max && dbt.bitrate > priv->bitrate_max) {
-			NL_SET_ERR_MSG_FMT(extack,
-					   "CANFD data bitrate %u bps surpasses transceiver capabilities of %u bps",
-					   dbt.bitrate, priv->bitrate_max);
-			return -EINVAL;
-		}
+	/* CAN FD */
+	err = can_dbt_changelink(dev, data[IFLA_CAN_DATA_BITTIMING], &priv->fd,
+				 data[IFLA_CAN_TDC], fd_tdc_flag_provided,
+				 can_fd_tdc_is_enabled(priv),
+				 CAN_CTRLMODE_FD_TDC_MASK, extack);
+	if (err)
+		return err;
 
-		memset(&priv->fd.tdc, 0, sizeof(priv->fd.tdc));
-		if (data[IFLA_CAN_TDC]) {
-			/* TDC parameters are provided: use them */
-			err = can_tdc_changelink(priv, data[IFLA_CAN_TDC],
-						 extack);
-			if (err) {
-				priv->ctrlmode &= ~CAN_CTRLMODE_FD_TDC_MASK;
-				return err;
-			}
-		} else if (!fd_tdc_flag_provided) {
-			/* Neither of TDC parameters nor TDC flags are
-			 * provided: do calculation
-			 */
-			can_calc_tdco(&priv->fd.tdc, priv->fd.tdc_const, &dbt,
-				      &priv->ctrlmode, priv->ctrlmode_supported);
-		} /* else: both CAN_CTRLMODE_TDC_{AUTO,MANUAL} are explicitly
-		   * turned off. TDC is disabled: do nothing
-		   */
-
-		memcpy(&priv->fd.data_bittiming, &dbt, sizeof(dbt));
-
-		if (priv->fd.do_set_data_bittiming) {
-			/* Finally, set the bit-timing registers */
-			err = priv->fd.do_set_data_bittiming(dev);
-			if (err)
-				return err;
-		}
-	}
+	/* CAN XL */
+	err = can_dbt_changelink(dev,
+				 data[IFLA_CAN_XL_DATA_BITTIMING], &priv->xl,
+				 data[IFLA_CAN_XL_TDC], xl_tdc_flag_provided,
+				 can_xl_tdc_is_enabled(priv),
+				 CAN_CTRLMODE_XL_TDC_MASK, extack);
+	if (err)
+		return err;
 
 	if (data[IFLA_CAN_TERMINATION]) {
 		const u16 termval = nla_get_u16(data[IFLA_CAN_TERMINATION]);
 		const unsigned int num_term = priv->termination_const_cnt;
 		unsigned int i;
@@ -387,36 +491,35 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 	}
 
 	return 0;
 }
 
-static size_t can_tdc_get_size(const struct net_device *dev)
+static size_t can_tdc_get_size(struct data_bittiming_params *dbt_params,
+			       bool tdc_is_enabled, bool tdc_manual)
 {
-	struct can_priv *priv = netdev_priv(dev);
 	size_t size;
 
-	if (!priv->fd.tdc_const)
+	if (!dbt_params->tdc_const)
 		return 0;
 
 	size = nla_total_size(0);			/* nest IFLA_CAN_TDC */
-	if (priv->ctrlmode_supported & CAN_CTRLMODE_TDC_MANUAL) {
+	if (tdc_manual) {
 		size += nla_total_size(sizeof(u32));	/* IFLA_CAN_TDCV_MIN */
 		size += nla_total_size(sizeof(u32));	/* IFLA_CAN_TDCV_MAX */
 	}
 	size += nla_total_size(sizeof(u32));		/* IFLA_CAN_TDCO_MIN */
 	size += nla_total_size(sizeof(u32));		/* IFLA_CAN_TDCO_MAX */
-	if (priv->fd.tdc_const->tdcf_max) {
+	if (dbt_params->tdc_const->tdcf_max) {
 		size += nla_total_size(sizeof(u32));	/* IFLA_CAN_TDCF_MIN */
 		size += nla_total_size(sizeof(u32));	/* IFLA_CAN_TDCF_MAX */
 	}
 
-	if (can_fd_tdc_is_enabled(priv)) {
-		if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL ||
-		    priv->fd.do_get_auto_tdcv)
+	if (tdc_is_enabled) {
+		if (tdc_manual || dbt_params->do_get_auto_tdcv)
 			size += nla_total_size(sizeof(u32));	/* IFLA_CAN_TDCV */
 		size += nla_total_size(sizeof(u32));		/* IFLA_CAN_TDCO */
-		if (priv->fd.tdc_const->tdcf_max)
+		if (dbt_params->tdc_const->tdcf_max)
 			size += nla_total_size(sizeof(u32));	/* IFLA_CAN_TDCF */
 	}
 
 	return size;
 }
@@ -456,31 +559,45 @@ static size_t can_get_size(const struct net_device *dev)
 				       priv->bitrate_const_cnt);
 	if (priv->fd.data_bitrate_const)			/* IFLA_CAN_DATA_BITRATE_CONST */
 		size += nla_total_size(sizeof(*priv->fd.data_bitrate_const) *
 				       priv->fd.data_bitrate_const_cnt);
 	size += sizeof(priv->bitrate_max);			/* IFLA_CAN_BITRATE_MAX */
-	size += can_tdc_get_size(dev);				/* IFLA_CAN_TDC */
+	size += can_tdc_get_size(&priv->fd,			/* IFLA_CAN_TDC */
+				 can_fd_tdc_is_enabled(priv),
+				 priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL);
 	size += can_ctrlmode_ext_get_size();			/* IFLA_CAN_CTRLMODE_EXT */
+	if (priv->xl.data_bittiming.bitrate)			/* IFLA_CAN_XL_DATA_BITTIMING */
+		size += nla_total_size(sizeof(struct can_bittiming));
+	if (priv->xl.data_bittiming_const)			/* IFLA_CAN_XL_DATA_BITTIMING_CONST */
+		size += nla_total_size(sizeof(struct can_bittiming_const));
+	if (priv->xl.data_bitrate_const)			/* IFLA_CAN_DATA_BITRATE_CONST */
+		size += nla_total_size(sizeof(*priv->xl.data_bitrate_const) *
+				       priv->xl.data_bitrate_const_cnt);
+	size += can_tdc_get_size(&priv->xl,			/* IFLA_CAN_XL_TDC */
+				 can_xl_tdc_is_enabled(priv),
+				 priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MANUAL);
 
 	return size;
 }
 
-static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev)
+static int can_tdc_fill_info(struct sk_buff *skb,  const struct net_device *dev,
+			     struct data_bittiming_params *dbt_params,
+			     bool tdc_is_enabled, bool tdc_manual,
+			     int ifla_can_tdc_type)
 {
 	struct nlattr *nest;
-	struct can_priv *priv = netdev_priv(dev);
-	struct can_tdc *tdc = &priv->fd.tdc;
-	const struct can_tdc_const *tdc_const = priv->fd.tdc_const;
+	struct can_tdc *tdc = &dbt_params->tdc;
+	const struct can_tdc_const *tdc_const = dbt_params->tdc_const;
 
 	if (!tdc_const)
 		return 0;
 
-	nest = nla_nest_start(skb, IFLA_CAN_TDC);
+	nest = nla_nest_start(skb, ifla_can_tdc_type);
 	if (!nest)
 		return -EMSGSIZE;
 
-	if (priv->ctrlmode_supported & CAN_CTRLMODE_TDC_MANUAL &&
+	if (tdc_manual &&
 	    (nla_put_u32(skb, IFLA_CAN_TDC_TDCV_MIN, tdc_const->tdcv_min) ||
 	     nla_put_u32(skb, IFLA_CAN_TDC_TDCV_MAX, tdc_const->tdcv_max)))
 		goto err_cancel;
 	if (nla_put_u32(skb, IFLA_CAN_TDC_TDCO_MIN, tdc_const->tdco_min) ||
 	    nla_put_u32(skb, IFLA_CAN_TDC_TDCO_MAX, tdc_const->tdco_max))
@@ -488,19 +605,19 @@ static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev)
 	if (tdc_const->tdcf_max &&
 	    (nla_put_u32(skb, IFLA_CAN_TDC_TDCF_MIN, tdc_const->tdcf_min) ||
 	     nla_put_u32(skb, IFLA_CAN_TDC_TDCF_MAX, tdc_const->tdcf_max)))
 		goto err_cancel;
 
-	if (can_fd_tdc_is_enabled(priv)) {
+	if (tdc_is_enabled) {
 		u32 tdcv;
 		int err = -EINVAL;
 
-		if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL) {
+		if (tdc_manual) {
 			tdcv = tdc->tdcv;
 			err = 0;
-		} else if (priv->fd.do_get_auto_tdcv) {
-			err = priv->fd.do_get_auto_tdcv(dev, &tdcv);
+		} else if (dbt_params->do_get_auto_tdcv) {
+			err = dbt_params->do_get_auto_tdcv(dev, &tdcv);
 		}
 		if (!err && nla_put_u32(skb, IFLA_CAN_TDC_TDCV, tdcv))
 			goto err_cancel;
 		if (nla_put_u32(skb, IFLA_CAN_TDC_TDCO, tdc->tdco))
 			goto err_cancel;
@@ -594,13 +711,34 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
 
 	    (nla_put(skb, IFLA_CAN_BITRATE_MAX,
 		     sizeof(priv->bitrate_max),
 		     &priv->bitrate_max)) ||
 
-	    can_tdc_fill_info(skb, dev) ||
+	    can_tdc_fill_info(skb, dev, &priv->fd, can_fd_tdc_is_enabled(priv),
+			      priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL,
+			      IFLA_CAN_TDC) ||
+
+	    can_ctrlmode_ext_fill_info(skb, priv) ||
+
+	    (priv->xl.data_bittiming.bitrate &&
+	     nla_put(skb, IFLA_CAN_XL_DATA_BITTIMING,
+		     sizeof(priv->xl.data_bittiming), &priv->xl.data_bittiming)) ||
+
+	    (priv->xl.data_bittiming_const &&
+	     nla_put(skb, IFLA_CAN_XL_DATA_BITTIMING_CONST,
+		     sizeof(*priv->xl.data_bittiming_const),
+		     priv->xl.data_bittiming_const)) ||
+
+	    (priv->xl.data_bitrate_const &&
+	     nla_put(skb, IFLA_CAN_XL_DATA_BITRATE_CONST,
+		     sizeof(*priv->xl.data_bitrate_const) *
+		     priv->xl.data_bitrate_const_cnt,
+		     priv->xl.data_bitrate_const)) ||
 
-	    can_ctrlmode_ext_fill_info(skb, priv)
+	    can_tdc_fill_info(skb, dev, &priv->xl, can_xl_tdc_is_enabled(priv),
+			      priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MANUAL,
+			      IFLA_CAN_XL_TDC)
 	    )
 
 		return -EMSGSIZE;
 
 	return 0;
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
index 81baec8eb1e5..3bd861d5b8ac 100644
--- a/drivers/net/can/xilinx_can.c
+++ b/drivers/net/can/xilinx_can.c
@@ -513,16 +513,16 @@ static int xcan_set_bittiming(struct net_device *ndev)
 
 	if (priv->devtype.cantype == XAXI_CANFD ||
 	    priv->devtype.cantype == XAXI_CANFD_2_0) {
 		/* Setting Baud Rate prescaler value in F_BRPR Register */
 		btr0 = dbt->brp - 1;
-		if (can_fd_tdc_is_enabled(&priv->can)) {
+		if (can_tdc_is_enabled(&priv->can)) {
 			if (priv->devtype.cantype == XAXI_CANFD)
-				btr0 |= FIELD_PREP(XCAN_BRPR_TDCO_MASK, priv->can.fd.tdc.tdco) |
+				btr0 |= FIELD_PREP(XCAN_BRPR_TDCO_MASK, priv->can.tdc.tdco) |
 					XCAN_BRPR_TDC_ENABLE;
 			else
-				btr0 |= FIELD_PREP(XCAN_2_BRPR_TDCO_MASK, priv->can.fd.tdc.tdco) |
+				btr0 |= FIELD_PREP(XCAN_2_BRPR_TDCO_MASK, priv->can.tdc.tdco) |
 					XCAN_BRPR_TDC_ENABLE;
 		}
 
 		/* Setting Time Segment 1 in BTR Register */
 		btr1 = dbt->prop_seg + dbt->phase_seg1 - 1;
@@ -1967,24 +1967,24 @@ static int xcan_probe(struct platform_device *pdev)
 		goto err_free;
 
 	if (devtype->cantype == XAXI_CANFD) {
 		priv->can.fd.data_bittiming_const =
 			&xcan_data_bittiming_const_canfd;
-		priv->can.fd.tdc_const = &xcan_tdc_const_canfd;
+		priv->can.tdc_const = &xcan_tdc_const_canfd;
 	}
 
 	if (devtype->cantype == XAXI_CANFD_2_0) {
 		priv->can.fd.data_bittiming_const =
 			&xcan_data_bittiming_const_canfd2;
-		priv->can.fd.tdc_const = &xcan_tdc_const_canfd2;
+		priv->can.tdc_const = &xcan_tdc_const_canfd2;
 	}
 
 	if (devtype->cantype == XAXI_CANFD ||
 	    devtype->cantype == XAXI_CANFD_2_0) {
 		priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD |
 						CAN_CTRLMODE_TDC_AUTO;
-		priv->can.fd.do_get_auto_tdcv = xcan_get_auto_tdcv;
+		priv->can.do_get_auto_tdcv = xcan_get_auto_tdcv;
 	}
 
 	priv->reg_base = addr;
 	priv->tx_max = tx_max;
 	priv->devtype = *devtype;
diff --git a/include/linux/can/bittiming.h b/include/linux/can/bittiming.h
index 5dfdbb63b1d5..2053b9dff0ad 100644
--- a/include/linux/can/bittiming.h
+++ b/include/linux/can/bittiming.h
@@ -14,10 +14,12 @@
 #define CAN_BITRATE_UNSET 0
 #define CAN_BITRATE_UNKNOWN (-1U)
 
 #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)
 
 /*
  * struct can_tdc - CAN FD Transmission Delay Compensation parameters
  *
  * At high bit rates, the propagation delay from the TX pin to the RX
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 9a92cbe5b2cb..1ac98914f351 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -56,11 +56,11 @@ struct can_priv {
 	struct net_device *dev;
 	struct can_device_stats can_stats;
 
 	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;
 	struct can_clock clock;
 
@@ -94,10 +94,15 @@ struct can_priv {
 static inline bool can_fd_tdc_is_enabled(const struct can_priv *priv)
 {
 	return !!(priv->ctrlmode & CAN_CTRLMODE_FD_TDC_MASK);
 }
 
+static inline bool can_xl_tdc_is_enabled(const struct can_priv *priv)
+{
+	return !!(priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MASK);
+}
+
 /*
  * can_get_relative_tdco() - TDCO relative to the sample point
  *
  * struct can_tdc::tdco represents the absolute offset from TDCV. Some
  * controllers use instead an offset relative to the Sample Point (SP)
@@ -114,17 +119,17 @@ static inline bool can_fd_tdc_is_enabled(const struct can_priv *priv)
  *                           |<------------------------>| absolute TDCO
  *                           |<--- Sample Point --->|
  *                           |                      |<->| relative TDCO
  *  |<------------- Secondary Sample Point ------------>|
  */
-static inline s32 can_get_relative_tdco(const struct can_priv *priv)
+static inline s32 can_get_relative_tdco(const struct data_bittiming_params *dbt_params)
 {
-	const struct can_bittiming *dbt = &priv->fd.data_bittiming;
+	const struct can_bittiming *dbt = &dbt_params->data_bittiming;
 	s32 sample_point_in_tc = (CAN_SYNC_SEG + dbt->prop_seg +
 				  dbt->phase_seg1) * dbt->brp;
 
-	return (s32)priv->fd.tdc.tdco - sample_point_in_tc;
+	return (s32)dbt_params->tdc.tdco - sample_point_in_tc;
 }
 
 /* helper to define static CAN controller features at device creation time */
 static inline int __must_check can_set_static_ctrlmode(struct net_device *dev,
 						       u32 static_mode)
diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netlink.h
index 02ec32d69474..f4fb8eea8f35 100644
--- a/include/uapi/linux/can/netlink.h
+++ b/include/uapi/linux/can/netlink.h
@@ -99,12 +99,15 @@ struct can_ctrlmode {
 #define CAN_CTRLMODE_BERR_REPORTING	0x10	/* Bus-error reporting */
 #define CAN_CTRLMODE_FD			0x20	/* CAN FD mode */
 #define CAN_CTRLMODE_PRESUME_ACK	0x40	/* Ignore missing CAN ACKs */
 #define CAN_CTRLMODE_FD_NON_ISO		0x80	/* CAN FD in non-ISO mode */
 #define CAN_CTRLMODE_CC_LEN8_DLC	0x100	/* Classic CAN DLC option */
-#define CAN_CTRLMODE_TDC_AUTO		0x200	/* CAN transiver automatically calculates TDCV */
-#define CAN_CTRLMODE_TDC_MANUAL		0x400	/* TDCV is manually set up by user */
+#define CAN_CTRLMODE_TDC_AUTO		0x200	/* FD transceiver automatically calculates TDCV */
+#define CAN_CTRLMODE_TDC_MANUAL		0x400	/* FD TDCV is manually set up by user */
+#define CAN_CTRLMODE_XL			0x800	/* CAN XL mode */
+#define CAN_CTRLMODE_XL_TDC_AUTO	0x1000	/* XL transceiver automatically calculates TDCV */
+#define CAN_CTRLMODE_XL_TDC_MANUAL	0x2000	/* XL TDCV is manually set up by user */
 
 /*
  * CAN device statistics
  */
 struct can_device_stats {
@@ -127,27 +130,31 @@ enum {
 	IFLA_CAN_STATE,
 	IFLA_CAN_CTRLMODE,
 	IFLA_CAN_RESTART_MS,
 	IFLA_CAN_RESTART,
 	IFLA_CAN_BERR_COUNTER,
-	IFLA_CAN_DATA_BITTIMING,
-	IFLA_CAN_DATA_BITTIMING_CONST,
+	IFLA_CAN_DATA_BITTIMING, /* FD */
+	IFLA_CAN_DATA_BITTIMING_CONST, /* FD */
 	IFLA_CAN_TERMINATION,
 	IFLA_CAN_TERMINATION_CONST,
 	IFLA_CAN_BITRATE_CONST,
-	IFLA_CAN_DATA_BITRATE_CONST,
+	IFLA_CAN_DATA_BITRATE_CONST, /* FD */
 	IFLA_CAN_BITRATE_MAX,
-	IFLA_CAN_TDC,
+	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,
 
 	/* add new constants above here */
 	__IFLA_CAN_MAX,
 	IFLA_CAN_MAX = __IFLA_CAN_MAX - 1
 };
 
 /*
- * CAN FD Transmitter Delay Compensation (TDC)
+ * CAN FD/XL Transmitter Delay Compensation (TDC)
  *
  * Please refer to struct can_tdc_const and can_tdc in
  * include/linux/can/bittiming.h for further details.
  */
 enum {
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 07/11] can: canxl: support Remote Request Substitution bit access
  2025-05-27 19:56 [PATCH 01/11] can: dev: add struct data_bittiming_params to group FD parameters Oliver Hartkopp
                   ` (4 preceding siblings ...)
  2025-05-27 19:56 ` [PATCH 06/11] can: netlink: add CAN XL support Oliver Hartkopp
@ 2025-05-27 19:56 ` Oliver Hartkopp
  2025-05-27 19:56 ` [PATCH 08/11] can: canxl: support CAN XL transceiver switching in data phase Oliver Hartkopp
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Oliver Hartkopp @ 2025-05-27 19:56 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp

The Remote Request Substitution bit is a dominant bit ("0") in the CAN XL
frame. As some CAN XL controllers support to access this bit a new
CANXL_RRS value has been defined for the canxl_frame.flags element.

To read/write the Remote Request Substitution (RRS) bit in the CAN XL
frame the CAN_CTRLMODE_XL_RRS has to be enabled in CAN driver.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
 include/uapi/linux/can/netlink.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netlink.h
index f4fb8eea8f35..55b8374ab094 100644
--- a/include/uapi/linux/can/netlink.h
+++ b/include/uapi/linux/can/netlink.h
@@ -104,10 +104,11 @@ struct can_ctrlmode {
 #define CAN_CTRLMODE_TDC_AUTO		0x200	/* FD transceiver automatically calculates TDCV */
 #define CAN_CTRLMODE_TDC_MANUAL		0x400	/* FD TDCV is manually set up by user */
 #define CAN_CTRLMODE_XL			0x800	/* CAN XL mode */
 #define CAN_CTRLMODE_XL_TDC_AUTO	0x1000	/* XL transceiver automatically calculates TDCV */
 #define CAN_CTRLMODE_XL_TDC_MANUAL	0x2000	/* XL TDCV is manually set up by user */
+#define CAN_CTRLMODE_XL_RRS		0x4000	/* XL enable RRS bit access */
 
 /*
  * CAN device statistics
  */
 struct can_device_stats {
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 08/11] can: canxl: support CAN XL transceiver switching in data phase
  2025-05-27 19:56 [PATCH 01/11] can: dev: add struct data_bittiming_params to group FD parameters Oliver Hartkopp
                   ` (5 preceding siblings ...)
  2025-05-27 19:56 ` [PATCH 07/11] can: canxl: support Remote Request Substitution bit access Oliver Hartkopp
@ 2025-05-27 19:56 ` Oliver Hartkopp
  2025-05-27 19:56 ` [PATCH 09/11] can: canxl: support CAN XL error signalling switching Oliver Hartkopp
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Oliver Hartkopp @ 2025-05-27 19:56 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp

In the CAN XL data phase the CAN XL controller can advise the CAN XL
transceiver to switch the physical layer.
To enable this feature the CAN_CTRLMODE_XL_TRX has to be set in the
driver control mode.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
 include/uapi/linux/can/netlink.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netlink.h
index 55b8374ab094..652576234f63 100644
--- a/include/uapi/linux/can/netlink.h
+++ b/include/uapi/linux/can/netlink.h
@@ -105,10 +105,11 @@ struct can_ctrlmode {
 #define CAN_CTRLMODE_TDC_MANUAL		0x400	/* FD TDCV is manually set up by user */
 #define CAN_CTRLMODE_XL			0x800	/* CAN XL mode */
 #define CAN_CTRLMODE_XL_TDC_AUTO	0x1000	/* XL transceiver automatically calculates TDCV */
 #define CAN_CTRLMODE_XL_TDC_MANUAL	0x2000	/* XL TDCV is manually set up by user */
 #define CAN_CTRLMODE_XL_RRS		0x4000	/* XL enable RRS bit access */
+#define CAN_CTRLMODE_XL_TRX		0x8000  /* XL switch trx in data phase */
 
 /*
  * CAN device statistics
  */
 struct can_device_stats {
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 09/11] can: canxl: support CAN XL error signalling switching
  2025-05-27 19:56 [PATCH 01/11] can: dev: add struct data_bittiming_params to group FD parameters Oliver Hartkopp
                   ` (6 preceding siblings ...)
  2025-05-27 19:56 ` [PATCH 08/11] can: canxl: support CAN XL transceiver switching in data phase Oliver Hartkopp
@ 2025-05-27 19:56 ` Oliver Hartkopp
  2025-05-27 19:56 ` [PATCH 10/11] can: canxl: add PWM config support Oliver Hartkopp
  2025-05-27 19:56 ` [PATCH 11/11] can: add CAN XL dummy driver DO NOT MERGE Oliver Hartkopp
  9 siblings, 0 replies; 22+ messages in thread
From: Oliver Hartkopp @ 2025-05-27 19:56 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp

For CAN CC and CAN FD the generation of error frames on the CAN bus in the
case of detected protocol violations is a mandatory feature.
With CAN XL utilizing a switchable CAN XL transceiver with a different
physical layer the error signalling is not possible when the transceiver
is switched into the new data mode physical layer.
When operating a CAN controller in CAN CC/FD/XL mode (XL = enabled!) with
a 'normal' CAN (FD) transceiver that does not switch the physical layer in
the data section the user can decide whether the error signalling is
enabled/disabled for all CAN protocols.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
 include/uapi/linux/can/netlink.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netlink.h
index 652576234f63..163a6167264e 100644
--- a/include/uapi/linux/can/netlink.h
+++ b/include/uapi/linux/can/netlink.h
@@ -106,10 +106,11 @@ struct can_ctrlmode {
 #define CAN_CTRLMODE_XL			0x800	/* CAN XL mode */
 #define CAN_CTRLMODE_XL_TDC_AUTO	0x1000	/* XL transceiver automatically calculates TDCV */
 #define CAN_CTRLMODE_XL_TDC_MANUAL	0x2000	/* XL TDCV is manually set up by user */
 #define CAN_CTRLMODE_XL_RRS		0x4000	/* XL enable RRS bit access */
 #define CAN_CTRLMODE_XL_TRX		0x8000  /* XL switch trx in data phase */
+#define CAN_CTRLMODE_XL_ERR_SIGNAL	0x10000	/* XL error signalling */
 
 /*
  * CAN device statistics
  */
 struct can_device_stats {
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 10/11] can: canxl: add PWM config support
  2025-05-27 19:56 [PATCH 01/11] can: dev: add struct data_bittiming_params to group FD parameters Oliver Hartkopp
                   ` (7 preceding siblings ...)
  2025-05-27 19:56 ` [PATCH 09/11] can: canxl: support CAN XL error signalling switching Oliver Hartkopp
@ 2025-05-27 19:56 ` Oliver Hartkopp
  2025-05-28 16:23   ` Marc Kleine-Budde
  2025-05-29  1:17   ` Vincent Mailhol
  2025-05-27 19:56 ` [PATCH 11/11] can: add CAN XL dummy driver DO NOT MERGE Oliver Hartkopp
  9 siblings, 2 replies; 22+ messages in thread
From: Oliver Hartkopp @ 2025-05-27 19:56 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
 drivers/net/can/dev/netlink.c    | 31 ++++++++++++++++++++++++++++++-
 include/linux/can/bittiming.h    | 25 +++++++++++++++++++++++++
 include/linux/can/dev.h          |  1 +
 include/uapi/linux/can/netlink.h | 15 +++++++++++++++
 4 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
index 1b798a7dcd64..685cceb74048 100644
--- a/drivers/net/can/dev/netlink.c
+++ b/drivers/net/can/dev/netlink.c
@@ -23,10 +23,11 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
 	[IFLA_CAN_TDC] = { .type = NLA_NESTED },
 	[IFLA_CAN_CTRLMODE_EXT] = { .type = NLA_NESTED },
 	[IFLA_CAN_XL_DATA_BITTIMING] = { .len = sizeof(struct can_bittiming) },
 	[IFLA_CAN_XL_DATA_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) },
 	[IFLA_CAN_XL_TDC] = { .type = NLA_NESTED },
+	[IFLA_CAN_XL_PWM] = { .type = NLA_NESTED },
 };
 
 static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = {
 	[IFLA_CAN_TDC_TDCV_MIN] = { .type = NLA_U32 },
 	[IFLA_CAN_TDC_TDCV_MAX] = { .type = NLA_U32 },
@@ -37,10 +38,16 @@ static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = {
 	[IFLA_CAN_TDC_TDCV] = { .type = NLA_U32 },
 	[IFLA_CAN_TDC_TDCO] = { .type = NLA_U32 },
 	[IFLA_CAN_TDC_TDCF] = { .type = NLA_U32 },
 };
 
+static const struct nla_policy can_pwm_policy[IFLA_CAN_PWM_MAX + 1] = {
+	[IFLA_CAN_PWM_OFFSET] = { .type = NLA_U8 },
+	[IFLA_CAN_PWM_LONG] = { .type = NLA_U8 },
+	[IFLA_CAN_PWM_SHORT] = { .type = NLA_U8 },
+};
+
 static int can_validate_bittiming(const struct can_bittiming *bt,
 				  struct netlink_ext_ack *extack)
 {
 	/* sample point is in one-tenth of a percent */
 	if (bt->sample_point >= 1000) {
@@ -464,10 +471,29 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 				 can_xl_tdc_is_enabled(priv),
 				 CAN_CTRLMODE_XL_TDC_MASK, extack);
 	if (err)
 		return err;
 
+	/* CAN XL transceiver PWM configuration */
+	if (data[IFLA_CAN_XL_PWM]) {
+		struct nlattr *tb_pwm[IFLA_CAN_PWM_MAX + 1];
+
+		err = 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_OFFSET])
+			priv->pwm.pwm_offset = nla_get_u8(tb_pwm[IFLA_CAN_PWM_OFFSET]) & 0x3F;
+
+		if (tb_pwm[IFLA_CAN_PWM_LONG])
+			priv->pwm.pwm_phase_long = nla_get_u8(tb_pwm[IFLA_CAN_PWM_LONG]) & 0x3F;
+
+		if (tb_pwm[IFLA_CAN_PWM_SHORT])
+			priv->pwm.pwm_phase_short = nla_get_u8(tb_pwm[IFLA_CAN_PWM_SHORT]) & 0x3F;
+	}
+
 	if (data[IFLA_CAN_TERMINATION]) {
 		const u16 termval = nla_get_u16(data[IFLA_CAN_TERMINATION]);
 		const unsigned int num_term = priv->termination_const_cnt;
 		unsigned int i;
 
@@ -573,10 +599,11 @@ static size_t can_get_size(const struct net_device *dev)
 		size += nla_total_size(sizeof(*priv->xl.data_bitrate_const) *
 				       priv->xl.data_bitrate_const_cnt);
 	size += can_tdc_get_size(&priv->xl,			/* IFLA_CAN_XL_TDC */
 				 can_xl_tdc_is_enabled(priv),
 				 priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MANUAL);
+	size += nla_total_size(sizeof(struct can_pwm));
 
 	return size;
 }
 
 static int can_tdc_fill_info(struct sk_buff *skb,  const struct net_device *dev,
@@ -734,11 +761,13 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
 		     priv->xl.data_bitrate_const_cnt,
 		     priv->xl.data_bitrate_const)) ||
 
 	    can_tdc_fill_info(skb, dev, &priv->xl, can_xl_tdc_is_enabled(priv),
 			      priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MANUAL,
-			      IFLA_CAN_XL_TDC)
+			      IFLA_CAN_XL_TDC) ||
+
+	    nla_put(skb, IFLA_CAN_XL_PWM, sizeof(priv->pwm), &priv->pwm)
 	    )
 
 		return -EMSGSIZE;
 
 	return 0;
diff --git a/include/linux/can/bittiming.h b/include/linux/can/bittiming.h
index 2053b9dff0ad..47e266ab7486 100644
--- a/include/linux/can/bittiming.h
+++ b/include/linux/can/bittiming.h
@@ -114,10 +114,35 @@ struct can_tdc_const {
 	u32 tdco_max;
 	u32 tdcf_min;
 	u32 tdcf_max;
 };
 
+/*
+ * struct can_pwm - PWM configuration for switchable CAN XL transceivers
+ *
+ * -+-- init-offset -+------- one bit in CAN XL data mode --------+- TX pin
+ *  |<--- Offset --->|
+ *                   |<-------- Long 1 -------->|<--- Short 0 --->|  level_1
+ *                   |<--- Short 1 --->|<-------- Long 0 -------->|  level_0
+ *                                          |
+ *                                 (50/50 sample point)
+ *
+ * The duration of a complete PWM bit representation has to be < 200ns to
+ * reliably switch the CAN XL transceiver into the CAN XL data mode.
+ *
+ * @pwm_offset: Offset before first PWM bit trasmmission to fill the ADH bit
+ *
+ * @pwm_phase_long: PWM Phase Long (ideally 75% of PWM bit representation)
+ *
+ * @pwm_phase_short: PWM Phase Short (ideally 25% of PWM bit representation)
+ */
+struct can_pwm {
+	u8 pwm_offset;
+	u8 pwm_phase_long;
+	u8 pwm_phase_short;
+};
+
 #ifdef CONFIG_CAN_CALC_BITTIMING
 int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
 		       const struct can_bittiming_const *btc, struct netlink_ext_ack *extack);
 
 void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const,
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 1ac98914f351..6b65b3fccfd2 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -60,10 +60,11 @@ struct can_priv {
 	struct can_bittiming bittiming;
 	struct data_bittiming_params fd, xl;
 	unsigned int bitrate_const_cnt;
 	const u32 *bitrate_const;
 	u32 bitrate_max;
+	struct can_pwm pwm;
 	struct can_clock clock;
 
 	unsigned int termination_const_cnt;
 	const u16 *termination_const;
 	u16 termination;
diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netlink.h
index 163a6167264e..bd3706b37e04 100644
--- a/include/uapi/linux/can/netlink.h
+++ b/include/uapi/linux/can/netlink.h
@@ -146,16 +146,31 @@ enum {
 	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,
+	IFLA_CAN_XL_PWM,
 
 	/* add new constants above here */
 	__IFLA_CAN_MAX,
 	IFLA_CAN_MAX = __IFLA_CAN_MAX - 1
 };
 
+/*
+ * CAN XL Transceiver data mode switching PWM configuration
+ */
+enum {
+	IFLA_CAN_PWM_UNSPEC,
+	IFLA_CAN_PWM_OFFSET,	/* u8 */
+	IFLA_CAN_PWM_LONG,	/* u8 */
+	IFLA_CAN_PWM_SHORT,	/* u8 */
+
+	/* add new constants above here */
+	__IFLA_CAN_PWM,
+	IFLA_CAN_PWM_MAX = __IFLA_CAN_PWM - 1
+};
+
 /*
  * CAN FD/XL Transmitter Delay Compensation (TDC)
  *
  * Please refer to struct can_tdc_const and can_tdc in
  * include/linux/can/bittiming.h for further details.
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 11/11] can: add CAN XL dummy driver DO NOT MERGE
  2025-05-27 19:56 [PATCH 01/11] can: dev: add struct data_bittiming_params to group FD parameters Oliver Hartkopp
                   ` (8 preceding siblings ...)
  2025-05-27 19:56 ` [PATCH 10/11] can: canxl: add PWM config support Oliver Hartkopp
@ 2025-05-27 19:56 ` Oliver Hartkopp
  9 siblings, 0 replies; 22+ messages in thread
From: Oliver Hartkopp @ 2025-05-27 19:56 UTC (permalink / raw)
  To: linux-can; +Cc: Vincent Mailhol, Oliver Hartkopp

From: Vincent Mailhol <mailhol.vincent@wanadoo.fr>

A dummy module just to check the CAN XL netlink interface.

Oliver: added control mode/supported output

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
 drivers/net/can/Kconfig   |   8 ++
 drivers/net/can/Makefile  |   1 +
 drivers/net/can/dummyxl.c | 226 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 235 insertions(+)
 create mode 100644 drivers/net/can/dummyxl.c

diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index cf989bea9aa3..a8bc5f4e752f 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -122,10 +122,18 @@ config CAN_CAN327
 	  Please refer to the documentation for information on how to use it:
 	  Documentation/networking/device_drivers/can/can327.rst
 
 	  If this driver is built as a module, it will be called can327.
 
+config CAN_DUMMY_XL
+	tristate "Dummy CAN XL"
+	help
+	  A dummy module just to check the CAN XL netlink interface. Do not
+	  merge this.
+
+	  If this driver is built as a module, it will be called dummyxl.
+
 config CAN_FLEXCAN
 	tristate "Support for Freescale FLEXCAN based chips"
 	depends on OF || COLDFIRE || COMPILE_TEST
 	depends on HAS_IOMEM
 	select CAN_RX_OFFLOAD
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index a71db2cfe990..ff8e00fa26e3 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -19,10 +19,11 @@ obj-$(CONFIG_CAN_AT91)		+= at91_can.o
 obj-$(CONFIG_CAN_BXCAN)		+= bxcan.o
 obj-$(CONFIG_CAN_CAN327)	+= can327.o
 obj-$(CONFIG_CAN_CC770)		+= cc770/
 obj-$(CONFIG_CAN_C_CAN)		+= c_can/
 obj-$(CONFIG_CAN_CTUCANFD)	+= ctucanfd/
+obj-$(CONFIG_CAN_DUMMY_XL)	+= dummyxl.o
 obj-$(CONFIG_CAN_FLEXCAN)	+= flexcan/
 obj-$(CONFIG_CAN_GRCAN)		+= grcan.o
 obj-$(CONFIG_CAN_IFI_CANFD)	+= ifi_canfd/
 obj-$(CONFIG_CAN_JANZ_ICAN3)	+= janz-ican3.o
 obj-$(CONFIG_CAN_KVASER_PCIEFD)	+= kvaser_pciefd.o
diff --git a/drivers/net/can/dummyxl.c b/drivers/net/can/dummyxl.c
new file mode 100644
index 000000000000..ac1b579b4c1f
--- /dev/null
+++ b/drivers/net/can/dummyxl.c
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* Copyright (c) 2024 Vincent Mailhol <mailhol.vincent@wanadoo.fr> */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/units.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/skb.h>
+
+struct dummyxl {
+	struct can_priv can;
+	struct net_device *dev;
+};
+
+static struct dummyxl *dummyxl;
+
+static const struct can_bittiming_const dummyxl_bittiming_const = {
+	.name = "dummyxl nominal",
+	.tseg1_min = 2,
+	.tseg1_max = 256,
+	.tseg2_min = 2,
+	.tseg2_max = 128,
+	.sjw_max = 128,
+	.brp_min = 1,
+	.brp_max = 512,
+	.brp_inc = 1
+};
+
+static const struct can_bittiming_const dummyxl_fd_databittiming_const = {
+	.name = "dummyxl FD",
+	.tseg1_min = 2,
+	.tseg1_max = 256,
+	.tseg2_min = 2,
+	.tseg2_max = 128,
+	.sjw_max = 128,
+	.brp_min = 1,
+	.brp_max = 512,
+	.brp_inc = 1
+};
+
+static const struct can_tdc_const dummyxl_fd_tdc_const = {
+	.tdcv_min = 0,
+	.tdcv_max = 0, /* Manual mode not supported. */
+	.tdco_min = 0,
+	.tdco_max = 127,
+	.tdcf_min = 0,
+	.tdcf_max = 127
+};
+
+static const struct can_bittiming_const dummyxl_xl_databittiming_const = {
+	.name = "dummyxl XL",
+	.tseg1_min = 2,
+	.tseg1_max = 256,
+	.tseg2_min = 2,
+	.tseg2_max = 128,
+	.sjw_max = 128,
+	.brp_min = 1,
+	.brp_max = 512,
+	.brp_inc = 1
+};
+
+static const struct can_tdc_const dummyxl_xl_tdc_const = {
+	.tdcv_min = 0,
+	.tdcv_max = 0, /* Manual mode not supported. */
+	.tdco_min = 0,
+	.tdco_max = 127,
+	.tdcf_min = 0,
+	.tdcf_max = 127
+};
+
+static void dummyxl_print_bittiming(struct net_device *dev, struct can_bittiming *bt)
+{
+	netdev_info(dev, "\tbitrate: %u\n", bt->bitrate);
+	netdev_info(dev, "\tsample_point: %u\n", bt->sample_point);
+	netdev_info(dev, "\ttq: %u\n", bt->tq);
+	netdev_info(dev, "\tprop_seg: %u\n", bt->prop_seg);
+	netdev_info(dev, "\tphase_seg1: %u\n", bt->phase_seg1);
+	netdev_info(dev, "\tphase_seg2: %u\n", bt->phase_seg2);
+	netdev_info(dev, "\tsjw: %u\n", bt->sjw);
+	netdev_info(dev, "\tbrp: %u\n", bt->brp);
+}
+
+static void dummyxl_print_tdc(struct net_device *dev, struct can_tdc *tdc)
+{
+	netdev_info(dev, "\t\ttdcv: %u\n", tdc->tdcv);
+	netdev_info(dev, "\t\ttdco: %u\n", tdc->tdco);
+	netdev_info(dev, "\t\ttdcf: %u\n", tdc->tdcf);
+}
+
+static int dummyxl_netdev_open(struct net_device *dev)
+{
+	struct dummyxl *priv = netdev_priv(dev);
+	struct can_priv *can_priv = &priv->can;
+	int ret;
+
+	netdev_info(dev, "CAN control mode/supported : %08X/%08X\n",
+		    can_priv->ctrlmode, can_priv->ctrlmode_supported);
+	netdev_info(dev, "CAN CC nominal bittiming:\n");
+	dummyxl_print_bittiming(dev, &can_priv->bittiming);
+	netdev_info(dev, "\n");
+
+	if (can_priv->ctrlmode & CAN_CTRLMODE_FD) {
+		netdev_info(dev, "CAN FD databittiming:\n");
+		dummyxl_print_bittiming(dev, &can_priv->fd.data_bittiming);
+		if (can_fd_tdc_is_enabled(can_priv)) {
+			netdev_info(dev, "\tCAN FD TDC:\n");
+			dummyxl_print_tdc(dev, &can_priv->fd.tdc);
+		} else {
+			netdev_info(dev, "\tCAN FD TDC is off\n");
+		}
+	} else {
+		netdev_info(dev, "CAN FD is off\n");
+	}
+	netdev_info(dev, "\n");
+
+	if (can_priv->ctrlmode & CAN_CTRLMODE_XL) {
+		netdev_info(dev, "CAN XL databittiming:\n");
+		dummyxl_print_bittiming(dev, &can_priv->xl.data_bittiming);
+		if (can_xl_tdc_is_enabled(can_priv)) {
+			netdev_info(dev, "\tCAN XL TDC:\n");
+			dummyxl_print_tdc(dev, &can_priv->xl.tdc);
+		} else {
+			netdev_info(dev, "\tCAN XL TDC is off\n");
+		}
+	} else {
+		netdev_info(dev, "CAN XL is off\n");
+	}
+	netdev_info(dev, "\n");
+
+	ret = open_candev(dev);
+	if (ret)
+		return ret;
+	netif_start_queue(dev);
+	netdev_info(dev, "dummyxl is up\n");
+
+	return 0;
+}
+
+static int dummyxl_netdev_close(struct net_device *dev)
+{
+	netif_stop_queue(dev);
+	close_candev(dev);
+	netdev_info(dev, "dummyxl is down\n");
+
+	return 0;
+}
+
+static netdev_tx_t dummyxl_start_xmit(struct sk_buff *skb,
+				      struct net_device *dev)
+{
+	if (can_is_canxl_skb(skb))
+		netdev_info(dev, "Received CAN XL skb\n");
+	else if (can_is_canfd_skb(skb))
+		netdev_info(dev, "Received CAN FD skb\n");
+	else if (can_is_can_skb(skb))
+		netdev_info(dev, "Received Classical CAN skb\n");
+	else
+		netdev_info(dev, "Received an odd skb?!\n");
+	kfree_skb(skb);
+	dev->stats.tx_dropped++;
+
+	return NETDEV_TX_OK;
+}
+
+static const struct net_device_ops dummyxl_netdev_ops = {
+	.ndo_open = dummyxl_netdev_open,
+	.ndo_stop = dummyxl_netdev_close,
+	.ndo_start_xmit = dummyxl_start_xmit,
+};
+
+static int __init dummyxl_init(void)
+{
+	struct net_device *dev;
+	struct dummyxl *priv;
+	int ret;
+
+	dev = alloc_candev(sizeof(struct dummyxl), 0);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->netdev_ops = &dummyxl_netdev_ops;
+	priv = netdev_priv(dev);
+	priv->can.bittiming_const = &dummyxl_bittiming_const;
+	priv->can.bitrate_max = 8 * MEGA /* BPS */;
+	priv->can.clock.freq = 80 * MEGA /* Hz */;
+	priv->can.fd.data_bittiming_const = &dummyxl_fd_databittiming_const;
+	priv->can.fd.tdc_const = &dummyxl_fd_tdc_const;
+	priv->can.xl.data_bittiming_const = &dummyxl_xl_databittiming_const;
+	priv->can.xl.tdc_const = &dummyxl_xl_tdc_const;
+	priv->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY |
+		CAN_CTRLMODE_FD | CAN_CTRLMODE_TDC_AUTO |
+		CAN_CTRLMODE_XL | CAN_CTRLMODE_XL_TDC_AUTO;
+	priv->dev = dev;
+
+	ret = register_candev(priv->dev);
+	if (ret) {
+		free_candev(priv->dev);
+		return ret;
+	}
+
+	dummyxl = priv;
+	netdev_info(dev, "dummyxl OK\n");
+
+	return 0;
+}
+
+static void __exit dummyxl_exit(void)
+{
+	struct net_device *dev = dummyxl->dev;
+
+	netdev_info(dev, "dummyxl bye bye\n");
+	unregister_candev(dev);
+	free_candev(dev);
+}
+
+module_init(dummyxl_init);
+module_exit(dummyxl_exit);
+
+MODULE_DESCRIPTION("A dummy module just to check the CAN XL netlink interface");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Vincent Mailhol <mailhol.vincent@wanadoo.fr>");
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 02/11] can: netlink: replace tabulation by space in assignment
  2025-05-27 19:56 ` [PATCH 02/11] can: netlink: replace tabulation by space in assignment Oliver Hartkopp
@ 2025-05-28  8:47   ` Marc Kleine-Budde
  2025-05-28 15:51     ` Vincent Mailhol
  0 siblings, 1 reply; 22+ messages in thread
From: Marc Kleine-Budde @ 2025-05-28  8:47 UTC (permalink / raw)
  To: Oliver Hartkopp; +Cc: linux-can, Vincent Mailhol

[-- Attachment #1: Type: text/plain, Size: 798 bytes --]

On 27.05.2025 21:56:16, Oliver Hartkopp wrote:
> From: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
> 
> commit cfd98c838cbe ("can: netlink: move '=' operators back to
> previous line (checkpatch fix)") inadvertently introduced a tabulation
> between the IFLA_CAN_DATA_BITTIMING_CONST array index and the equal
> sign.
> 
> Remove it.
> 
> Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>

The patches 2...5 look good to me. If Oliver adds his S-o-b, I can take
them for linux-can-next.

regards,
Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde          |
Embedded Linux                   | https://www.pengutronix.de |
Vertretung Nürnberg              | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-9   |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 02/11] can: netlink: replace tabulation by space in assignment
  2025-05-28  8:47   ` Marc Kleine-Budde
@ 2025-05-28 15:51     ` Vincent Mailhol
  2025-05-28 16:12       ` Marc Kleine-Budde
  0 siblings, 1 reply; 22+ messages in thread
From: Vincent Mailhol @ 2025-05-28 15:51 UTC (permalink / raw)
  To: Marc Kleine-Budde, Oliver Hartkopp; +Cc: linux-can

On 28/05/2025 at 17:47, Marc Kleine-Budde wrote:
> On 27.05.2025 21:56:16, Oliver Hartkopp wrote:
>> From: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
>>
>> commit cfd98c838cbe ("can: netlink: move '=' operators back to
>> previous line (checkpatch fix)") inadvertently introduced a tabulation
>> between the IFLA_CAN_DATA_BITTIMING_CONST array index and the equal
>> sign.
>>
>> Remove it.
>>
>> Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
> 
> The patches 2...5 look good to me. If Oliver adds his S-o-b, I can take
> them for linux-can-next.

If you prefer, I already submitted those in the past in a dedicated series with
a proper cover letter:


https://lore.kernel.org/linux-can/20241112165118.586613-7-mailhol.vincent@wanadoo.fr/

Because I got zero answers, I split it even further. This is why only one patch
got merge in for 6.15. I was planning to resend those clean-up patches anyway,
but if you are OK to take them directly from my previous series, go ahead.
Nothing has changed for these since November, except from the first patch with
was merged separately.


Yours sincerely,
Vincent Mailhol


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 02/11] can: netlink: replace tabulation by space in assignment
  2025-05-28 15:51     ` Vincent Mailhol
@ 2025-05-28 16:12       ` Marc Kleine-Budde
  2025-05-29  0:30         ` Vincent Mailhol
  2025-06-11  7:10         ` Marc Kleine-Budde
  0 siblings, 2 replies; 22+ messages in thread
From: Marc Kleine-Budde @ 2025-05-28 16:12 UTC (permalink / raw)
  To: Vincent Mailhol; +Cc: Oliver Hartkopp, linux-can

[-- Attachment #1: Type: text/plain, Size: 1688 bytes --]

On 29.05.2025 00:51:12, Vincent Mailhol wrote:
> On 28/05/2025 at 17:47, Marc Kleine-Budde wrote:
> > On 27.05.2025 21:56:16, Oliver Hartkopp wrote:
> >> From: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
> >>
> >> commit cfd98c838cbe ("can: netlink: move '=' operators back to
> >> previous line (checkpatch fix)") inadvertently introduced a tabulation
> >> between the IFLA_CAN_DATA_BITTIMING_CONST array index and the equal
> >> sign.
> >>
> >> Remove it.
> >>
> >> Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
> > 
> > The patches 2...5 look good to me. If Oliver adds his S-o-b, I can take
> > them for linux-can-next.
> 
> If you prefer, I already submitted those in the past in a dedicated series with
> a proper cover letter:
> 
> https://lore.kernel.org/linux-can/20241112165118.586613-7-mailhol.vincent@wanadoo.fr/

Even better.

> Because I got zero answers, I split it even further. This is why only one patch
> got merge in for 6.15. I was planning to resend those clean-up patches anyway,
> but if you are OK to take them directly from my previous series, go ahead.
> Nothing has changed for these since November, except from the first patch with
> was merged separately.

I've adjusted the cover letter, as patch 1 is already mainline, and
taken the rest of the series to can-next/testing. Note, once -rc1 is
out, I'll rebase this branch.

regards,
Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde          |
Embedded Linux                   | https://www.pengutronix.de |
Vertretung Nürnberg              | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-9   |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 10/11] can: canxl: add PWM config support
  2025-05-27 19:56 ` [PATCH 10/11] can: canxl: add PWM config support Oliver Hartkopp
@ 2025-05-28 16:23   ` Marc Kleine-Budde
  2025-05-29  1:17   ` Vincent Mailhol
  1 sibling, 0 replies; 22+ messages in thread
From: Marc Kleine-Budde @ 2025-05-28 16:23 UTC (permalink / raw)
  To: Oliver Hartkopp; +Cc: linux-can

[-- Attachment #1: Type: text/plain, Size: 3348 bytes --]

On 27.05.2025 21:56:24, Oliver Hartkopp wrote:
> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
> ---
>  drivers/net/can/dev/netlink.c    | 31 ++++++++++++++++++++++++++++++-
>  include/linux/can/bittiming.h    | 25 +++++++++++++++++++++++++
>  include/linux/can/dev.h          |  1 +
>  include/uapi/linux/can/netlink.h | 15 +++++++++++++++
>  4 files changed, 71 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
> index 1b798a7dcd64..685cceb74048 100644
> --- a/drivers/net/can/dev/netlink.c
> +++ b/drivers/net/can/dev/netlink.c
> @@ -23,10 +23,11 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
>  	[IFLA_CAN_TDC] = { .type = NLA_NESTED },
>  	[IFLA_CAN_CTRLMODE_EXT] = { .type = NLA_NESTED },
>  	[IFLA_CAN_XL_DATA_BITTIMING] = { .len = sizeof(struct can_bittiming) },
>  	[IFLA_CAN_XL_DATA_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) },
>  	[IFLA_CAN_XL_TDC] = { .type = NLA_NESTED },
> +	[IFLA_CAN_XL_PWM] = { .type = NLA_NESTED },
>  };
>  
>  static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = {
>  	[IFLA_CAN_TDC_TDCV_MIN] = { .type = NLA_U32 },
>  	[IFLA_CAN_TDC_TDCV_MAX] = { .type = NLA_U32 },
> @@ -37,10 +38,16 @@ static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = {
>  	[IFLA_CAN_TDC_TDCV] = { .type = NLA_U32 },
>  	[IFLA_CAN_TDC_TDCO] = { .type = NLA_U32 },
>  	[IFLA_CAN_TDC_TDCF] = { .type = NLA_U32 },
>  };
>  
> +static const struct nla_policy can_pwm_policy[IFLA_CAN_PWM_MAX + 1] = {
> +	[IFLA_CAN_PWM_OFFSET] = { .type = NLA_U8 },
> +	[IFLA_CAN_PWM_LONG] = { .type = NLA_U8 },
> +	[IFLA_CAN_PWM_SHORT] = { .type = NLA_U8 },

IIRC when Oleksij added some Ethernet related stuff, upstream wanted u32
even if the values would have fitted in a u8.

> +};
> +
>  static int can_validate_bittiming(const struct can_bittiming *bt,
>  				  struct netlink_ext_ack *extack)
>  {
>  	/* sample point is in one-tenth of a percent */
>  	if (bt->sample_point >= 1000) {
> @@ -464,10 +471,29 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
>  				 can_xl_tdc_is_enabled(priv),
>  				 CAN_CTRLMODE_XL_TDC_MASK, extack);
>  	if (err)
>  		return err;
>  
> +	/* CAN XL transceiver PWM configuration */
> +	if (data[IFLA_CAN_XL_PWM]) {
> +		struct nlattr *tb_pwm[IFLA_CAN_PWM_MAX + 1];
> +
> +		err = 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_OFFSET])
> +			priv->pwm.pwm_offset = nla_get_u8(tb_pwm[IFLA_CAN_PWM_OFFSET]) & 0x3F;
> +
> +		if (tb_pwm[IFLA_CAN_PWM_LONG])
> +			priv->pwm.pwm_phase_long = nla_get_u8(tb_pwm[IFLA_CAN_PWM_LONG]) & 0x3F;
> +
> +		if (tb_pwm[IFLA_CAN_PWM_SHORT])
> +			priv->pwm.pwm_phase_short = nla_get_u8(tb_pwm[IFLA_CAN_PWM_SHORT]) & 0x3F;

If the values are to large, reject them. Do not silently take only 6
bits. Fill extack for a descriptive error message.

Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde          |
Embedded Linux                   | https://www.pengutronix.de |
Vertretung Nürnberg              | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-9   |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 02/11] can: netlink: replace tabulation by space in assignment
  2025-05-28 16:12       ` Marc Kleine-Budde
@ 2025-05-29  0:30         ` Vincent Mailhol
  2025-06-11  7:10         ` Marc Kleine-Budde
  1 sibling, 0 replies; 22+ messages in thread
From: Vincent Mailhol @ 2025-05-29  0:30 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: Oliver Hartkopp, linux-can

On 29/05/2025 at 01:12, Marc Kleine-Budde wrote:

(...)

> I've adjusted the cover letter, as patch 1 is already mainline, and
> taken the rest of the series to can-next/testing. Note, once -rc1 is
> out, I'll rebase this branch.

Perfect! That's helpful, thanks!


Yours sincerely,
Vincent Mailhol


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 10/11] can: canxl: add PWM config support
  2025-05-27 19:56 ` [PATCH 10/11] can: canxl: add PWM config support Oliver Hartkopp
  2025-05-28 16:23   ` Marc Kleine-Budde
@ 2025-05-29  1:17   ` Vincent Mailhol
  2025-05-29 12:49     ` Oliver Hartkopp
  1 sibling, 1 reply; 22+ messages in thread
From: Vincent Mailhol @ 2025-05-29  1:17 UTC (permalink / raw)
  To: Oliver Hartkopp, linux-can; +Cc: Marc Kleine-Budde

Hi Oliver,

How do you want to move forward on this?

I stopped my work, waiting for my preparation patches to be merged and for the
PWM calculation to be clarified. Now that those two blockers are removed, I was
about to resume the work.

Do you plan to take over? It will be complicated if both of us work
simultaneously on the feature.


On 28/05/2025 at 04:56, Oliver Hartkopp wrote:
> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
> ---
>  drivers/net/can/dev/netlink.c    | 31 ++++++++++++++++++++++++++++++-
>  include/linux/can/bittiming.h    | 25 +++++++++++++++++++++++++
>  include/linux/can/dev.h          |  1 +
>  include/uapi/linux/can/netlink.h | 15 +++++++++++++++
>  4 files changed, 71 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
> index 1b798a7dcd64..685cceb74048 100644
> --- a/drivers/net/can/dev/netlink.c
> +++ b/drivers/net/can/dev/netlink.c
> @@ -23,10 +23,11 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
>  	[IFLA_CAN_TDC] = { .type = NLA_NESTED },
>  	[IFLA_CAN_CTRLMODE_EXT] = { .type = NLA_NESTED },
>  	[IFLA_CAN_XL_DATA_BITTIMING] = { .len = sizeof(struct can_bittiming) },
>  	[IFLA_CAN_XL_DATA_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) },
>  	[IFLA_CAN_XL_TDC] = { .type = NLA_NESTED },
> +	[IFLA_CAN_XL_PWM] = { .type = NLA_NESTED },
>  };
>  
>  static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = {
>  	[IFLA_CAN_TDC_TDCV_MIN] = { .type = NLA_U32 },
>  	[IFLA_CAN_TDC_TDCV_MAX] = { .type = NLA_U32 },
> @@ -37,10 +38,16 @@ static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = {
>  	[IFLA_CAN_TDC_TDCV] = { .type = NLA_U32 },
>  	[IFLA_CAN_TDC_TDCO] = { .type = NLA_U32 },
>  	[IFLA_CAN_TDC_TDCF] = { .type = NLA_U32 },
>  };
>  
> +static const struct nla_policy can_pwm_policy[IFLA_CAN_PWM_MAX + 1] = {
> +	[IFLA_CAN_PWM_OFFSET] = { .type = NLA_U8 },
> +	[IFLA_CAN_PWM_LONG] = { .type = NLA_U8 },
> +	[IFLA_CAN_PWM_SHORT] = { .type = NLA_U8 },
> +};

ISO 11898-1 uses the accronyms PWML, PWMO and PWMS. I would prefer to keep the
exact same naming as the standard.

Also, +1 to what Marc said, u32 seems better here.

>  static int can_validate_bittiming(const struct can_bittiming *bt,
>  				  struct netlink_ext_ack *extack)
>  {
>  	/* sample point is in one-tenth of a percent */
>  	if (bt->sample_point >= 1000) {
> @@ -464,10 +471,29 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
>  				 can_xl_tdc_is_enabled(priv),
>  				 CAN_CTRLMODE_XL_TDC_MASK, extack);
>  	if (err)
>  		return err;
>  
> +	/* CAN XL transceiver PWM configuration */
> +	if (data[IFLA_CAN_XL_PWM]) {
> +		struct nlattr *tb_pwm[IFLA_CAN_PWM_MAX + 1];
> +
> +		err = 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_OFFSET])
> +			priv->pwm.pwm_offset = nla_get_u8(tb_pwm[IFLA_CAN_PWM_OFFSET]) & 0x3F;
> +
> +		if (tb_pwm[IFLA_CAN_PWM_LONG])
> +			priv->pwm.pwm_phase_long = nla_get_u8(tb_pwm[IFLA_CAN_PWM_LONG]) & 0x3F;
> +
> +		if (tb_pwm[IFLA_CAN_PWM_SHORT])
> +			priv->pwm.pwm_phase_short = nla_get_u8(tb_pwm[IFLA_CAN_PWM_SHORT]) & 0x3F;
> +	}
> +
>  	if (data[IFLA_CAN_TERMINATION]) {
>  		const u16 termval = nla_get_u16(data[IFLA_CAN_TERMINATION]);
>  		const unsigned int num_term = priv->termination_const_cnt;
>  		unsigned int i;
>  
> @@ -573,10 +599,11 @@ static size_t can_get_size(const struct net_device *dev)
>  		size += nla_total_size(sizeof(*priv->xl.data_bitrate_const) *
>  				       priv->xl.data_bitrate_const_cnt);
>  	size += can_tdc_get_size(&priv->xl,			/* IFLA_CAN_XL_TDC */
>  				 can_xl_tdc_is_enabled(priv),
>  				 priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MANUAL);
> +	size += nla_total_size(sizeof(struct can_pwm));

This looks wrong. Does this work? The size of a nested NLA is the sum of its NLA
members. Look at can_tdc_get_size().

>  	return size;
>  }
>  
>  static int can_tdc_fill_info(struct sk_buff *skb,  const struct net_device *dev,
> @@ -734,11 +761,13 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
>  		     priv->xl.data_bitrate_const_cnt,
>  		     priv->xl.data_bitrate_const)) ||
>  
>  	    can_tdc_fill_info(skb, dev, &priv->xl, can_xl_tdc_is_enabled(priv),
>  			      priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MANUAL,
> -			      IFLA_CAN_XL_TDC)
> +			      IFLA_CAN_XL_TDC) ||
> +
> +	    nla_put(skb, IFLA_CAN_XL_PWM, sizeof(priv->pwm), &priv->pwm)

Same as above.

>  	    )
>  
>  		return -EMSGSIZE;
>  
>  	return 0;
> diff --git a/include/linux/can/bittiming.h b/include/linux/can/bittiming.h
> index 2053b9dff0ad..47e266ab7486 100644
> --- a/include/linux/can/bittiming.h
> +++ b/include/linux/can/bittiming.h
> @@ -114,10 +114,35 @@ struct can_tdc_const {
>  	u32 tdco_max;
>  	u32 tdcf_min;
>  	u32 tdcf_max;
>  };
>  
> +/*
> + * struct can_pwm - PWM configuration for switchable CAN XL transceivers
> + *
> + * -+-- init-offset -+------- one bit in CAN XL data mode --------+- TX pin
> + *  |<--- Offset --->|
> + *                   |<-------- Long 1 -------->|<--- Short 0 --->|  level_1
> + *                   |<--- Short 1 --->|<-------- Long 0 -------->|  level_0
> + *                                          |
> + *                                 (50/50 sample point)
> + *
> + * The duration of a complete PWM bit representation has to be < 200ns to
> + * reliably switch the CAN XL transceiver into the CAN XL data mode.
> + *
> + * @pwm_offset: Offset before first PWM bit trasmmission to fill the ADH bit
> + *
> + * @pwm_phase_long: PWM Phase Long (ideally 75% of PWM bit representation)
> + *
> + * @pwm_phase_short: PWM Phase Short (ideally 25% of PWM bit representation)
> + */
> +struct can_pwm {
> +	u8 pwm_offset;
> +	u8 pwm_phase_long;
> +	u8 pwm_phase_short;
> +};
> +
>  #ifdef CONFIG_CAN_CALC_BITTIMING
>  int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
>  		       const struct can_bittiming_const *btc, struct netlink_ext_ack *extack);
>  
>  void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const,
> diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
> index 1ac98914f351..6b65b3fccfd2 100644
> --- a/include/linux/can/dev.h
> +++ b/include/linux/can/dev.h
> @@ -60,10 +60,11 @@ struct can_priv {
>  	struct can_bittiming bittiming;
>  	struct data_bittiming_params fd, xl;
>  	unsigned int bitrate_const_cnt;
>  	const u32 *bitrate_const;
>  	u32 bitrate_max;
> +	struct can_pwm pwm;
>  	struct can_clock clock;
>  
>  	unsigned int termination_const_cnt;
>  	const u16 *termination_const;
>  	u16 termination;
> diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netlink.h
> index 163a6167264e..bd3706b37e04 100644
> --- a/include/uapi/linux/can/netlink.h
> +++ b/include/uapi/linux/can/netlink.h
> @@ -146,16 +146,31 @@ enum {
>  	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,
> +	IFLA_CAN_XL_PWM,
>  
>  	/* add new constants above here */
>  	__IFLA_CAN_MAX,
>  	IFLA_CAN_MAX = __IFLA_CAN_MAX - 1
>  };
>  
> +/*
> + * CAN XL Transceiver data mode switching PWM configuration
> + */
> +enum {
> +	IFLA_CAN_PWM_UNSPEC,
> +	IFLA_CAN_PWM_OFFSET,	/* u8 */
> +	IFLA_CAN_PWM_LONG,	/* u8 */
> +	IFLA_CAN_PWM_SHORT,	/* u8 */
> +
> +	/* add new constants above here */
> +	__IFLA_CAN_PWM,
> +	IFLA_CAN_PWM_MAX = __IFLA_CAN_PWM - 1
> +};
> +
>  /*
>   * CAN FD/XL Transmitter Delay Compensation (TDC)
>   *
>   * Please refer to struct can_tdc_const and can_tdc in
>   * include/linux/can/bittiming.h for further details.

Yours sincerely,
Vincent Mailhol


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 06/11] can: netlink: add CAN XL support
  2025-05-27 19:56 ` [PATCH 06/11] can: netlink: add CAN XL support Oliver Hartkopp
@ 2025-05-29  6:57   ` Marc Kleine-Budde
  0 siblings, 0 replies; 22+ messages in thread
From: Marc Kleine-Budde @ 2025-05-29  6:57 UTC (permalink / raw)
  To: Oliver Hartkopp; +Cc: linux-can

[-- Attachment #1: Type: text/plain, Size: 542 bytes --]

On 27.05.2025 21:56:20, Oliver Hartkopp wrote:
>  drivers/net/can/xilinx_can.c     |  12 +-

I've removed the changes in xlinix_can.c from my tree b4/can-xl, they
broke compilation. See https://lore.kernel.org/all/202505291443.O21tBseZ-lkp@intel.com/

regards,
Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde          |
Embedded Linux                   | https://www.pengutronix.de |
Vertretung Nürnberg              | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-9   |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 10/11] can: canxl: add PWM config support
  2025-05-29  1:17   ` Vincent Mailhol
@ 2025-05-29 12:49     ` Oliver Hartkopp
  0 siblings, 0 replies; 22+ messages in thread
From: Oliver Hartkopp @ 2025-05-29 12:49 UTC (permalink / raw)
  To: Vincent Mailhol, Stéphane Grosjean; +Cc: Marc Kleine-Budde, linux-can

Hi Vincent,

On 29.05.25 03:17, Vincent Mailhol wrote:

> How do you want to move forward on this?
> 
> I stopped my work, waiting for my preparation patches to be merged and for the
> PWM calculation to be clarified. Now that those two blockers are removed, I was
> about to resume the work.
> 
> Do you plan to take over? It will be complicated if both of us work
> simultaneously on the feature.

I just try to get my CAN XL hardware setup to work. Therefore I 
thankfully took your patches and added some stuff that was missing,
e.g. the RRS handling, the TRX switch handling, the Error Signalling 
switch (which might be obsolete according to Stephane) and the option to 
simply set the three PWM values without calculation.

So besides the RRS & TRX switch patches the other stuff can be seen as 
"hacks" to get it working in the meanwhile. It's no plan to take it over ;-)

I still would like to get my setup working based on your patches and 
give my feedback. So I would appreciate when you continue your work.

Best regards,
Oliver

> 
> 
> On 28/05/2025 at 04:56, Oliver Hartkopp wrote:
>> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
>> ---
>>   drivers/net/can/dev/netlink.c    | 31 ++++++++++++++++++++++++++++++-
>>   include/linux/can/bittiming.h    | 25 +++++++++++++++++++++++++
>>   include/linux/can/dev.h          |  1 +
>>   include/uapi/linux/can/netlink.h | 15 +++++++++++++++
>>   4 files changed, 71 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
>> index 1b798a7dcd64..685cceb74048 100644
>> --- a/drivers/net/can/dev/netlink.c
>> +++ b/drivers/net/can/dev/netlink.c
>> @@ -23,10 +23,11 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
>>   	[IFLA_CAN_TDC] = { .type = NLA_NESTED },
>>   	[IFLA_CAN_CTRLMODE_EXT] = { .type = NLA_NESTED },
>>   	[IFLA_CAN_XL_DATA_BITTIMING] = { .len = sizeof(struct can_bittiming) },
>>   	[IFLA_CAN_XL_DATA_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) },
>>   	[IFLA_CAN_XL_TDC] = { .type = NLA_NESTED },
>> +	[IFLA_CAN_XL_PWM] = { .type = NLA_NESTED },
>>   };
>>   
>>   static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = {
>>   	[IFLA_CAN_TDC_TDCV_MIN] = { .type = NLA_U32 },
>>   	[IFLA_CAN_TDC_TDCV_MAX] = { .type = NLA_U32 },
>> @@ -37,10 +38,16 @@ static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = {
>>   	[IFLA_CAN_TDC_TDCV] = { .type = NLA_U32 },
>>   	[IFLA_CAN_TDC_TDCO] = { .type = NLA_U32 },
>>   	[IFLA_CAN_TDC_TDCF] = { .type = NLA_U32 },
>>   };
>>   
>> +static const struct nla_policy can_pwm_policy[IFLA_CAN_PWM_MAX + 1] = {
>> +	[IFLA_CAN_PWM_OFFSET] = { .type = NLA_U8 },
>> +	[IFLA_CAN_PWM_LONG] = { .type = NLA_U8 },
>> +	[IFLA_CAN_PWM_SHORT] = { .type = NLA_U8 },
>> +};
> 
> ISO 11898-1 uses the accronyms PWML, PWMO and PWMS. I would prefer to keep the
> exact same naming as the standard.
> 
> Also, +1 to what Marc said, u32 seems better here.
> 
>>   static int can_validate_bittiming(const struct can_bittiming *bt,
>>   				  struct netlink_ext_ack *extack)
>>   {
>>   	/* sample point is in one-tenth of a percent */
>>   	if (bt->sample_point >= 1000) {
>> @@ -464,10 +471,29 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
>>   				 can_xl_tdc_is_enabled(priv),
>>   				 CAN_CTRLMODE_XL_TDC_MASK, extack);
>>   	if (err)
>>   		return err;
>>   
>> +	/* CAN XL transceiver PWM configuration */
>> +	if (data[IFLA_CAN_XL_PWM]) {
>> +		struct nlattr *tb_pwm[IFLA_CAN_PWM_MAX + 1];
>> +
>> +		err = 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_OFFSET])
>> +			priv->pwm.pwm_offset = nla_get_u8(tb_pwm[IFLA_CAN_PWM_OFFSET]) & 0x3F;
>> +
>> +		if (tb_pwm[IFLA_CAN_PWM_LONG])
>> +			priv->pwm.pwm_phase_long = nla_get_u8(tb_pwm[IFLA_CAN_PWM_LONG]) & 0x3F;
>> +
>> +		if (tb_pwm[IFLA_CAN_PWM_SHORT])
>> +			priv->pwm.pwm_phase_short = nla_get_u8(tb_pwm[IFLA_CAN_PWM_SHORT]) & 0x3F;
>> +	}
>> +
>>   	if (data[IFLA_CAN_TERMINATION]) {
>>   		const u16 termval = nla_get_u16(data[IFLA_CAN_TERMINATION]);
>>   		const unsigned int num_term = priv->termination_const_cnt;
>>   		unsigned int i;
>>   
>> @@ -573,10 +599,11 @@ static size_t can_get_size(const struct net_device *dev)
>>   		size += nla_total_size(sizeof(*priv->xl.data_bitrate_const) *
>>   				       priv->xl.data_bitrate_const_cnt);
>>   	size += can_tdc_get_size(&priv->xl,			/* IFLA_CAN_XL_TDC */
>>   				 can_xl_tdc_is_enabled(priv),
>>   				 priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MANUAL);
>> +	size += nla_total_size(sizeof(struct can_pwm));
> 
> This looks wrong. Does this work? The size of a nested NLA is the sum of its NLA
> members. Look at can_tdc_get_size().
> 
>>   	return size;
>>   }
>>   
>>   static int can_tdc_fill_info(struct sk_buff *skb,  const struct net_device *dev,
>> @@ -734,11 +761,13 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
>>   		     priv->xl.data_bitrate_const_cnt,
>>   		     priv->xl.data_bitrate_const)) ||
>>   
>>   	    can_tdc_fill_info(skb, dev, &priv->xl, can_xl_tdc_is_enabled(priv),
>>   			      priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MANUAL,
>> -			      IFLA_CAN_XL_TDC)
>> +			      IFLA_CAN_XL_TDC) ||
>> +
>> +	    nla_put(skb, IFLA_CAN_XL_PWM, sizeof(priv->pwm), &priv->pwm)
> 
> Same as above.
> 
>>   	    )
>>   
>>   		return -EMSGSIZE;
>>   
>>   	return 0;
>> diff --git a/include/linux/can/bittiming.h b/include/linux/can/bittiming.h
>> index 2053b9dff0ad..47e266ab7486 100644
>> --- a/include/linux/can/bittiming.h
>> +++ b/include/linux/can/bittiming.h
>> @@ -114,10 +114,35 @@ struct can_tdc_const {
>>   	u32 tdco_max;
>>   	u32 tdcf_min;
>>   	u32 tdcf_max;
>>   };
>>   
>> +/*
>> + * struct can_pwm - PWM configuration for switchable CAN XL transceivers
>> + *
>> + * -+-- init-offset -+------- one bit in CAN XL data mode --------+- TX pin
>> + *  |<--- Offset --->|
>> + *                   |<-------- Long 1 -------->|<--- Short 0 --->|  level_1
>> + *                   |<--- Short 1 --->|<-------- Long 0 -------->|  level_0
>> + *                                          |
>> + *                                 (50/50 sample point)
>> + *
>> + * The duration of a complete PWM bit representation has to be < 200ns to
>> + * reliably switch the CAN XL transceiver into the CAN XL data mode.
>> + *
>> + * @pwm_offset: Offset before first PWM bit trasmmission to fill the ADH bit
>> + *
>> + * @pwm_phase_long: PWM Phase Long (ideally 75% of PWM bit representation)
>> + *
>> + * @pwm_phase_short: PWM Phase Short (ideally 25% of PWM bit representation)
>> + */
>> +struct can_pwm {
>> +	u8 pwm_offset;
>> +	u8 pwm_phase_long;
>> +	u8 pwm_phase_short;
>> +};
>> +
>>   #ifdef CONFIG_CAN_CALC_BITTIMING
>>   int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
>>   		       const struct can_bittiming_const *btc, struct netlink_ext_ack *extack);
>>   
>>   void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const,
>> diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
>> index 1ac98914f351..6b65b3fccfd2 100644
>> --- a/include/linux/can/dev.h
>> +++ b/include/linux/can/dev.h
>> @@ -60,10 +60,11 @@ struct can_priv {
>>   	struct can_bittiming bittiming;
>>   	struct data_bittiming_params fd, xl;
>>   	unsigned int bitrate_const_cnt;
>>   	const u32 *bitrate_const;
>>   	u32 bitrate_max;
>> +	struct can_pwm pwm;
>>   	struct can_clock clock;
>>   
>>   	unsigned int termination_const_cnt;
>>   	const u16 *termination_const;
>>   	u16 termination;
>> diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netlink.h
>> index 163a6167264e..bd3706b37e04 100644
>> --- a/include/uapi/linux/can/netlink.h
>> +++ b/include/uapi/linux/can/netlink.h
>> @@ -146,16 +146,31 @@ enum {
>>   	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,
>> +	IFLA_CAN_XL_PWM,
>>   
>>   	/* add new constants above here */
>>   	__IFLA_CAN_MAX,
>>   	IFLA_CAN_MAX = __IFLA_CAN_MAX - 1
>>   };
>>   
>> +/*
>> + * CAN XL Transceiver data mode switching PWM configuration
>> + */
>> +enum {
>> +	IFLA_CAN_PWM_UNSPEC,
>> +	IFLA_CAN_PWM_OFFSET,	/* u8 */
>> +	IFLA_CAN_PWM_LONG,	/* u8 */
>> +	IFLA_CAN_PWM_SHORT,	/* u8 */
>> +
>> +	/* add new constants above here */
>> +	__IFLA_CAN_PWM,
>> +	IFLA_CAN_PWM_MAX = __IFLA_CAN_PWM - 1
>> +};
>> +
>>   /*
>>    * CAN FD/XL Transmitter Delay Compensation (TDC)
>>    *
>>    * Please refer to struct can_tdc_const and can_tdc in
>>    * include/linux/can/bittiming.h for further details.
> 
> Yours sincerely,
> Vincent Mailhol
> 


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 02/11] can: netlink: replace tabulation by space in assignment
  2025-05-28 16:12       ` Marc Kleine-Budde
  2025-05-29  0:30         ` Vincent Mailhol
@ 2025-06-11  7:10         ` Marc Kleine-Budde
  2025-06-11 11:29           ` Vincent Mailhol
  1 sibling, 1 reply; 22+ messages in thread
From: Marc Kleine-Budde @ 2025-06-11  7:10 UTC (permalink / raw)
  To: Vincent Mailhol; +Cc: Oliver Hartkopp, linux-can

[-- Attachment #1: Type: text/plain, Size: 1461 bytes --]

On 28.05.2025 18:12:53, Marc Kleine-Budde wrote:
> > > The patches 2...5 look good to me. If Oliver adds his S-o-b, I can take
> > > them for linux-can-next.
> > 
> > If you prefer, I already submitted those in the past in a dedicated series with
> > a proper cover letter:
> > 
> > https://lore.kernel.org/linux-can/20241112165118.586613-7-mailhol.vincent@wanadoo.fr/
> 
> Even better.

These are in net-next now \o/

> > Because I got zero answers, I split it even further. This is why only one patch
> > got merge in for 6.15. I was planning to resend those clean-up patches anyway,
> > but if you are OK to take them directly from my previous series, go ahead.
> > Nothing has changed for these since November, except from the first patch with
> > was merged separately.
> 
> I've adjusted the cover letter, as patch 1 is already mainline, and
> taken the rest of the series to can-next/testing. Note, once -rc1 is
> out, I'll rebase this branch.

I've rebased the remaining can-xl patches to current net-next/main and
pushed it to my b4/can-xl branch:

| https://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git/log/?h=b4/can-xl

regards,
Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde          |
Embedded Linux                   | https://www.pengutronix.de |
Vertretung Nürnberg              | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-9   |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 02/11] can: netlink: replace tabulation by space in assignment
  2025-06-11  7:10         ` Marc Kleine-Budde
@ 2025-06-11 11:29           ` Vincent Mailhol
  2025-06-11 12:02             ` Marc Kleine-Budde
  0 siblings, 1 reply; 22+ messages in thread
From: Vincent Mailhol @ 2025-06-11 11:29 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: Oliver Hartkopp, linux-can

On 11/06/2025 at 16:10, Marc Kleine-Budde wrote:
> On 28.05.2025 18:12:53, Marc Kleine-Budde wrote:
>>>> The patches 2...5 look good to me. If Oliver adds his S-o-b, I can take
>>>> them for linux-can-next.
>>>
>>> If you prefer, I already submitted those in the past in a dedicated series with
>>> a proper cover letter:
>>>
>>> https://lore.kernel.org/linux-can/20241112165118.586613-7-mailhol.vincent@wanadoo.fr/
>>
>> Even better.
> 
> These are in net-next now \o/
> 
>>> Because I got zero answers, I split it even further. This is why only one patch
>>> got merge in for 6.15. I was planning to resend those clean-up patches anyway,
>>> but if you are OK to take them directly from my previous series, go ahead.
>>> Nothing has changed for these since November, except from the first patch with
>>> was merged separately.
>>
>> I've adjusted the cover letter, as patch 1 is already mainline, and
>> taken the rest of the series to can-next/testing. Note, once -rc1 is
>> out, I'll rebase this branch.
> 
> I've rebased the remaining can-xl patches to current net-next/main and
> pushed it to my b4/can-xl branch:
> 
> | https://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git/log/?h=b4/can-xl

Yes, I saw the pull request.

I actually started to tidy up my previous work. So nice timing.

For the next step, I plan to split the CAN-XL series in two:

  1. One more preparation series that will do all the netlink.c refactor

  2. The actual stuff that will modify the uapi and add the CAN XL netlink
     interface

For point 1., it will be patch 6 to 11 and patch 13 of the original RFC:


https://lore.kernel.org/linux-can/20241110155902.72807-16-mailhol.vincent@wanadoo.fr/

Actually, I already have it ready in my local tree, I just need to double check
before sending.

I intend to have the preparation series 1. merged first before sending series 2.

On a different topic, I know have my kernel.org account. I do not know what is
the most convenient for you, but I could also create my own branch on
git.kernel.org. Or, if gitolite allows it, maybe you can give me write access to
your b4/can-xl branch? (I didn't check yet what gitolite offers in term of
access control…)


Yours sincerely,
Vincent Mailhol


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 02/11] can: netlink: replace tabulation by space in assignment
  2025-06-11 11:29           ` Vincent Mailhol
@ 2025-06-11 12:02             ` Marc Kleine-Budde
  0 siblings, 0 replies; 22+ messages in thread
From: Marc Kleine-Budde @ 2025-06-11 12:02 UTC (permalink / raw)
  To: Vincent Mailhol; +Cc: Oliver Hartkopp, linux-can

[-- Attachment #1: Type: text/plain, Size: 1539 bytes --]

On 11.06.2025 20:29:32, Vincent Mailhol wrote:
> Yes, I saw the pull request.
> 
> I actually started to tidy up my previous work. So nice timing.
> 
> For the next step, I plan to split the CAN-XL series in two:
> 
>   1. One more preparation series that will do all the netlink.c refactor
> 
>   2. The actual stuff that will modify the uapi and add the CAN XL netlink
>      interface
> 
> For point 1., it will be patch 6 to 11 and patch 13 of the original RFC:
> 
> https://lore.kernel.org/linux-can/20241110155902.72807-16-mailhol.vincent@wanadoo.fr/
> 
> Actually, I already have it ready in my local tree, I just need to double check
> before sending.

nice, looking forward for this.

> I intend to have the preparation series 1. merged first before sending series 2.

makes sense

> On a different topic, I know have my kernel.org account. I do not know what is
> the most convenient for you, but I could also create my own branch on
> git.kernel.org. Or, if gitolite allows it, maybe you can give me write access to
> your b4/can-xl branch? (I didn't check yet what gitolite offers in term of
> access control…)

I haven't checked access control, but it's faster/easier if you create a
b4/can-xl branch.

regards,
Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde          |
Embedded Linux                   | https://www.pengutronix.de |
Vertretung Nürnberg              | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-9   |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2025-06-11 12:02 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-27 19:56 [PATCH 01/11] can: dev: add struct data_bittiming_params to group FD parameters Oliver Hartkopp
2025-05-27 19:56 ` [PATCH 02/11] can: netlink: replace tabulation by space in assignment Oliver Hartkopp
2025-05-28  8:47   ` Marc Kleine-Budde
2025-05-28 15:51     ` Vincent Mailhol
2025-05-28 16:12       ` Marc Kleine-Budde
2025-05-29  0:30         ` Vincent Mailhol
2025-06-11  7:10         ` Marc Kleine-Budde
2025-06-11 11:29           ` Vincent Mailhol
2025-06-11 12:02             ` Marc Kleine-Budde
2025-05-27 19:56 ` [PATCH 03/11] can: bittiming: rename CAN_CTRLMODE_TDC_MASK into CAN_CTRLMODE_FD_TDC_MASK Oliver Hartkopp
2025-05-27 19:56 ` [PATCH 04/11] can: bittiming: rename can_tdc_is_enabled() into can_fd_tdc_is_enabled() Oliver Hartkopp
2025-05-27 19:56 ` [PATCH 05/11] can: netlink: can_changelink(): rename tdc_mask into fd_tdc_flag_provided Oliver Hartkopp
2025-05-27 19:56 ` [PATCH 06/11] can: netlink: add CAN XL support Oliver Hartkopp
2025-05-29  6:57   ` Marc Kleine-Budde
2025-05-27 19:56 ` [PATCH 07/11] can: canxl: support Remote Request Substitution bit access Oliver Hartkopp
2025-05-27 19:56 ` [PATCH 08/11] can: canxl: support CAN XL transceiver switching in data phase Oliver Hartkopp
2025-05-27 19:56 ` [PATCH 09/11] can: canxl: support CAN XL error signalling switching Oliver Hartkopp
2025-05-27 19:56 ` [PATCH 10/11] can: canxl: add PWM config support Oliver Hartkopp
2025-05-28 16:23   ` Marc Kleine-Budde
2025-05-29  1:17   ` Vincent Mailhol
2025-05-29 12:49     ` Oliver Hartkopp
2025-05-27 19:56 ` [PATCH 11/11] can: add CAN XL dummy driver DO NOT MERGE Oliver Hartkopp

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).