[RFC PATCH 12/14] can: netlink: add CAN XL support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add the netlink interface for CAN XL.

Signed-off-by: Vincent Mailhol <mailhol.vincent@xxxxxxxxxx>
---
 drivers/net/can/dev/netlink.c    | 78 +++++++++++++++++++++++++++++---
 include/linux/can/bittiming.h    |  2 +
 include/linux/can/dev.h          | 13 ++++--
 include/uapi/linux/can/netlink.h |  7 +++
 4 files changed, 90 insertions(+), 10 deletions(-)

diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
index 6c3fa5aa22cf..3c89b304c5b8 100644
--- a/drivers/net/can/dev/netlink.c
+++ b/drivers/net/can/dev/netlink.c
@@ -22,6 +22,9 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
 	[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] = {
@@ -55,6 +58,10 @@ static int can_validate_tdc(struct nlattr *data_tdc,
 {
 	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;
@@ -94,7 +101,7 @@ static int can_validate_tdc(struct nlattr *data_tdc,
 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
@@ -111,6 +118,7 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
 		struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
 
 		is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD;
+		is_can_xl = cm->flags & cm->mask & CAN_CTRLMODE_XL;
 
 		err = can_validate_tdc(data[IFLA_CAN_TDC],
 				       cm->flags & CAN_CTRLMODE_TDC_AUTO,
@@ -133,11 +141,19 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
 		if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_DATA_BITTIMING])
 			return -EOPNOTSUPP;
 	}
+	if (is_can_xl) {
+		if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_XL_DATA_BITTIMING])
+			return -EOPNOTSUPP;
+	}
 
 	if (data[IFLA_CAN_DATA_BITTIMING] || data[IFLA_CAN_TDC]) {
 		if (!is_can_fd)
 			return -EOPNOTSUPP;
 	}
+	if (data[IFLA_CAN_XL_DATA_BITTIMING] || data[IFLA_CAN_XL_TDC]) {
+		if (!is_can_xl)
+			return -EOPNOTSUPP;
+	}
 
 	if (data[IFLA_CAN_DATA_BITTIMING]) {
 		struct can_bittiming bt;
@@ -147,6 +163,14 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
 		if (err)
 			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)
+			return err;
+	}
 
 	return 0;
 }
@@ -275,8 +299,8 @@ 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() */
@@ -310,8 +334,10 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 		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;
@@ -322,11 +348,14 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 		}
 
 		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]) {
@@ -395,6 +424,15 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 	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;
@@ -494,6 +532,16 @@ static size_t can_get_size(const struct net_device *dev)
 				 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;
 }
@@ -634,7 +682,25 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
 	    can_tdc_fill_info(skb, dev, &priv->fd, can_fd_tdc_is_enabled(priv),
 			      priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL) ||
 
-	    can_ctrlmode_ext_fill_info(skb, priv)
+	    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_tdc_fill_info(skb, dev, &priv->xl, can_xl_tdc_is_enabled(priv),
+			      priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MANUAL)
 	    )
 
 		return -EMSGSIZE;
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
@@ -16,6 +16,8 @@
 
 #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
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
@@ -58,7 +58,7 @@ struct can_priv {
 
 	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;
@@ -96,6 +96,11 @@ 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
  *
@@ -116,13 +121,13 @@ static inline bool can_fd_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)
+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 */
diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netlink.h
index ef62f56eaaef..c81fd153a07f 100644
--- a/include/uapi/linux/can/netlink.h
+++ b/include/uapi/linux/can/netlink.h
@@ -103,6 +103,9 @@ struct can_ctrlmode {
 #define CAN_CTRLMODE_CC_LEN8_DLC	0x100	/* Classic CAN DLC option */
 #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	0x200	/* XL transceiver automatically calculates TDCV */
+#define CAN_CTRLMODE_XL_TDC_MANUAL	0x400	/* XL TDCV is manually set up by user */
 
 /*
  * CAN device statistics
@@ -138,6 +141,10 @@ enum {
 	IFLA_CAN_BITRATE_MAX,
 	IFLA_CAN_TDC, /* FD */
 	IFLA_CAN_CTRLMODE_EXT,
+	IFLA_CAN_XL_DATA_BITTIMING,
+	IFLA_CAN_XL_DATA_BITTIMING_CONST,
+	IFLA_CAN_XL_DATA_BITRATE_CONST,
+	IFLA_CAN_XL_TDC,
 
 	/* add new constants above here */
 	__IFLA_CAN_MAX,
-- 
2.45.2





[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux