From 0159a9305d401fd21a1cda5e7baaf62122c46a5b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 6 Jul 2022 10:59:48 +0300 Subject: [PATCH 01/29] can: slcan: use scnprintf() as a hardening measure The snprintf() function returns the number of bytes which *would* have been copied if there were no space. So, since this code does not check the return value, there if the buffer was not large enough then there would be a buffer overflow two lines later when it does: actual = sl->tty->ops->write(sl->tty, sl->xbuff, n); Use scnprintf() instead because that returns the number of bytes which were actually copied. Fixes: 52f9ac85b876 ("can: slcan: allow to send commands to the adapter") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/all/YsVA9KoY/ZSvNGYk@kili Signed-off-by: Marc Kleine-Budde --- drivers/net/can/slcan/slcan-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c index 54d29a410ad54..92bdd49996d1d 100644 --- a/drivers/net/can/slcan/slcan-core.c +++ b/drivers/net/can/slcan/slcan-core.c @@ -647,7 +647,7 @@ static int slcan_transmit_cmd(struct slcan *sl, const unsigned char *cmd) return -ENODEV; } - n = snprintf(sl->xbuff, sizeof(sl->xbuff), "%s", cmd); + n = scnprintf(sl->xbuff, sizeof(sl->xbuff), "%s", cmd); set_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags); actual = sl->tty->ops->write(sl->tty, sl->xbuff, n); sl->xleft = n - actual; From 71f3a4cc740ad214d04172832461d7e5fdfe71da Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sun, 3 Jul 2022 11:19:23 +0200 Subject: [PATCH 02/29] can: slcan: convert comments to network style comments Convert all comments to network subsystem style comments. Link: https://lore.kernel.org/all/20220704125954.1587880-2-mkl@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/slcan/slcan-core.c | 55 +++++++++++++----------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c index 92bdd49996d1d..2d3bf15061a74 100644 --- a/drivers/net/can/slcan/slcan-core.c +++ b/drivers/net/can/slcan/slcan-core.c @@ -67,8 +67,9 @@ MODULE_AUTHOR("Oliver Hartkopp "); #define SLCAN_MAGIC 0x53CA static int maxdev = 10; /* MAX number of SLCAN channels; - This can be overridden with - insmod slcan.ko maxdev=nnn */ + * This can be overridden with + * insmod slcan.ko maxdev=nnn + */ module_param(maxdev, int, 0); MODULE_PARM_DESC(maxdev, "Maximum number of slcan interfaces"); @@ -139,12 +140,11 @@ int slcan_enable_err_rst_on_open(struct net_device *ndev, bool on) return 0; } - /************************************************************************ - * SLCAN ENCAPSULATION FORMAT * - ************************************************************************/ +/************************************************************************* + * SLCAN ENCAPSULATION FORMAT * + *************************************************************************/ -/* - * A CAN frame has a can_id (11 bit standard frame format OR 29 bit extended +/* A CAN frame has a can_id (11 bit standard frame format OR 29 bit extended * frame format) a data length code (len) which can be from 0 to 8 * and up to data bytes as payload. * Additionally a CAN frame may become a remote transmission frame if the @@ -174,9 +174,9 @@ int slcan_enable_err_rst_on_open(struct net_device *ndev, bool on) * */ - /************************************************************************ - * STANDARD SLCAN DECAPSULATION * - ************************************************************************/ +/************************************************************************* + * STANDARD SLCAN DECAPSULATION * + *************************************************************************/ /* Send one completely decapsulated can_frame to the network layer */ static void slc_bump_frame(struct slcan *sl) @@ -486,9 +486,9 @@ static void slcan_unesc(struct slcan *sl, unsigned char s) } } - /************************************************************************ - * STANDARD SLCAN ENCAPSULATION * - ************************************************************************/ +/************************************************************************* + * STANDARD SLCAN ENCAPSULATION * + *************************************************************************/ /* Encapsulate one can_frame and stuff into a TTY queue. */ static void slc_encaps(struct slcan *sl, struct can_frame *cf) @@ -575,7 +575,8 @@ static void slcan_transmit(struct work_struct *work) } /* Now serial buffer is almost free & we can start - * transmission of another packet */ + * transmission of another packet + */ sl->dev->stats.tx_packets++; clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags); spin_unlock_bh(&sl->lock); @@ -589,8 +590,7 @@ static void slcan_transmit(struct work_struct *work) spin_unlock_bh(&sl->lock); } -/* - * Called by the driver when there's room for more data. +/* Called by the driver when there's room for more data. * Schedule the transmit. */ static void slcan_write_wakeup(struct tty_struct *tty) @@ -632,7 +632,6 @@ static netdev_tx_t slc_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } - /****************************************** * Routines looking at netdevice side. ******************************************/ @@ -736,7 +735,6 @@ static int slc_open(struct net_device *dev) /* The CAN framework has already validate the bitrate value, * so we can avoid to check if `s' has been properly set. */ - snprintf(cmd, sizeof(cmd), "C\rS%d\r", s); err = slcan_transmit_cmd(sl, cmd); if (err) { @@ -792,18 +790,16 @@ static const struct net_device_ops slc_netdev_ops = { }; /****************************************** - Routines looking at TTY side. + * Routines looking at TTY side. ******************************************/ -/* - * Handle the 'receiver data ready' interrupt. +/* Handle the 'receiver data ready' interrupt. * This function is called by the 'tty_io' module in the kernel when * a block of SLCAN data has been received, which can now be decapsulated * and sent on to some IP layer for further processing. This will not * be re-entered while running but other ldisc functions may be called * in parallel */ - static void slcan_receive_buf(struct tty_struct *tty, const unsigned char *cp, const char *fp, int count) @@ -890,8 +886,7 @@ static struct slcan *slc_alloc(void) return sl; } -/* - * Open the high-level part of the SLCAN channel. +/* Open the high-level part of the SLCAN channel. * This function is called by the TTY module when the * SLCAN line discipline is called for. Because we are * sure the tty line exists, we only have to link it to @@ -899,7 +894,6 @@ static struct slcan *slc_alloc(void) * * Called in process context serialized from other ldisc calls. */ - static int slcan_open(struct tty_struct *tty) { struct slcan *sl; @@ -912,8 +906,8 @@ static int slcan_open(struct tty_struct *tty) return -EOPNOTSUPP; /* RTnetlink lock is misused here to serialize concurrent - opens of slcan channels. There are better ways, but it is - the simplest one. + * opens of slcan channels. There are better ways, but it is + * the simplest one. */ rtnl_lock(); @@ -974,14 +968,12 @@ static int slcan_open(struct tty_struct *tty) return err; } -/* - * Close down a SLCAN channel. +/* Close down a SLCAN channel. * This means flushing out any pending queues, and then returning. This * call is serialized against other ldisc functions. * * We also use this method for a hangup event. */ - static void slcan_close(struct tty_struct *tty) { struct slcan *sl = (struct slcan *) tty->disc_data; @@ -1104,7 +1096,8 @@ static void __exit slcan_exit(void) } while (busy && time_before(jiffies, timeout)); /* FIXME: hangup is async so we should wait when doing this second - phase */ + * phase + */ for (i = 0; i < maxdev; i++) { dev = slcan_devs[i]; From ded5fa885b2d967dfc3e5b0dd85fcdf068cbe166 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sun, 3 Jul 2022 11:21:13 +0200 Subject: [PATCH 03/29] can: slcan: slcan_init() convert printk(LEVEL ...) to pr_level() Convert the last printk(LEVEL ...) to pr_level(). Link: https://lore.kernel.org/all/20220704125954.1587880-3-mkl@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/slcan/slcan-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c index 2d3bf15061a74..ead3afefcf19d 100644 --- a/drivers/net/can/slcan/slcan-core.c +++ b/drivers/net/can/slcan/slcan-core.c @@ -1057,7 +1057,7 @@ static int __init slcan_init(void) /* Fill in our line protocol discipline, and register it */ status = tty_register_ldisc(&slc_ldisc); if (status) { - printk(KERN_ERR "slcan: can't register line discipline\n"); + pr_err("slcan: can't register line discipline\n"); kfree(slcan_devs); } return status; From f07d9e3c849b9c320e89037e0835da04b0f583e4 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sun, 3 Jul 2022 11:23:18 +0200 Subject: [PATCH 04/29] can: slcan: fix whitespace issues Add and remove whitespace to make checkpatch happy. Link: https://lore.kernel.org/all/20220704125954.1587880-4-mkl@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/slcan/slcan-core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c index ead3afefcf19d..aa15c06dc198c 100644 --- a/drivers/net/can/slcan/slcan-core.c +++ b/drivers/net/can/slcan/slcan-core.c @@ -74,7 +74,7 @@ module_param(maxdev, int, 0); MODULE_PARM_DESC(maxdev, "Maximum number of slcan interfaces"); /* maximum rx buffer len: extended CAN frame with timestamp */ -#define SLC_MTU (sizeof("T1111222281122334455667788EA5F\r")+1) +#define SLC_MTU (sizeof("T1111222281122334455667788EA5F\r") + 1) #define SLC_CMD_LEN 1 #define SLC_SFF_ID_LEN 3 @@ -624,7 +624,7 @@ static netdev_tx_t slc_xmit(struct sk_buff *skb, struct net_device *dev) } netif_stop_queue(sl->dev); - slc_encaps(sl, (struct can_frame *) skb->data); /* encaps & send */ + slc_encaps(sl, (struct can_frame *)skb->data); /* encaps & send */ spin_unlock(&sl->lock); out: @@ -804,7 +804,7 @@ static void slcan_receive_buf(struct tty_struct *tty, const unsigned char *cp, const char *fp, int count) { - struct slcan *sl = (struct slcan *) tty->disc_data; + struct slcan *sl = (struct slcan *)tty->disc_data; if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev)) return; @@ -976,7 +976,7 @@ static int slcan_open(struct tty_struct *tty) */ static void slcan_close(struct tty_struct *tty) { - struct slcan *sl = (struct slcan *) tty->disc_data; + struct slcan *sl = (struct slcan *)tty->disc_data; /* First make sure we're connected. */ if (!sl || sl->magic != SLCAN_MAGIC || sl->tty != tty) @@ -1006,7 +1006,7 @@ static void slcan_hangup(struct tty_struct *tty) static int slcan_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { - struct slcan *sl = (struct slcan *) tty->disc_data; + struct slcan *sl = (struct slcan *)tty->disc_data; unsigned int tmp; /* First make sure we're connected. */ From 69a6539632dd9389e9c3b4e209308b74d5d46de5 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sun, 3 Jul 2022 11:24:26 +0200 Subject: [PATCH 05/29] can: slcan: convert comparison to NULL into !val All comparison to NULL could be written "!val", convert them to make checkpatch happy. Link: https://lore.kernel.org/all/20220704125954.1587880-5-mkl@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/slcan/slcan-core.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c index aa15c06dc198c..70a6d1ba46ebe 100644 --- a/drivers/net/can/slcan/slcan-core.c +++ b/drivers/net/can/slcan/slcan-core.c @@ -618,7 +618,7 @@ static netdev_tx_t slc_xmit(struct sk_buff *skb, struct net_device *dev) netdev_warn(dev, "xmit: iface is down\n"); goto out; } - if (sl->tty == NULL) { + if (!sl->tty) { spin_unlock(&sl->lock); goto out; } @@ -707,7 +707,7 @@ static int slc_open(struct net_device *dev) unsigned char cmd[SLC_MTU]; int err, s; - if (sl->tty == NULL) + if (!sl->tty) return -ENODEV; /* The baud rate is not set with the command @@ -834,7 +834,7 @@ static void slc_sync(void) for (i = 0; i < maxdev; i++) { dev = slcan_devs[i]; - if (dev == NULL) + if (!dev) break; sl = netdev_priv(dev); @@ -854,9 +854,8 @@ static struct slcan *slc_alloc(void) for (i = 0; i < maxdev; i++) { dev = slcan_devs[i]; - if (dev == NULL) + if (!dev) break; - } /* Sorry, too many, all slots in use */ @@ -902,7 +901,7 @@ static int slcan_open(struct tty_struct *tty) if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (tty->ops->write == NULL) + if (!tty->ops->write) return -EOPNOTSUPP; /* RTnetlink lock is misused here to serialize concurrent @@ -924,7 +923,7 @@ static int slcan_open(struct tty_struct *tty) /* OK. Find a free SLCAN channel to use. */ err = -ENFILE; sl = slc_alloc(); - if (sl == NULL) + if (!sl) goto err_exit; sl->tty = tty; @@ -1071,7 +1070,7 @@ static void __exit slcan_exit(void) unsigned long timeout = jiffies + HZ; int busy = 0; - if (slcan_devs == NULL) + if (!slcan_devs) return; /* First of all: check for active disciplines and hangup them. From 18de712a58021a3eda96f832eae58e66d5254c60 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sun, 3 Jul 2022 11:26:58 +0200 Subject: [PATCH 06/29] can: slcan: clean up if/else Remove braces after if() for single statement blocks, also remove else after return() in if() block. Link: https://lore.kernel.org/all/20220704125954.1587880-6-mkl@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/slcan/slcan-core.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c index 70a6d1ba46ebe..d9bf75a25988e 100644 --- a/drivers/net/can/slcan/slcan-core.c +++ b/drivers/net/can/slcan/slcan-core.c @@ -469,19 +469,19 @@ static void slcan_unesc(struct slcan *sl, unsigned char s) { if ((s == '\r') || (s == '\a')) { /* CR or BEL ends the pdu */ if (!test_and_clear_bit(SLF_ERROR, &sl->flags) && - (sl->rcount > 4)) { + sl->rcount > 4) slc_bump(sl); - } + sl->rcount = 0; } else { if (!test_bit(SLF_ERROR, &sl->flags)) { if (sl->rcount < SLC_MTU) { sl->rbuff[sl->rcount++] = s; return; - } else { - sl->dev->stats.rx_over_errors++; - set_bit(SLF_ERROR, &sl->flags); } + + sl->dev->stats.rx_over_errors++; + set_bit(SLF_ERROR, &sl->flags); } } } @@ -1104,9 +1104,8 @@ static void __exit slcan_exit(void) continue; sl = netdev_priv(dev); - if (sl->tty) { + if (sl->tty) netdev_err(dev, "tty discipline still running\n"); - } slc_close(dev); unregister_candev(dev); From f6b8061db9af1d3660160392e1d6591c2b03596d Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sun, 10 Jul 2022 12:52:43 +0100 Subject: [PATCH 07/29] dt-bindings: can: sja1000: Convert to json-schema Convert the NXP SJA1000 CAN Controller Device Tree binding documentation to json-schema. Update the example to match reality. Link: https://lore.kernel.org/all/20220710115248.190280-2-biju.das.jz@bp.renesas.com Signed-off-by: Biju Das Reviewed-by: Krzysztof Kozlowski Signed-off-by: Marc Kleine-Budde --- .../bindings/net/can/nxp,sja1000.yaml | 101 ++++++++++++++++++ .../devicetree/bindings/net/can/sja1000.txt | 58 ---------- 2 files changed, 101 insertions(+), 58 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/can/nxp,sja1000.yaml delete mode 100644 Documentation/devicetree/bindings/net/can/sja1000.txt diff --git a/Documentation/devicetree/bindings/net/can/nxp,sja1000.yaml b/Documentation/devicetree/bindings/net/can/nxp,sja1000.yaml new file mode 100644 index 0000000000000..ca9bfdfa50abf --- /dev/null +++ b/Documentation/devicetree/bindings/net/can/nxp,sja1000.yaml @@ -0,0 +1,101 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/can/nxp,sja1000.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Memory mapped SJA1000 CAN controller from NXP (formerly Philips) + +maintainers: + - Wolfgang Grandegger + +properties: + compatible: + enum: + - nxp,sja1000 + - technologic,sja1000 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + reg-io-width: + $ref: /schemas/types.yaml#/definitions/uint32 + description: I/O register width (in bytes) implemented by this device + default: 1 + enum: [ 1, 2, 4 ] + + nxp,external-clock-frequency: + $ref: /schemas/types.yaml#/definitions/uint32 + default: 16000000 + description: | + Frequency of the external oscillator clock in Hz. + The internal clock frequency used by the SJA1000 is half of that value. + + nxp,tx-output-mode: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 0, 1, 2, 3 ] + default: 1 + description: | + operation mode of the TX output control logic. Valid values are: + <0> : bi-phase output mode + <1> : normal output mode (default) + <2> : test output mode + <3> : clock output mode + + nxp,tx-output-config: + $ref: /schemas/types.yaml#/definitions/uint32 + default: 0x02 + description: | + TX output pin configuration. Valid values are any one of the below + or combination of TX0 and TX1: + <0x01> : TX0 invert + <0x02> : TX0 pull-down (default) + <0x04> : TX0 pull-up + <0x06> : TX0 push-pull + <0x08> : TX1 invert + <0x10> : TX1 pull-down + <0x20> : TX1 pull-up + <0x30> : TX1 push-pull + + nxp,clock-out-frequency: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + clock frequency in Hz on the CLKOUT pin. + If not specified or if the specified value is 0, the CLKOUT pin + will be disabled. + + nxp,no-comparator-bypass: + type: boolean + description: Allows to disable the CAN input comparator. + +required: + - compatible + - reg + - interrupts + +allOf: + - $ref: can-controller.yaml# + - if: + properties: + compatible: + contains: + const: technologic,sja1000 + then: + required: + - reg-io-width + +unevaluatedProperties: false + +examples: + - | + can@1a000 { + compatible = "technologic,sja1000"; + reg = <0x1a000 0x100>; + interrupts = <1>; + reg-io-width = <2>; + nxp,tx-output-config = <0x06>; + nxp,external-clock-frequency = <24000000>; + }; diff --git a/Documentation/devicetree/bindings/net/can/sja1000.txt b/Documentation/devicetree/bindings/net/can/sja1000.txt deleted file mode 100644 index ac3160eca96a2..0000000000000 --- a/Documentation/devicetree/bindings/net/can/sja1000.txt +++ /dev/null @@ -1,58 +0,0 @@ -Memory mapped SJA1000 CAN controller from NXP (formerly Philips) - -Required properties: - -- compatible : should be one of "nxp,sja1000", "technologic,sja1000". - -- reg : should specify the chip select, address offset and size required - to map the registers of the SJA1000. The size is usually 0x80. - -- interrupts: property with a value describing the interrupt source - (number and sensitivity) required for the SJA1000. - -Optional properties: - -- reg-io-width : Specify the size (in bytes) of the IO accesses that - should be performed on the device. Valid value is 1, 2 or 4. - This property is ignored for technologic version. - Default to 1 (8 bits). - -- nxp,external-clock-frequency : Frequency of the external oscillator - clock in Hz. Note that the internal clock frequency used by the - SJA1000 is half of that value. If not specified, a default value - of 16000000 (16 MHz) is used. - -- nxp,tx-output-mode : operation mode of the TX output control logic: - <0x0> : bi-phase output mode - <0x1> : normal output mode (default) - <0x2> : test output mode - <0x3> : clock output mode - -- nxp,tx-output-config : TX output pin configuration: - <0x01> : TX0 invert - <0x02> : TX0 pull-down (default) - <0x04> : TX0 pull-up - <0x06> : TX0 push-pull - <0x08> : TX1 invert - <0x10> : TX1 pull-down - <0x20> : TX1 pull-up - <0x30> : TX1 push-pull - -- nxp,clock-out-frequency : clock frequency in Hz on the CLKOUT pin. - If not specified or if the specified value is 0, the CLKOUT pin - will be disabled. - -- nxp,no-comparator-bypass : Allows to disable the CAN input comparator. - -For further information, please have a look to the SJA1000 data sheet. - -Examples: - -can@3,100 { - compatible = "nxp,sja1000"; - reg = <3 0x100 0x80>; - interrupts = <2 0>; - interrupt-parent = <&mpic>; - nxp,external-clock-frequency = <16000000>; -}; - From 4591c760b79759849b563605132e6afdd0149717 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sun, 10 Jul 2022 12:52:44 +0100 Subject: [PATCH 08/29] dt-bindings: can: nxp,sja1000: Document RZ/N1{D,S} support Add CAN binding documentation for Renesas RZ/N1 SoC. The SJA1000 CAN controller on RZ/N1 SoC has some differences compared to others like it has no clock divider register (CDR) support and it has no HW loopback (HW doesn't see tx messages on rx), so introduced a new compatible 'renesas,rzn1-sja1000' to handle these differences. Link: https://lore.kernel.org/all/20220710115248.190280-3-biju.das.jz@bp.renesas.com Signed-off-by: Biju Das Reviewed-by: Krzysztof Kozlowski Signed-off-by: Marc Kleine-Budde --- .../bindings/net/can/nxp,sja1000.yaml | 39 +++++++++++++++++-- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/net/can/nxp,sja1000.yaml b/Documentation/devicetree/bindings/net/can/nxp,sja1000.yaml index ca9bfdfa50abf..b1327c5b86cfb 100644 --- a/Documentation/devicetree/bindings/net/can/nxp,sja1000.yaml +++ b/Documentation/devicetree/bindings/net/can/nxp,sja1000.yaml @@ -11,9 +11,15 @@ maintainers: properties: compatible: - enum: - - nxp,sja1000 - - technologic,sja1000 + oneOf: + - enum: + - nxp,sja1000 + - technologic,sja1000 + - items: + - enum: + - renesas,r9a06g032-sja1000 # RZ/N1D + - renesas,r9a06g033-sja1000 # RZ/N1S + - const: renesas,rzn1-sja1000 # RZ/N1 reg: maxItems: 1 @@ -21,6 +27,9 @@ properties: interrupts: maxItems: 1 + clocks: + maxItems: 1 + reg-io-width: $ref: /schemas/types.yaml#/definitions/uint32 description: I/O register width (in bytes) implemented by this device @@ -82,10 +91,20 @@ allOf: properties: compatible: contains: - const: technologic,sja1000 + enum: + - technologic,sja1000 + - renesas,rzn1-sja1000 then: required: - reg-io-width + - if: + properties: + compatible: + contains: + const: renesas,rzn1-sja1000 + then: + required: + - clocks unevaluatedProperties: false @@ -99,3 +118,15 @@ examples: nxp,tx-output-config = <0x06>; nxp,external-clock-frequency = <24000000>; }; + + - | + #include + #include + + can@52104000 { + compatible = "renesas,r9a06g032-sja1000", "renesas,rzn1-sja1000"; + reg = <0x52104000 0x800>; + reg-io-width = <4>; + interrupts = ; + clocks = <&sysctrl R9A06G032_HCLK_CAN0>; + }; From 2d99bfbf3386962692dcccd73931cb0db07a1a43 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sun, 10 Jul 2022 12:52:45 +0100 Subject: [PATCH 09/29] can: sja1000: Add Quirk for RZ/N1 SJA1000 CAN controller As per Chapter 6.5.16 of the RZ/N1 Peripheral Manual, The SJA1000 CAN controller does not support Clock Divider Register compared to the reference Philips SJA1000 device. This patch adds a device quirk to handle this difference. Link: https://lore.kernel.org/all/20220710115248.190280-4-biju.das.jz@bp.renesas.com Signed-off-by: Biju Das Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sja1000/sja1000.c | 8 +++++--- drivers/net/can/sja1000/sja1000.h | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 2e7638f98cf1b..d9da471f1bb91 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -183,8 +183,9 @@ static void chipset_init(struct net_device *dev) { struct sja1000_priv *priv = netdev_priv(dev); - /* set clock divider and output control register */ - priv->write_reg(priv, SJA1000_CDR, priv->cdr | CDR_PELICAN); + if (!(priv->flags & SJA1000_QUIRK_NO_CDR_REG)) + /* set clock divider and output control register */ + priv->write_reg(priv, SJA1000_CDR, priv->cdr | CDR_PELICAN); /* set acceptance filter (accept all) */ priv->write_reg(priv, SJA1000_ACCC0, 0x00); @@ -209,7 +210,8 @@ static void sja1000_start(struct net_device *dev) set_reset_mode(dev); /* Initialize chip if uninitialized at this stage */ - if (!(priv->read_reg(priv, SJA1000_CDR) & CDR_PELICAN)) + if (!(priv->flags & SJA1000_QUIRK_NO_CDR_REG || + priv->read_reg(priv, SJA1000_CDR) & CDR_PELICAN)) chipset_init(dev); /* Clear error counters and error code capture */ diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h index 9d46398f81548..7f736f1df5474 100644 --- a/drivers/net/can/sja1000/sja1000.h +++ b/drivers/net/can/sja1000/sja1000.h @@ -145,7 +145,8 @@ /* * Flags for sja1000priv.flags */ -#define SJA1000_CUSTOM_IRQ_HANDLER 0x1 +#define SJA1000_CUSTOM_IRQ_HANDLER BIT(0) +#define SJA1000_QUIRK_NO_CDR_REG BIT(1) /* * SJA1000 private data structure From 63ab1b63695e65fe8cce32afc5319f121f0320f1 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sun, 10 Jul 2022 12:52:46 +0100 Subject: [PATCH 10/29] can: sja1000: Use device_get_match_data to get device data This patch replaces of_match_device->device_get_match_data to get pointer to device data. Link: https://lore.kernel.org/all/20220710115248.190280-5-biju.das.jz@bp.renesas.com Signed-off-by: Biju Das Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sja1000/sja1000_platform.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c index f9ec7bd8dfac0..0b78568f52863 100644 --- a/drivers/net/can/sja1000/sja1000_platform.c +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -210,7 +210,6 @@ static int sp_probe(struct platform_device *pdev) struct resource *res_mem, *res_irq = NULL; struct sja1000_platform_data *pdata; struct device_node *of = pdev->dev.of_node; - const struct of_device_id *of_id; const struct sja1000_of_data *of_data = NULL; size_t priv_sz = 0; @@ -243,11 +242,9 @@ static int sp_probe(struct platform_device *pdev) return -ENODEV; } - of_id = of_match_device(sp_of_table, &pdev->dev); - if (of_id && of_id->data) { - of_data = of_id->data; + of_data = device_get_match_data(&pdev->dev); + if (of_data) priv_sz = of_data->priv_sz; - } dev = alloc_sja1000dev(priv_sz); if (!dev) From 6d5fe10796bb3d336eac4962e71a3cbb6ff728f9 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sun, 10 Jul 2022 12:52:47 +0100 Subject: [PATCH 11/29] can: sja1000: Change the return type as void for SoC specific init Change the return type as void for SoC specific init function as it always return 0. Link: https://lore.kernel.org/all/20220710115248.190280-6-biju.das.jz@bp.renesas.com Signed-off-by: Biju Das Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sja1000/sja1000_platform.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c index 0b78568f52863..81bc741905fd0 100644 --- a/drivers/net/can/sja1000/sja1000_platform.c +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -31,7 +31,7 @@ MODULE_LICENSE("GPL v2"); struct sja1000_of_data { size_t priv_sz; - int (*init)(struct sja1000_priv *priv, struct device_node *of); + void (*init)(struct sja1000_priv *priv, struct device_node *of); }; struct technologic_priv { @@ -94,15 +94,13 @@ static void sp_technologic_write_reg16(const struct sja1000_priv *priv, spin_unlock_irqrestore(&tp->io_lock, flags); } -static int sp_technologic_init(struct sja1000_priv *priv, struct device_node *of) +static void sp_technologic_init(struct sja1000_priv *priv, struct device_node *of) { struct technologic_priv *tp = priv->priv; priv->read_reg = sp_technologic_read_reg16; priv->write_reg = sp_technologic_write_reg16; spin_lock_init(&tp->io_lock); - - return 0; } static void sp_populate(struct sja1000_priv *priv, @@ -266,11 +264,8 @@ static int sp_probe(struct platform_device *pdev) if (of) { sp_populate_of(priv, of); - if (of_data && of_data->init) { - err = of_data->init(priv, of); - if (err) - goto exit_free; - } + if (of_data && of_data->init) + of_data->init(priv, of); } else { sp_populate(priv, pdata, res_mem->flags); } From c6887023268e8c92c7409613065db7ba50b25f18 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Fri, 15 Jul 2022 09:29:51 +0200 Subject: [PATCH 12/29] can: slcan: do not sleep with a spin lock held We can't call close_candev() with a spin lock held, so release the lock before calling it. After calling close_candev(), we can update the fields of the private `struct can_priv' without having to acquire the lock. Fixes: c4e54b063f42f ("can: slcan: use CAN network device driver API") Link: https://lore.kernel.org/linux-kernel/Ysrf1Yc5DaRGN1WE@xsang-OptiPlex-9020/ Link: https://lore.kernel.org/all/20220715072951.859586-1-dario.binacchi@amarulasolutions.com Reported-by: kernel test robot Signed-off-by: Dario Binacchi Signed-off-by: Marc Kleine-Budde --- drivers/net/can/slcan/slcan-core.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c index d9bf75a25988e..057b211f3e7f4 100644 --- a/drivers/net/can/slcan/slcan-core.c +++ b/drivers/net/can/slcan/slcan-core.c @@ -688,15 +688,14 @@ static int slc_close(struct net_device *dev) clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags); } netif_stop_queue(dev); + sl->rcount = 0; + sl->xleft = 0; + spin_unlock_bh(&sl->lock); close_candev(dev); sl->can.state = CAN_STATE_STOPPED; if (sl->can.bittiming.bitrate == CAN_BITRATE_UNKNOWN) sl->can.bittiming.bitrate = CAN_BITRATE_UNSET; - sl->rcount = 0; - sl->xleft = 0; - spin_unlock_bh(&sl->lock); - return 0; } From 4940eb51fc49c6e89eb7ac4216f1983eec1d1c6f Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Sat, 16 Jul 2022 19:01:12 +0200 Subject: [PATCH 13/29] can: c_can: remove wrong comment The comment referred to a status (warning) other than the one that was being managed (active error). Link: https://lore.kernel.org/all/20220716170112.2020291-1-dario.binacchi@amarulasolutions.com Signed-off-by: Dario Binacchi Signed-off-by: Marc Kleine-Budde --- drivers/net/can/c_can/c_can_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/can/c_can/c_can_main.c b/drivers/net/can/c_can/c_can_main.c index a7362af0babb6..ed4db4cf87163 100644 --- a/drivers/net/can/c_can/c_can_main.c +++ b/drivers/net/can/c_can/c_can_main.c @@ -952,7 +952,6 @@ static int c_can_handle_state_change(struct net_device *dev, switch (error_type) { case C_CAN_NO_ERROR: - /* error warning state */ cf->can_id |= CAN_ERR_CRTL; cf->data[1] = CAN_ERR_CRTL_ACTIVE; cf->data[6] = bec.txerr; From 9e7c9b8eb719835638ee74d93dccc2173581324c Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Mon, 18 Jul 2022 12:26:21 +0200 Subject: [PATCH 14/29] can: ctucanfd: Update CTU CAN FD IP core registers to match version 3.x. The update is compatible/pure extension of 2.x IP core version - new option for 2, 4, or 8 Tx buffers option during synthesis. The 2.x version has fixed 4 Tx buffers. 3.x version default is 4 as well - new REG_TX_COMMAND_TXT_BUFFER_COUNT provides synthesis choice. When read as 0 assume 2.x core with fixed 4 Tx buffers. - new REG_ERR_CAPT_TS_BITS field to provide most significant active/implemented timestamp bit. For 2.x read as zero, assume value 63 is such case for 64 bit counter. - new REG_MODE_RXBAM bit which controls automatic advance to next word after Rx FIFO register read. Bit is set to 1 by default after the core reset (REG_MODE_RST) and value 1 has to be preserved for the normal ctucanfd Linux driver operation. Even preceding driver version resets core and then modifies only known/required MODE register bits so backward and forward compatibility is ensured. See complete datasheet for time-triggered and other updated capabilities http://canbus.pages.fel.cvut.cz/ctucanfd_ip_core/doc/Datasheet.pdf The fields related to ongoing Ondrej Ille's work on fault tolerant version with parity protected buffers and FIFOs are not included for now. Their inclusion will be considered when design is settled and tested. Link: https://lore.kernel.org/all/14a98ed1829121f0f3bde784f1aa533bc3cc7fe0.1658139843.git.pisa@cmp.felk.cvut.cz Signed-off-by: Pavel Pisa Signed-off-by: Marc Kleine-Budde --- drivers/net/can/ctucanfd/ctucanfd_kregs.h | 32 ++++++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/ctucanfd/ctucanfd_kregs.h b/drivers/net/can/ctucanfd/ctucanfd_kregs.h index edc1c1a243488..0c181ab51bf87 100644 --- a/drivers/net/can/ctucanfd/ctucanfd_kregs.h +++ b/drivers/net/can/ctucanfd/ctucanfd_kregs.h @@ -4,9 +4,9 @@ * CTU CAN FD IP Core * * Copyright (C) 2015-2018 Ondrej Ille FEE CTU - * Copyright (C) 2018-2021 Ondrej Ille self-funded + * Copyright (C) 2018-2022 Ondrej Ille self-funded * Copyright (C) 2018-2019 Martin Jerabek FEE CTU - * Copyright (C) 2018-2021 Pavel Pisa FEE CTU/self-funded + * Copyright (C) 2018-2022 Pavel Pisa FEE CTU/self-funded * * Project advisors: * Jiri Novak @@ -64,9 +64,12 @@ enum ctu_can_fd_can_registers { CTUCANFD_RX_DATA = 0x6c, CTUCANFD_TX_STATUS = 0x70, CTUCANFD_TX_COMMAND = 0x74, + CTUCANFD_TXTB_INFO = 0x76, CTUCANFD_TX_PRIORITY = 0x78, CTUCANFD_ERR_CAPT = 0x7c, + CTUCANFD_RETR_CTR = 0x7d, CTUCANFD_ALC = 0x7e, + CTUCANFD_TS_INFO = 0x7f, CTUCANFD_TRV_DELAY = 0x80, CTUCANFD_SSP_CFG = 0x82, CTUCANFD_RX_FR_CTR = 0x84, @@ -102,8 +105,12 @@ enum ctu_can_fd_can_registers { #define REG_MODE_STM BIT(2) #define REG_MODE_AFM BIT(3) #define REG_MODE_FDE BIT(4) +#define REG_MODE_TTTM BIT(5) +#define REG_MODE_ROM BIT(6) #define REG_MODE_ACF BIT(7) #define REG_MODE_TSTM BIT(8) +#define REG_MODE_RXBAM BIT(9) +#define REG_MODE_SAM BIT(11) #define REG_MODE_RTRLE BIT(16) #define REG_MODE_RTRTH GENMASK(20, 17) #define REG_MODE_ILBP BIT(21) @@ -123,8 +130,10 @@ enum ctu_can_fd_can_registers { #define REG_STATUS_EWL BIT(6) #define REG_STATUS_IDLE BIT(7) #define REG_STATUS_PEXS BIT(8) +#define REG_STATUS_STCNT BIT(16) /* COMMAND registers */ +#define REG_COMMAND_RXRPMV BIT(1) #define REG_COMMAND_RRB BIT(2) #define REG_COMMAND_CDO BIT(3) #define REG_COMMAND_ERCRST BIT(4) @@ -263,8 +272,12 @@ enum ctu_can_fd_can_registers { #define REG_TX_STATUS_TX2S GENMASK(7, 4) #define REG_TX_STATUS_TX3S GENMASK(11, 8) #define REG_TX_STATUS_TX4S GENMASK(15, 12) +#define REG_TX_STATUS_TX5S GENMASK(19, 16) +#define REG_TX_STATUS_TX6S GENMASK(23, 20) +#define REG_TX_STATUS_TX7S GENMASK(27, 24) +#define REG_TX_STATUS_TX8S GENMASK(31, 28) -/* TX_COMMAND registers */ +/* TX_COMMAND TXTB_INFO registers */ #define REG_TX_COMMAND_TXCE BIT(0) #define REG_TX_COMMAND_TXCR BIT(1) #define REG_TX_COMMAND_TXCA BIT(2) @@ -272,18 +285,29 @@ enum ctu_can_fd_can_registers { #define REG_TX_COMMAND_TXB2 BIT(9) #define REG_TX_COMMAND_TXB3 BIT(10) #define REG_TX_COMMAND_TXB4 BIT(11) +#define REG_TX_COMMAND_TXB5 BIT(12) +#define REG_TX_COMMAND_TXB6 BIT(13) +#define REG_TX_COMMAND_TXB7 BIT(14) +#define REG_TX_COMMAND_TXB8 BIT(15) +#define REG_TX_COMMAND_TXT_BUFFER_COUNT GENMASK(19, 16) /* TX_PRIORITY registers */ #define REG_TX_PRIORITY_TXT1P GENMASK(2, 0) #define REG_TX_PRIORITY_TXT2P GENMASK(6, 4) #define REG_TX_PRIORITY_TXT3P GENMASK(10, 8) #define REG_TX_PRIORITY_TXT4P GENMASK(14, 12) +#define REG_TX_PRIORITY_TXT5P GENMASK(18, 16) +#define REG_TX_PRIORITY_TXT6P GENMASK(22, 20) +#define REG_TX_PRIORITY_TXT7P GENMASK(26, 24) +#define REG_TX_PRIORITY_TXT8P GENMASK(30, 28) -/* ERR_CAPT ALC registers */ +/* ERR_CAPT RETR_CTR ALC TS_INFO registers */ #define REG_ERR_CAPT_ERR_POS GENMASK(4, 0) #define REG_ERR_CAPT_ERR_TYPE GENMASK(7, 5) +#define REG_ERR_CAPT_RETR_CTR_VAL GENMASK(11, 8) #define REG_ERR_CAPT_ALC_BIT GENMASK(20, 16) #define REG_ERR_CAPT_ALC_ID_FIELD GENMASK(23, 21) +#define REG_ERR_CAPT_TS_BITS GENMASK(29, 24) /* TRV_DELAY SSP_CFG registers */ #define REG_TRV_DELAY_TRV_DELAY_VALUE GENMASK(6, 0) From 92505df464ff16a0cfb7ae27533f0978dca0bce5 Mon Sep 17 00:00:00 2001 From: Stephane Grosjean Date: Tue, 19 Jul 2022 14:06:30 +0200 Subject: [PATCH 15/29] can: peak_usb: pcan_dump_mem(): mark input prompt and data pointer as const Mark the input prompt and data pointer as const. Link: https://lore.kernel.org/all/20220719120632.26774-1-s.grosjean@peak-system.com Signed-off-by: Stephane Grosjean [mkl: mark data pointer as const, too; update commit message] Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/peak_usb/pcan_usb_core.c | 2 +- drivers/net/can/usb/peak_usb/pcan_usb_core.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 b850ff8fe4bd5..27b0a72fd885b 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -57,7 +57,7 @@ MODULE_DEVICE_TABLE(usb, peak_usb_table); * dump memory */ #define DUMP_WIDTH 16 -void pcan_dump_mem(char *prompt, void *p, int l) +void pcan_dump_mem(const char *prompt, const void *p, int l) { pr_info("%s dumping %s (%d bytes):\n", PCAN_USB_DRIVER_NAME, prompt ? prompt : "memory", l); diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.h b/drivers/net/can/usb/peak_usb/pcan_usb_core.h index f60af573a2e01..9c90487b9c920 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.h +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.h @@ -132,7 +132,7 @@ struct peak_usb_device { struct peak_usb_device *next_siblings; }; -void pcan_dump_mem(char *prompt, void *p, int l); +void pcan_dump_mem(const char *prompt, const void *p, int l); /* common timestamp management */ void peak_usb_init_time_ref(struct peak_time_ref *time_ref, From a0cf2fe6cf2eff9fa74181e8cf2116d35ba47a09 Mon Sep 17 00:00:00 2001 From: Stephane Grosjean Date: Tue, 19 Jul 2022 14:06:31 +0200 Subject: [PATCH 16/29] can: peak_usb: correction of an initially misnamed field name The data structure returned from the USB device contains a number flashed by the user and not the serial number of the device. Link: https://lore.kernel.org/all/20220719120632.26774-2-s.grosjean@peak-system.com Signed-off-by: Stephane Grosjean Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/peak_usb/pcan_usb_pro.c | 2 +- drivers/net/can/usb/peak_usb/pcan_usb_pro.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c index ebe087f258e30..457887113e755 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c @@ -439,7 +439,7 @@ static int pcan_usb_pro_get_device_id(struct peak_usb_device *dev, return err; pdn = (struct pcan_usb_pro_devid *)pc; - *device_id = le32_to_cpu(pdn->serial_num); + *device_id = le32_to_cpu(pdn->dev_num); return err; } diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.h b/drivers/net/can/usb/peak_usb/pcan_usb_pro.h index 5d4cf14eb9d9e..a34e0fc021c96 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.h +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.h @@ -112,7 +112,7 @@ struct __packed pcan_usb_pro_devid { u8 data_type; u8 channel; __le16 dummy; - __le32 serial_num; + __le32 dev_num; }; #define PCAN_USBPRO_LED_DEVICE 0x00 From 4f232482467a354a74e08633faa1ed93fe00ee5e Mon Sep 17 00:00:00 2001 From: Stephane Grosjean Date: Tue, 19 Jul 2022 14:06:32 +0200 Subject: [PATCH 17/29] can: peak_usb: include support for a new MCU The CANFD-USB PCAN-USB FD interface undergoes an internal component change that requires a slight modification of its drivers, which leads them to dynamically use endpoint numbers provided by the interface itself. In addition to a change in the calls to the USB functions exported by the kernel, the detection of the USB interface dedicated to CAN must also be modified, as some PEAK-System devices support other interfaces than CAN. Link: https://lore.kernel.org/all/20220719120632.26774-3-s.grosjean@peak-system.com Signed-off-by: Stephane Grosjean [mkl: add missing cpu_to_le16() conversion] [mkl: fix networking block comment style] Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/peak_usb/pcan_usb_fd.c | 68 ++++++++++++++++++---- 1 file changed, 58 insertions(+), 10 deletions(-) diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c index 65487ec335669..3d7e0e370505b 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c @@ -33,6 +33,10 @@ #define PCAN_UFD_RX_BUFFER_SIZE 2048 #define PCAN_UFD_TX_BUFFER_SIZE 512 +/* struct pcan_ufd_fw_info::type */ +#define PCAN_USBFD_TYPE_STD 1 +#define PCAN_USBFD_TYPE_EXT 2 /* includes EP numbers */ + /* read some versions info from the hw device */ struct __packed pcan_ufd_fw_info { __le16 size_of; /* sizeof this */ @@ -44,6 +48,13 @@ struct __packed pcan_ufd_fw_info { __le32 dev_id[2]; /* "device id" per CAN */ __le32 ser_no; /* S/N */ __le32 flags; /* special functions */ + + /* extended data when type == PCAN_USBFD_TYPE_EXT */ + u8 cmd_out_ep; /* ep for cmd */ + u8 cmd_in_ep; /* ep for replies */ + u8 data_out_ep[2]; /* ep for CANx TX */ + u8 data_in_ep; /* ep for CAN RX */ + u8 dummy[3]; }; /* handle device specific info used by the netdevices */ @@ -171,6 +182,9 @@ static inline void *pcan_usb_fd_cmd_buffer(struct peak_usb_device *dev) /* send PCAN-USB Pro FD commands synchronously */ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail) { + struct pcan_usb_fd_device *pdev = + container_of(dev, struct pcan_usb_fd_device, dev); + struct pcan_ufd_fw_info *fw_info = &pdev->usb_if->fw_info; void *cmd_head = pcan_usb_fd_cmd_buffer(dev); int err = 0; u8 *packet_ptr; @@ -200,7 +214,7 @@ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail) do { err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, - PCAN_USBPRO_EP_CMDOUT), + fw_info->cmd_out_ep), packet_ptr, packet_len, NULL, PCAN_UFD_CMD_TIMEOUT_MS); if (err) { @@ -426,6 +440,9 @@ static int pcan_usb_fd_set_bittiming_fast(struct peak_usb_device *dev, static int pcan_usb_fd_restart_async(struct peak_usb_device *dev, struct urb *urb, u8 *buf) { + struct pcan_usb_fd_device *pdev = + container_of(dev, struct pcan_usb_fd_device, dev); + struct pcan_ufd_fw_info *fw_info = &pdev->usb_if->fw_info; u8 *pc = buf; /* build the entire cmds list in the provided buffer, to go back into @@ -439,7 +456,7 @@ static int pcan_usb_fd_restart_async(struct peak_usb_device *dev, /* complete the URB */ usb_fill_bulk_urb(urb, dev->udev, - usb_sndbulkpipe(dev->udev, PCAN_USBPRO_EP_CMDOUT), + usb_sndbulkpipe(dev->udev, fw_info->cmd_out_ep), buf, pc - buf, pcan_usb_pro_restart_complete, dev); @@ -839,6 +856,15 @@ static int pcan_usb_fd_get_berr_counter(const struct net_device *netdev, return 0; } +/* probe function for all PCAN-USB FD family usb interfaces */ +static int pcan_usb_fd_probe(struct usb_interface *intf) +{ + struct usb_host_interface *iface_desc = &intf->altsetting[0]; + + /* CAN interface is always interface #0 */ + return iface_desc->desc.bInterfaceNumber; +} + /* stop interface (last chance before set bus off) */ static int pcan_usb_fd_stop(struct peak_usb_device *dev) { @@ -860,6 +886,7 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) { struct pcan_usb_fd_device *pdev = container_of(dev, struct pcan_usb_fd_device, dev); + struct pcan_ufd_fw_info *fw_info; int i, err = -ENOMEM; /* do this for 1st channel only */ @@ -878,10 +905,12 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) /* number of ts msgs to ignore before taking one into account */ pdev->usb_if->cm_ignore_count = 5; + fw_info = &pdev->usb_if->fw_info; + err = pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_INFO, PCAN_USBPRO_INFO_FW, - &pdev->usb_if->fw_info, - sizeof(pdev->usb_if->fw_info)); + fw_info, + sizeof(*fw_info)); if (err) { dev_err(dev->netdev->dev.parent, "unable to read %s firmware info (err %d)\n", @@ -895,14 +924,14 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) */ dev_info(dev->netdev->dev.parent, "PEAK-System %s v%u fw v%u.%u.%u (%u channels)\n", - dev->adapter->name, pdev->usb_if->fw_info.hw_version, - pdev->usb_if->fw_info.fw_version[0], - pdev->usb_if->fw_info.fw_version[1], - pdev->usb_if->fw_info.fw_version[2], + dev->adapter->name, fw_info->hw_version, + fw_info->fw_version[0], + fw_info->fw_version[1], + fw_info->fw_version[2], dev->adapter->ctrl_count); /* check for ability to switch between ISO/non-ISO modes */ - if (pdev->usb_if->fw_info.fw_version[0] >= 2) { + if (fw_info->fw_version[0] >= 2) { /* firmware >= 2.x supports ISO/non-ISO switching */ dev->can.ctrlmode_supported |= CAN_CTRLMODE_FD_NON_ISO; } else { @@ -910,6 +939,14 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) dev->can.ctrlmode |= CAN_CTRLMODE_FD_NON_ISO; } + /* if vendor rsp is of type 2, then it contains EP numbers to + * use for cmds pipes. If not, then default EP should be used. + */ + if (fw_info->type != cpu_to_le16(PCAN_USBFD_TYPE_EXT)) { + fw_info->cmd_out_ep = PCAN_USBPRO_EP_CMDOUT; + fw_info->cmd_in_ep = PCAN_USBPRO_EP_CMDIN; + } + /* tell the hardware the can driver is running */ err = pcan_usb_fd_drv_loaded(dev, 1); if (err) { @@ -930,12 +967,23 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) /* do a copy of the ctrlmode[_supported] too */ dev->can.ctrlmode = ppdev->dev.can.ctrlmode; dev->can.ctrlmode_supported = ppdev->dev.can.ctrlmode_supported; + + fw_info = &pdev->usb_if->fw_info; } pdev->usb_if->dev[dev->ctrl_idx] = dev; dev->device_number = le32_to_cpu(pdev->usb_if->fw_info.dev_id[dev->ctrl_idx]); + /* if vendor rsp is of type 2, then it contains EP numbers to + * use for data pipes. If not, then statically defined EP are used + * (see peak_usb_create_dev()). + */ + if (fw_info->type == cpu_to_le16(PCAN_USBFD_TYPE_EXT)) { + dev->ep_msg_in = fw_info->data_in_ep; + dev->ep_msg_out = fw_info->data_out_ep[dev->ctrl_idx]; + } + /* set clock domain */ for (i = 0; i < ARRAY_SIZE(pcan_usb_fd_clk_freq); i++) if (dev->adapter->clock.freq == pcan_usb_fd_clk_freq[i]) @@ -1091,7 +1139,7 @@ const struct peak_usb_adapter pcan_usb_fd = { .tx_buffer_size = PCAN_UFD_TX_BUFFER_SIZE, /* device callbacks */ - .intf_probe = pcan_usb_pro_probe, /* same as PCAN-USB Pro */ + .intf_probe = pcan_usb_fd_probe, .dev_init = pcan_usb_fd_init, .dev_exit = pcan_usb_fd_exit, From 3a5c7e4611ddcf0ef37a3a17296b964d986161a6 Mon Sep 17 00:00:00 2001 From: Vincent Mailhol Date: Tue, 19 Jul 2022 23:35:39 +0900 Subject: [PATCH 18/29] can: pch_can: do not report txerr and rxerr during bus-off During bus off, the error count is greater than 255 and can not fit in a u8. Fixes: 0c78ab76a05c ("pch_can: Add setting TEC/REC statistics processing") Link: https://lore.kernel.org/all/20220719143550.3681-2-mailhol.vincent@wanadoo.fr Signed-off-by: Vincent Mailhol Signed-off-by: Marc Kleine-Budde --- drivers/net/can/pch_can.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index fde3ac516d264..497ef77340ea0 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c @@ -496,6 +496,9 @@ static void pch_can_error(struct net_device *ndev, u32 status) cf->can_id |= CAN_ERR_BUSOFF; priv->can.can_stats.bus_off++; can_bus_off(ndev); + } else { + cf->data[6] = errc & PCH_TEC; + cf->data[7] = (errc & PCH_REC) >> 8; } errc = ioread32(&priv->regs->errc); @@ -556,9 +559,6 @@ static void pch_can_error(struct net_device *ndev, u32 status) break; } - cf->data[6] = errc & PCH_TEC; - cf->data[7] = (errc & PCH_REC) >> 8; - priv->can.state = state; netif_receive_skb(skb); } From a37b7245e831a641df360ca41db6a71c023d3746 Mon Sep 17 00:00:00 2001 From: Vincent Mailhol Date: Tue, 19 Jul 2022 23:35:40 +0900 Subject: [PATCH 19/29] can: rcar_can: do not report txerr and rxerr during bus-off During bus off, the error count is greater than 255 and can not fit in a u8. Fixes: fd1159318e55 ("can: add Renesas R-Car CAN driver") Link: https://lore.kernel.org/all/20220719143550.3681-3-mailhol.vincent@wanadoo.fr Signed-off-by: Vincent Mailhol Signed-off-by: Marc Kleine-Budde --- drivers/net/can/rcar/rcar_can.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c index d45762f1cf6bc..24d7a71def6a0 100644 --- a/drivers/net/can/rcar/rcar_can.c +++ b/drivers/net/can/rcar/rcar_can.c @@ -232,11 +232,8 @@ static void rcar_can_error(struct net_device *ndev) if (eifr & (RCAR_CAN_EIFR_EWIF | RCAR_CAN_EIFR_EPIF)) { txerr = readb(&priv->regs->tecr); rxerr = readb(&priv->regs->recr); - if (skb) { + if (skb) cf->can_id |= CAN_ERR_CRTL; - cf->data[6] = txerr; - cf->data[7] = rxerr; - } } if (eifr & RCAR_CAN_EIFR_BEIF) { int rx_errors = 0, tx_errors = 0; @@ -336,6 +333,9 @@ static void rcar_can_error(struct net_device *ndev) can_bus_off(ndev); if (skb) cf->can_id |= CAN_ERR_BUSOFF; + } else if (skb) { + cf->data[6] = txerr; + cf->data[7] = rxerr; } if (eifr & RCAR_CAN_EIFR_ORIF) { netdev_dbg(priv->ndev, "Receive overrun error interrupt\n"); From 164d7cb2d5a30f1b3a5ab4fab1a27731fb1494a8 Mon Sep 17 00:00:00 2001 From: Vincent Mailhol Date: Tue, 19 Jul 2022 23:35:41 +0900 Subject: [PATCH 20/29] can: sja1000: do not report txerr and rxerr during bus-off During bus off, the error count is greater than 255 and can not fit in a u8. Fixes: 215db1856e83 ("can: sja1000: Consolidate and unify state change handling") Link: https://lore.kernel.org/all/20220719143550.3681-4-mailhol.vincent@wanadoo.fr Signed-off-by: Vincent Mailhol Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sja1000/sja1000.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index d9da471f1bb91..74bff5092b472 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -404,9 +404,6 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) txerr = priv->read_reg(priv, SJA1000_TXERR); rxerr = priv->read_reg(priv, SJA1000_RXERR); - cf->data[6] = txerr; - cf->data[7] = rxerr; - if (isrc & IRQ_DOI) { /* data overrun interrupt */ netdev_dbg(dev, "data overrun interrupt\n"); @@ -428,6 +425,10 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) else state = CAN_STATE_ERROR_ACTIVE; } + if (state != CAN_STATE_BUS_OFF) { + cf->data[6] = txerr; + cf->data[7] = rxerr; + } if (isrc & IRQ_BEI) { /* bus error interrupt */ priv->can.can_stats.bus_error++; From ce0e7aeb676b40e765ec5b88d690fa9fa252c373 Mon Sep 17 00:00:00 2001 From: Vincent Mailhol Date: Tue, 19 Jul 2022 23:35:42 +0900 Subject: [PATCH 21/29] can: slcan: do not report txerr and rxerr during bus-off During bus off, the error count is greater than 255 and can not fit in a u8. alloc_can_err_skb() already sets cf to NULL if the allocation fails [1], so the redundant cf = NULL assignment gets removed. [1] https://elixir.bootlin.com/linux/latest/source/drivers/net/can/dev/skb.c#L187 Fixes: 0a9cdcf098a4 ("can: slcan: extend the protocol with CAN state info") Link: https://lore.kernel.org/all/20220719143550.3681-5-mailhol.vincent@wanadoo.fr CC: Dario Binacchi Signed-off-by: Vincent Mailhol Signed-off-by: Marc Kleine-Budde --- drivers/net/can/slcan/slcan-core.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c index 057b211f3e7f4..dfd1baba41300 100644 --- a/drivers/net/can/slcan/slcan-core.c +++ b/drivers/net/can/slcan/slcan-core.c @@ -306,19 +306,17 @@ static void slc_bump_state(struct slcan *sl) return; skb = alloc_can_err_skb(dev, &cf); - if (skb) { - cf->data[6] = txerr; - cf->data[7] = rxerr; - } else { - cf = NULL; - } tx_state = txerr >= rxerr ? state : 0; rx_state = txerr <= rxerr ? state : 0; can_change_state(dev, cf, tx_state, rx_state); - if (state == CAN_STATE_BUS_OFF) + if (state == CAN_STATE_BUS_OFF) { can_bus_off(dev); + } else if (skb) { + cf->data[6] = txerr; + cf->data[7] = rxerr; + } if (skb) netif_rx(skb); From a22bd630cfff496b270211745536e50e98eb3a45 Mon Sep 17 00:00:00 2001 From: Vincent Mailhol Date: Tue, 19 Jul 2022 23:35:43 +0900 Subject: [PATCH 22/29] can: hi311x: do not report txerr and rxerr during bus-off During bus off, the error count is greater than 255 and can not fit in a u8. Fixes: 57e83fb9b746 ("can: hi311x: Add Holt HI-311x CAN driver") Link: https://lore.kernel.org/all/20220719143550.3681-6-mailhol.vincent@wanadoo.fr Signed-off-by: Vincent Mailhol Signed-off-by: Marc Kleine-Budde --- drivers/net/can/spi/hi311x.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c index ebc4ebb44c980..bfb7c4bb5bc32 100644 --- a/drivers/net/can/spi/hi311x.c +++ b/drivers/net/can/spi/hi311x.c @@ -667,8 +667,6 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id) txerr = hi3110_read(spi, HI3110_READ_TEC); rxerr = hi3110_read(spi, HI3110_READ_REC); - cf->data[6] = txerr; - cf->data[7] = rxerr; tx_state = txerr >= rxerr ? new_state : 0; rx_state = txerr <= rxerr ? new_state : 0; can_change_state(net, cf, tx_state, rx_state); @@ -681,6 +679,9 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id) hi3110_hw_sleep(spi); break; } + } else { + cf->data[6] = txerr; + cf->data[7] = rxerr; } } From 0ac15a8f661b941519379831d09bfb12271b23ee Mon Sep 17 00:00:00 2001 From: Vincent Mailhol Date: Tue, 19 Jul 2022 23:35:44 +0900 Subject: [PATCH 23/29] can: sun4i_can: do not report txerr and rxerr during bus-off During bus off, the error count is greater than 255 and can not fit in a u8. Fixes: 0738eff14d81 ("can: Allwinner A10/A20 CAN Controller support - Kernel module") Link: https://lore.kernel.org/all/20220719143550.3681-7-mailhol.vincent@wanadoo.fr CC: Chen-Yu Tsai Signed-off-by: Vincent Mailhol Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sun4i_can.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index 155b90f6c767c..afe9b541f0376 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -535,11 +535,6 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status) rxerr = (errc >> 16) & 0xFF; txerr = errc & 0xFF; - if (skb) { - cf->data[6] = txerr; - cf->data[7] = rxerr; - } - if (isrc & SUN4I_INT_DATA_OR) { /* data overrun interrupt */ netdev_dbg(dev, "data overrun interrupt\n"); @@ -570,6 +565,10 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status) else state = CAN_STATE_ERROR_ACTIVE; } + if (skb && state != CAN_STATE_BUS_OFF) { + cf->data[6] = txerr; + cf->data[7] = rxerr; + } if (isrc & SUN4I_INT_BUS_ERR) { /* bus error interrupt */ netdev_dbg(dev, "bus error interrupt\n"); From 936e90595376e64b6247c72d3ea8b8b164b7ac96 Mon Sep 17 00:00:00 2001 From: Vincent Mailhol Date: Tue, 19 Jul 2022 23:35:45 +0900 Subject: [PATCH 24/29] can: kvaser_usb_hydra: do not report txerr and rxerr during bus-off During bus off, the error count is greater than 255 and can not fit in a u8. Fixes: aec5fb2268b7 ("can: kvaser_usb: Add support for Kvaser USB hydra family") Link: https://lore.kernel.org/all/20220719143550.3681-8-mailhol.vincent@wanadoo.fr CC: Jimmy Assarsson Signed-off-by: Vincent Mailhol Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c index 5d70844ac0300..404093468b2f1 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c @@ -917,8 +917,10 @@ static void kvaser_usb_hydra_update_state(struct kvaser_usb_net_priv *priv, new_state < CAN_STATE_BUS_OFF) priv->can.can_stats.restarts++; - cf->data[6] = bec->txerr; - cf->data[7] = bec->rxerr; + if (new_state != CAN_STATE_BUS_OFF) { + cf->data[6] = bec->txerr; + cf->data[7] = bec->rxerr; + } netif_rx(skb); } @@ -1069,8 +1071,10 @@ kvaser_usb_hydra_error_frame(struct kvaser_usb_net_priv *priv, shhwtstamps->hwtstamp = hwtstamp; cf->can_id |= CAN_ERR_BUSERROR; - cf->data[6] = bec.txerr; - cf->data[7] = bec.rxerr; + if (new_state != CAN_STATE_BUS_OFF) { + cf->data[6] = bec.txerr; + cf->data[7] = bec.rxerr; + } netif_rx(skb); From a57732084e06791d37ea1ea447cca46220737abd Mon Sep 17 00:00:00 2001 From: Vincent Mailhol Date: Tue, 19 Jul 2022 23:35:46 +0900 Subject: [PATCH 25/29] can: kvaser_usb_leaf: do not report txerr and rxerr during bus-off During bus off, the error count is greater than 255 and can not fit in a u8. Fixes: 7259124eac7d1 ("can: kvaser_usb: Split driver into kvaser_usb_core.c and kvaser_usb_leaf.c") Link: https://lore.kernel.org/all/20220719143550.3681-9-mailhol.vincent@wanadoo.fr CC: Jimmy Assarsson Signed-off-by: Vincent Mailhol Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c index cc809ecd1e622..f551fde16a709 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c @@ -853,8 +853,10 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev, break; } - cf->data[6] = es->txerr; - cf->data[7] = es->rxerr; + if (new_state != CAN_STATE_BUS_OFF) { + cf->data[6] = es->txerr; + cf->data[7] = es->rxerr; + } netif_rx(skb); } From aebe8a2433cd090ccdc222861f44bddb75eb01de Mon Sep 17 00:00:00 2001 From: Vincent Mailhol Date: Tue, 19 Jul 2022 23:35:47 +0900 Subject: [PATCH 26/29] can: usb_8dev: do not report txerr and rxerr during bus-off During bus off, the error count is greater than 255 and can not fit in a u8. Fixes: 0024d8ad1639 ("can: usb_8dev: Add support for USB2CAN interface from 8 devices") Link: https://lore.kernel.org/all/20220719143550.3681-10-mailhol.vincent@wanadoo.fr Signed-off-by: Vincent Mailhol Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/usb_8dev.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c index f3363575bf32c..4d38dc90472a8 100644 --- a/drivers/net/can/usb/usb_8dev.c +++ b/drivers/net/can/usb/usb_8dev.c @@ -438,9 +438,10 @@ static void usb_8dev_rx_err_msg(struct usb_8dev_priv *priv, if (rx_errors) stats->rx_errors++; - - cf->data[6] = txerr; - cf->data[7] = rxerr; + if (priv->can.state != CAN_STATE_BUS_OFF) { + cf->data[6] = txerr; + cf->data[7] = rxerr; + } priv->bec.txerr = txerr; priv->bec.rxerr = rxerr; From e70a3263a7eed768d5f947b8f2aff8d2a79c9d97 Mon Sep 17 00:00:00 2001 From: Vincent Mailhol Date: Tue, 19 Jul 2022 23:35:48 +0900 Subject: [PATCH 27/29] can: error: specify the values of data[5..7] of CAN error frames Currently, data[5..7] of struct can_frame, when used as a CAN error frame, are defined as being "controller specific". Device specific behaviours are problematic because it prevents someone from writing code which is portable between devices. As a matter of fact, data[5] is never used, data[6] is always used to report TX error counter and data[7] is always used to report RX error counter. can-utils also relies on this. This patch updates the comment in the uapi header to specify that data[5] is reserved (and thus should not be used) and that data[6..7] are used for error counters. Fixes: 0d66548a10cb ("[CAN]: Add PF_CAN core module") Link: https://lore.kernel.org/all/20220719143550.3681-11-mailhol.vincent@wanadoo.fr Signed-off-by: Vincent Mailhol Signed-off-by: Marc Kleine-Budde --- include/uapi/linux/can/error.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/can/error.h b/include/uapi/linux/can/error.h index 34633283de641..a1000cb630632 100644 --- a/include/uapi/linux/can/error.h +++ b/include/uapi/linux/can/error.h @@ -120,6 +120,9 @@ #define CAN_ERR_TRX_CANL_SHORT_TO_GND 0x70 /* 0111 0000 */ #define CAN_ERR_TRX_CANL_SHORT_TO_CANH 0x80 /* 1000 0000 */ -/* controller specific additional information / data[5..7] */ +/* data[5] is reserved (do not use) */ + +/* TX error counter / data[6] */ +/* RX error counter / data[7] */ #endif /* _UAPI_CAN_ERROR_H */ From 3e5c291c7942d0909a48bc5ec1b9bba136465166 Mon Sep 17 00:00:00 2001 From: Vincent Mailhol Date: Tue, 19 Jul 2022 23:35:49 +0900 Subject: [PATCH 28/29] can: add CAN_ERR_CNT flag to notify availability of error counter Add a dedicated flag in uapi/linux/can/error.h to notify the userland that fields data[6] and data[7] of the CAN error frame were respectively populated with the tx and rx error counters. For all driver tree-wide, set up this flags whenever needed. Link: https://lore.kernel.org/all/20220719143550.3681-12-mailhol.vincent@wanadoo.fr Signed-off-by: Vincent Mailhol Signed-off-by: Marc Kleine-Budde --- drivers/net/can/c_can/c_can_main.c | 6 +++--- drivers/net/can/cc770/cc770.c | 1 + drivers/net/can/ctucanfd/ctucanfd_base.c | 5 +++-- drivers/net/can/grcan.c | 1 + drivers/net/can/ifi_canfd/ifi_canfd.c | 4 ++-- drivers/net/can/janz-ican3.c | 4 ++-- drivers/net/can/kvaser_pciefd.c | 2 +- drivers/net/can/m_can/m_can.c | 4 ++-- drivers/net/can/pch_can.c | 1 + drivers/net/can/peak_canfd/peak_canfd.c | 6 +++--- drivers/net/can/rcar/rcar_can.c | 1 + drivers/net/can/rcar/rcar_canfd.c | 4 ++-- drivers/net/can/sja1000/sja1000.c | 1 + drivers/net/can/slcan/slcan-core.c | 1 + drivers/net/can/spi/hi311x.c | 1 + drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 1 + drivers/net/can/sun4i_can.c | 1 + drivers/net/can/ti_hecc.c | 1 + drivers/net/can/usb/esd_usb.c | 3 ++- drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 2 ++ drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 1 + drivers/net/can/usb/peak_usb/pcan_usb.c | 1 + drivers/net/can/usb/usb_8dev.c | 1 + drivers/net/can/xilinx_can.c | 1 + include/uapi/linux/can/error.h | 2 ++ 25 files changed, 38 insertions(+), 18 deletions(-) diff --git a/drivers/net/can/c_can/c_can_main.c b/drivers/net/can/c_can/c_can_main.c index ed4db4cf87163..de38d8f7b5f7a 100644 --- a/drivers/net/can/c_can/c_can_main.c +++ b/drivers/net/can/c_can/c_can_main.c @@ -952,14 +952,14 @@ static int c_can_handle_state_change(struct net_device *dev, switch (error_type) { case C_CAN_NO_ERROR: - cf->can_id |= CAN_ERR_CRTL; + cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; cf->data[1] = CAN_ERR_CRTL_ACTIVE; cf->data[6] = bec.txerr; cf->data[7] = bec.rxerr; break; case C_CAN_ERROR_WARNING: /* error warning state */ - cf->can_id |= CAN_ERR_CRTL; + cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; cf->data[1] = (bec.txerr > bec.rxerr) ? CAN_ERR_CRTL_TX_WARNING : CAN_ERR_CRTL_RX_WARNING; @@ -969,7 +969,7 @@ static int c_can_handle_state_change(struct net_device *dev, break; case C_CAN_ERROR_PASSIVE: /* error passive state */ - cf->can_id |= CAN_ERR_CRTL; + cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; if (rx_err_passive) cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; if (bec.txerr > 127) diff --git a/drivers/net/can/cc770/cc770.c b/drivers/net/can/cc770/cc770.c index bb7224cfc6ab5..797a954bb1a0c 100644 --- a/drivers/net/can/cc770/cc770.c +++ b/drivers/net/can/cc770/cc770.c @@ -512,6 +512,7 @@ static int cc770_err(struct net_device *dev, u8 status) /* Use extended functions of the CC770 */ if (priv->control_normal_mode & CTRL_EAF) { + cf->can_id |= CAN_ERR_CNT; cf->data[6] = cc770_read_reg(priv, tx_error_counter); cf->data[7] = cc770_read_reg(priv, rx_error_counter); } diff --git a/drivers/net/can/ctucanfd/ctucanfd_base.c b/drivers/net/can/ctucanfd/ctucanfd_base.c index 14ac7c0ee04ce..6b281f6eb9b41 100644 --- a/drivers/net/can/ctucanfd/ctucanfd_base.c +++ b/drivers/net/can/ctucanfd/ctucanfd_base.c @@ -847,7 +847,7 @@ static void ctucan_err_interrupt(struct net_device *ndev, u32 isr) case CAN_STATE_ERROR_PASSIVE: priv->can.can_stats.error_passive++; if (skb) { - cf->can_id |= CAN_ERR_CRTL; + cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; cf->data[1] = (bec.rxerr > 127) ? CAN_ERR_CRTL_RX_PASSIVE : CAN_ERR_CRTL_TX_PASSIVE; @@ -858,7 +858,7 @@ static void ctucan_err_interrupt(struct net_device *ndev, u32 isr) case CAN_STATE_ERROR_WARNING: priv->can.can_stats.error_warning++; if (skb) { - cf->can_id |= CAN_ERR_CRTL; + cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; cf->data[1] |= (bec.txerr > bec.rxerr) ? CAN_ERR_CRTL_TX_WARNING : CAN_ERR_CRTL_RX_WARNING; @@ -867,6 +867,7 @@ static void ctucan_err_interrupt(struct net_device *ndev, u32 isr) } break; case CAN_STATE_ERROR_ACTIVE: + cf->can_id |= CAN_ERR_CNT; cf->data[1] = CAN_ERR_CRTL_ACTIVE; cf->data[6] = bec.txerr; cf->data[7] = bec.rxerr; diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c index 4c47c1055eff9..24035a6187c98 100644 --- a/drivers/net/can/grcan.c +++ b/drivers/net/can/grcan.c @@ -671,6 +671,7 @@ static void grcan_err(struct net_device *dev, u32 sources, u32 status) /* There are no others at this point */ break; } + cf.can_id |= CAN_ERR_CNT; cf.data[6] = txerr; cf.data[7] = rxerr; priv->can.state = state; diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c index 968ed6d7316bb..64e3be8b73af5 100644 --- a/drivers/net/can/ifi_canfd/ifi_canfd.c +++ b/drivers/net/can/ifi_canfd/ifi_canfd.c @@ -492,7 +492,7 @@ static int ifi_canfd_handle_state_change(struct net_device *ndev, switch (new_state) { case CAN_STATE_ERROR_WARNING: /* error warning state */ - cf->can_id |= CAN_ERR_CRTL; + cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; cf->data[1] = (bec.txerr > bec.rxerr) ? CAN_ERR_CRTL_TX_WARNING : CAN_ERR_CRTL_RX_WARNING; @@ -501,7 +501,7 @@ static int ifi_canfd_handle_state_change(struct net_device *ndev, break; case CAN_STATE_ERROR_PASSIVE: /* error passive state */ - cf->can_id |= CAN_ERR_CRTL; + cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; if (bec.txerr > 127) cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE; diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 35bfb82d69299..ccb5c5405224e 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -1127,7 +1127,7 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg) /* bus error interrupt */ if (isrc == CEVTIND_BEI) { mod->can.can_stats.bus_error++; - cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR | CAN_ERR_CNT; switch (ecc & ECC_MASK) { case ECC_BIT: @@ -1153,7 +1153,7 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg) if (state != mod->can.state && (state == CAN_STATE_ERROR_WARNING || state == CAN_STATE_ERROR_PASSIVE)) { - cf->can_id |= CAN_ERR_CRTL; + cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; if (state == CAN_STATE_ERROR_WARNING) { mod->can.can_stats.error_warning++; cf->data[1] = (txerr > rxerr) ? diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c index 017f2d36ffc38..dcd2c9d50d5e2 100644 --- a/drivers/net/can/kvaser_pciefd.c +++ b/drivers/net/can/kvaser_pciefd.c @@ -1306,7 +1306,7 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can, shhwtstamps->hwtstamp = ns_to_ktime(div_u64(p->timestamp * 1000, can->kv_pcie->freq_to_ticks_div)); - cf->can_id |= CAN_ERR_BUSERROR; + cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_CNT; cf->data[6] = bec.txerr; cf->data[7] = bec.rxerr; diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index afaaeb610c005..713a4b0edf860 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -741,7 +741,7 @@ static int m_can_handle_state_change(struct net_device *dev, switch (new_state) { case CAN_STATE_ERROR_WARNING: /* error warning state */ - cf->can_id |= CAN_ERR_CRTL; + cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; cf->data[1] = (bec.txerr > bec.rxerr) ? CAN_ERR_CRTL_TX_WARNING : CAN_ERR_CRTL_RX_WARNING; @@ -750,7 +750,7 @@ static int m_can_handle_state_change(struct net_device *dev, break; case CAN_STATE_ERROR_PASSIVE: /* error passive state */ - cf->can_id |= CAN_ERR_CRTL; + cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; ecr = m_can_read(cdev, M_CAN_ECR); if (ecr & ECR_RP) cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index 497ef77340ea0..50f6719b3aa44 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c @@ -497,6 +497,7 @@ static void pch_can_error(struct net_device *ndev, u32 status) priv->can.can_stats.bus_off++; can_bus_off(ndev); } else { + cf->can_id |= CAN_ERR_CNT; cf->data[6] = errc & PCH_TEC; cf->data[7] = (errc & PCH_REC) >> 8; } diff --git a/drivers/net/can/peak_canfd/peak_canfd.c b/drivers/net/can/peak_canfd/peak_canfd.c index b2dea360813d2..afb9adb3d5c29 100644 --- a/drivers/net/can/peak_canfd/peak_canfd.c +++ b/drivers/net/can/peak_canfd/peak_canfd.c @@ -373,7 +373,7 @@ static int pucan_handle_status(struct peak_canfd_priv *priv, priv->can.state = CAN_STATE_ERROR_PASSIVE; priv->can.can_stats.error_passive++; if (skb) { - cf->can_id |= CAN_ERR_CRTL; + cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; cf->data[1] = (priv->bec.txerr > priv->bec.rxerr) ? CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE; @@ -386,7 +386,7 @@ static int pucan_handle_status(struct peak_canfd_priv *priv, priv->can.state = CAN_STATE_ERROR_WARNING; priv->can.can_stats.error_warning++; if (skb) { - cf->can_id |= CAN_ERR_CRTL; + cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; cf->data[1] = (priv->bec.txerr > priv->bec.rxerr) ? CAN_ERR_CRTL_TX_WARNING : CAN_ERR_CRTL_RX_WARNING; @@ -430,7 +430,7 @@ static int pucan_handle_cache_critical(struct peak_canfd_priv *priv) return -ENOMEM; } - cf->can_id |= CAN_ERR_CRTL; + cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; cf->data[6] = priv->bec.txerr; diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c index 24d7a71def6a0..d11db2112a4a7 100644 --- a/drivers/net/can/rcar/rcar_can.c +++ b/drivers/net/can/rcar/rcar_can.c @@ -334,6 +334,7 @@ static void rcar_can_error(struct net_device *ndev) if (skb) cf->can_id |= CAN_ERR_BUSOFF; } else if (skb) { + cf->can_id |= CAN_ERR_CNT; cf->data[6] = txerr; cf->data[7] = rxerr; } diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c index ba42cef10a532..e3382284e172e 100644 --- a/drivers/net/can/rcar/rcar_canfd.c +++ b/drivers/net/can/rcar/rcar_canfd.c @@ -1052,7 +1052,7 @@ static void rcar_canfd_error(struct net_device *ndev, u32 cerfl, netdev_dbg(ndev, "Error warning interrupt\n"); priv->can.state = CAN_STATE_ERROR_WARNING; priv->can.can_stats.error_warning++; - cf->can_id |= CAN_ERR_CRTL; + cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; cf->data[1] = txerr > rxerr ? CAN_ERR_CRTL_TX_WARNING : CAN_ERR_CRTL_RX_WARNING; cf->data[6] = txerr; @@ -1062,7 +1062,7 @@ static void rcar_canfd_error(struct net_device *ndev, u32 cerfl, netdev_dbg(ndev, "Error passive interrupt\n"); priv->can.state = CAN_STATE_ERROR_PASSIVE; priv->can.can_stats.error_passive++; - cf->can_id |= CAN_ERR_CRTL; + cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; cf->data[1] = txerr > rxerr ? CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE; cf->data[6] = txerr; diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 74bff5092b472..75a2f9bf8c16b 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -426,6 +426,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) state = CAN_STATE_ERROR_ACTIVE; } if (state != CAN_STATE_BUS_OFF) { + cf->can_id |= CAN_ERR_CNT; cf->data[6] = txerr; cf->data[7] = rxerr; } diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c index dfd1baba41300..dc28e715bbe17 100644 --- a/drivers/net/can/slcan/slcan-core.c +++ b/drivers/net/can/slcan/slcan-core.c @@ -314,6 +314,7 @@ static void slc_bump_state(struct slcan *sl) if (state == CAN_STATE_BUS_OFF) { can_bus_off(dev); } else if (skb) { + cf->can_id |= CAN_ERR_CNT; cf->data[6] = txerr; cf->data[7] = rxerr; } diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c index bfb7c4bb5bc32..167114aae6dd1 100644 --- a/drivers/net/can/spi/hi311x.c +++ b/drivers/net/can/spi/hi311x.c @@ -680,6 +680,7 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id) break; } } else { + cf->can_id |= CAN_ERR_CNT; cf->data[6] = txerr; cf->data[7] = rxerr; } diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c index 9b47b07162fe5..f4e174cadd4ef 100644 --- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c +++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c @@ -1099,6 +1099,7 @@ static int mcp251xfd_handle_cerrif(struct mcp251xfd_priv *priv) err = mcp251xfd_get_berr_counter(priv->ndev, &bec); if (err) return err; + cf->can_id |= CAN_ERR_CNT; cf->data[6] = bec.txerr; cf->data[7] = bec.rxerr; } diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index afe9b541f0376..b90dfb429ccdc 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -566,6 +566,7 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status) state = CAN_STATE_ERROR_ACTIVE; } if (skb && state != CAN_STATE_BUS_OFF) { + cf->can_id |= CAN_ERR_CNT; cf->data[6] = txerr; cf->data[7] = rxerr; } diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index debe17bfd0f0e..afa38771520eb 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -662,6 +662,7 @@ static void ti_hecc_change_state(struct net_device *ndev, can_change_state(priv->ndev, cf, tx_state, rx_state); if (max(tx_state, rx_state) != CAN_STATE_BUS_OFF) { + cf->can_id |= CAN_ERR_CNT; cf->data[6] = hecc_read(priv, HECC_CANTEC); cf->data[7] = hecc_read(priv, HECC_CANREC); } diff --git a/drivers/net/can/usb/esd_usb.c b/drivers/net/can/usb/esd_usb.c index 8a4bf2961f3d8..177ed33e08d9e 100644 --- a/drivers/net/can/usb/esd_usb.c +++ b/drivers/net/can/usb/esd_usb.c @@ -265,7 +265,8 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, priv->can.can_stats.bus_error++; stats->rx_errors++; - cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR | + CAN_ERR_CNT; switch (ecc & SJA1000_ECC_MASK) { case SJA1000_ECC_BIT: diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c index 404093468b2f1..dd65c101bfb8e 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c @@ -918,6 +918,7 @@ static void kvaser_usb_hydra_update_state(struct kvaser_usb_net_priv *priv, priv->can.can_stats.restarts++; if (new_state != CAN_STATE_BUS_OFF) { + cf->can_id |= CAN_ERR_CNT; cf->data[6] = bec->txerr; cf->data[7] = bec->rxerr; } @@ -1072,6 +1073,7 @@ kvaser_usb_hydra_error_frame(struct kvaser_usb_net_priv *priv, cf->can_id |= CAN_ERR_BUSERROR; if (new_state != CAN_STATE_BUS_OFF) { + cf->can_id |= CAN_ERR_CNT; cf->data[6] = bec.txerr; cf->data[7] = bec.rxerr; } diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c index f551fde16a709..07f687f29b341 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c @@ -854,6 +854,7 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev, } if (new_state != CAN_STATE_BUS_OFF) { + cf->can_id |= CAN_ERR_CNT; cf->data[6] = es->txerr; cf->data[7] = es->rxerr; } diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c index 091c631ebe235..d07b7ee79e3e4 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb.c @@ -506,6 +506,7 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n, /* Supply TX/RX error counters in case of * controller error. */ + cf->can_id = CAN_ERR_CNT; cf->data[6] = mc->pdev->bec.txerr; cf->data[7] = mc->pdev->bec.rxerr; } diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c index 4d38dc90472a8..8b7cd69e20b04 100644 --- a/drivers/net/can/usb/usb_8dev.c +++ b/drivers/net/can/usb/usb_8dev.c @@ -439,6 +439,7 @@ static void usb_8dev_rx_err_msg(struct usb_8dev_priv *priv, if (rx_errors) stats->rx_errors++; if (priv->can.state != CAN_STATE_BUS_OFF) { + cf->can_id |= CAN_ERR_CNT; cf->data[6] = txerr; cf->data[7] = rxerr; } diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 0de2f97d9f62f..caa6b4cee63f2 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -965,6 +965,7 @@ static void xcan_set_error_state(struct net_device *ndev, can_change_state(ndev, cf, tx_state, rx_state); if (cf) { + cf->can_id |= CAN_ERR_CNT; cf->data[6] = txerr; cf->data[7] = rxerr; } diff --git a/include/uapi/linux/can/error.h b/include/uapi/linux/can/error.h index a1000cb630632..b7c3efd9ff992 100644 --- a/include/uapi/linux/can/error.h +++ b/include/uapi/linux/can/error.h @@ -57,6 +57,8 @@ #define CAN_ERR_BUSOFF 0x00000040U /* bus off */ #define CAN_ERR_BUSERROR 0x00000080U /* bus error (may flood!) */ #define CAN_ERR_RESTARTED 0x00000100U /* controller restarted */ +#define CAN_ERR_CNT 0x00000200U /* TX error counter / data[6] */ + /* RX error counter / data[7] */ /* arbitration lost in bit ... / data[0] */ #define CAN_ERR_LOSTARB_UNSPEC 0x00 /* unspecified */ From 3f9c26210cf80ea8cb5dd901aba5feb77200b085 Mon Sep 17 00:00:00 2001 From: Vincent Mailhol Date: Tue, 19 Jul 2022 23:35:50 +0900 Subject: [PATCH 29/29] can: error: add definitions for the different CAN error thresholds Currently, drivers are using magic numbers to derive the CAN error states from the error counter. Add three macro declarations to remediate this. For reference, the error-active, error-passive and bus-off are defined in ISO 11898, section 12.1.4.2 "Error counting". Although ISO 11898 does not define error-warning state, this extra value is also commonly used and is thus also added. Link: https://lore.kernel.org/all/20220719143550.3681-13-mailhol.vincent@wanadoo.fr Signed-off-by: Vincent Mailhol Signed-off-by: Marc Kleine-Budde --- include/uapi/linux/can/error.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/uapi/linux/can/error.h b/include/uapi/linux/can/error.h index b7c3efd9ff992..acc1ac393d2a1 100644 --- a/include/uapi/linux/can/error.h +++ b/include/uapi/linux/can/error.h @@ -127,4 +127,17 @@ /* TX error counter / data[6] */ /* RX error counter / data[7] */ +/* CAN state thresholds + * + * Error counter Error state + * ----------------------------------- + * 0 - 95 Error-active + * 96 - 127 Error-warning + * 128 - 255 Error-passive + * 256 and greater Bus-off + */ +#define CAN_ERROR_WARNING_THRESHOLD 96 +#define CAN_ERROR_PASSIVE_THRESHOLD 128 +#define CAN_BUS_OFF_THRESHOLD 256 + #endif /* _UAPI_CAN_ERROR_H */