Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

can: length: refactor frame lengths definition to add size in bits

Introduce a method to calculate the exact size in bits of a CAN(-FD)
frame with or without dynamic bitstuffing.

These are all the possible combinations taken into account:

- Classical CAN or CAN-FD
- Standard or Extended frame format
- CAN-FD CRC17 or CRC21
- Include or not intermission

Instead of doing several individual macro definitions, declare the
can_frame_bits() function-like macro. To this extent, do a full
refactoring of the length definitions.

In addition add the can_frame_bytes(). This function-like macro
replaces the existing macro:

- CAN_FRAME_OVERHEAD_SFF: can_frame_bytes(false, false, 0)
- CAN_FRAME_OVERHEAD_EFF: can_frame_bytes(false, true, 0)
- CANFD_FRAME_OVERHEAD_SFF: can_frame_bytes(true, false, 0)
- CANFD_FRAME_OVERHEAD_EFF: can_frame_bytes(true, true, 0)

Function-like macros were chosen over inline functions because they
can be used to initialize const struct fields.

The different maximum frame lengths (maximum data length, including
intermission) are as follow:

Frame type bits bytes
-------------------------------------------------------
Classic CAN SFF no bitstuffing 111 14
Classic CAN EFF no bitstuffing 131 17
Classic CAN SFF bitstuffing 135 17
Classic CAN EFF bitstuffing 160 20
CAN-FD SFF no bitstuffing 579 73
CAN-FD EFF no bitstuffing 598 75
CAN-FD SFF bitstuffing 712 89
CAN-FD EFF bitstuffing 736 92

The macro CAN_FRAME_LEN_MAX and CANFD_FRAME_LEN_MAX are kept as an
alias to, respectively, can_frame_bytes(false, true, CAN_MAX_DLEN) and
can_frame_bytes(true, true, CANFD_MAX_DLEN).

In addition to the above:

- Use ISO 11898-1:2015 definitions for the names of the CAN frame
fields.
- Include linux/bits.h for use of BITS_PER_BYTE.
- Include linux/math.h for use of mult_frac() and
DIV_ROUND_UP(). N.B: the use of DIV_ROUND_UP() is not new to this
patch, but the include was previously omitted.
- Add copyright 2023 for myself.

Suggested-by: Thomas Kopp <Thomas.Kopp@microchip.com>
Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Reviewed-by: Thomas Kopp <Thomas.Kopp@microchip.com>
Link: https://lore.kernel.org/all/20230611025728.450837-4-mailhol.vincent@wanadoo.fr
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Vincent Mailhol and committed by
Marc Kleine-Budde
80a2fbce 10711b11

+224 -109
+2 -13
drivers/net/can/dev/length.c
··· 78 78 else 79 79 len = cf->len; 80 80 81 - if (can_is_canfd_skb(skb)) { 82 - if (cf->can_id & CAN_EFF_FLAG) 83 - len += CANFD_FRAME_OVERHEAD_EFF; 84 - else 85 - len += CANFD_FRAME_OVERHEAD_SFF; 86 - } else { 87 - if (cf->can_id & CAN_EFF_FLAG) 88 - len += CAN_FRAME_OVERHEAD_EFF; 89 - else 90 - len += CAN_FRAME_OVERHEAD_SFF; 91 - } 92 - 93 - return len; 81 + return can_frame_bytes(can_is_canfd_skb(skb), cf->can_id & CAN_EFF_FLAG, 82 + false, len); 94 83 } 95 84 EXPORT_SYMBOL_GPL(can_skb_get_frame_len);
+222 -96
include/linux/can/length.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 2 /* Copyright (C) 2020 Oliver Hartkopp <socketcan@hartkopp.net> 3 3 * Copyright (C) 2020 Marc Kleine-Budde <kernel@pengutronix.de> 4 - * Copyright (C) 2020 Vincent Mailhol <mailhol.vincent@wanadoo.fr> 4 + * Copyright (C) 2020, 2023 Vincent Mailhol <mailhol.vincent@wanadoo.fr> 5 5 */ 6 6 7 7 #ifndef _CAN_LENGTH_H 8 8 #define _CAN_LENGTH_H 9 9 10 + #include <linux/bits.h> 10 11 #include <linux/can.h> 11 12 #include <linux/can/netlink.h> 13 + #include <linux/math.h> 12 14 13 15 /* 14 - * Size of a Classical CAN Standard Frame 16 + * Size of a Classical CAN Standard Frame header in bits 17 + * 18 + * Name of Field Bits 19 + * --------------------------------------------------------- 20 + * Start Of Frame (SOF) 1 21 + * Arbitration field: 22 + * base ID 11 23 + * Remote Transmission Request (RTR) 1 24 + * Control field: 25 + * IDentifier Extension bit (IDE) 1 26 + * FD Format indicator (FDF) 1 27 + * Data Length Code (DLC) 4 28 + * 29 + * including all fields preceding the data field, ignoring bitstuffing 30 + */ 31 + #define CAN_FRAME_HEADER_SFF_BITS 19 32 + 33 + /* 34 + * Size of a Classical CAN Extended Frame header in bits 35 + * 36 + * Name of Field Bits 37 + * --------------------------------------------------------- 38 + * Start Of Frame (SOF) 1 39 + * Arbitration field: 40 + * base ID 11 41 + * Substitute Remote Request (SRR) 1 42 + * IDentifier Extension bit (IDE) 1 43 + * ID extension 18 44 + * Remote Transmission Request (RTR) 1 45 + * Control field: 46 + * FD Format indicator (FDF) 1 47 + * Reserved bit (r0) 1 48 + * Data length code (DLC) 4 49 + * 50 + * including all fields preceding the data field, ignoring bitstuffing 51 + */ 52 + #define CAN_FRAME_HEADER_EFF_BITS 39 53 + 54 + /* 55 + * Size of a CAN-FD Standard Frame in bits 56 + * 57 + * Name of Field Bits 58 + * --------------------------------------------------------- 59 + * Start Of Frame (SOF) 1 60 + * Arbitration field: 61 + * base ID 11 62 + * Remote Request Substitution (RRS) 1 63 + * Control field: 64 + * IDentifier Extension bit (IDE) 1 65 + * FD Format indicator (FDF) 1 66 + * Reserved bit (res) 1 67 + * Bit Rate Switch (BRS) 1 68 + * Error Status Indicator (ESI) 1 69 + * Data length code (DLC) 4 70 + * 71 + * including all fields preceding the data field, ignoring bitstuffing 72 + */ 73 + #define CANFD_FRAME_HEADER_SFF_BITS 22 74 + 75 + /* 76 + * Size of a CAN-FD Extended Frame in bits 77 + * 78 + * Name of Field Bits 79 + * --------------------------------------------------------- 80 + * Start Of Frame (SOF) 1 81 + * Arbitration field: 82 + * base ID 11 83 + * Substitute Remote Request (SRR) 1 84 + * IDentifier Extension bit (IDE) 1 85 + * ID extension 18 86 + * Remote Request Substitution (RRS) 1 87 + * Control field: 88 + * FD Format indicator (FDF) 1 89 + * Reserved bit (res) 1 90 + * Bit Rate Switch (BRS) 1 91 + * Error Status Indicator (ESI) 1 92 + * Data length code (DLC) 4 93 + * 94 + * including all fields preceding the data field, ignoring bitstuffing 95 + */ 96 + #define CANFD_FRAME_HEADER_EFF_BITS 41 97 + 98 + /* 99 + * Size of a CAN CRC Field in bits 15 100 * 16 101 * Name of Field Bits 17 102 * --------------------------------------------------------- 18 - * Start-of-frame 1 19 - * Identifier 11 20 - * Remote transmission request (RTR) 1 21 - * Identifier extension bit (IDE) 1 22 - * Reserved bit (r0) 1 23 - * Data length code (DLC) 4 24 - * Data field 0...64 25 - * CRC 15 26 - * CRC delimiter 1 103 + * CRC sequence (CRC15) 15 104 + * CRC Delimiter 1 105 + * 106 + * ignoring bitstuffing 107 + */ 108 + #define CAN_FRAME_CRC_FIELD_BITS 16 109 + 110 + /* 111 + * Size of a CAN-FD CRC17 Field in bits (length: 0..16) 112 + * 113 + * Name of Field Bits 114 + * --------------------------------------------------------- 115 + * Stuff Count 4 116 + * CRC Sequence (CRC17) 17 117 + * CRC Delimiter 1 118 + * Fixed stuff bits 6 119 + */ 120 + #define CANFD_FRAME_CRC17_FIELD_BITS 28 121 + 122 + /* 123 + * Size of a CAN-FD CRC21 Field in bits (length: 20..64) 124 + * 125 + * Name of Field Bits 126 + * --------------------------------------------------------- 127 + * Stuff Count 4 128 + * CRC sequence (CRC21) 21 129 + * CRC Delimiter 1 130 + * Fixed stuff bits 7 131 + */ 132 + #define CANFD_FRAME_CRC21_FIELD_BITS 33 133 + 134 + /* 135 + * Size of a CAN(-FD) Frame footer in bits 136 + * 137 + * Name of Field Bits 138 + * --------------------------------------------------------- 27 139 * ACK slot 1 28 140 * ACK delimiter 1 29 - * End-of-frame (EOF) 7 30 - * Inter frame spacing 3 141 + * End Of Frame (EOF) 7 31 142 * 32 - * rounded up and ignoring bitstuffing 143 + * including all fields following the CRC field 33 144 */ 34 - #define CAN_FRAME_OVERHEAD_SFF DIV_ROUND_UP(47, 8) 145 + #define CAN_FRAME_FOOTER_BITS 9 35 146 36 147 /* 37 - * Size of a Classical CAN Extended Frame 38 - * 39 - * Name of Field Bits 40 - * --------------------------------------------------------- 41 - * Start-of-frame 1 42 - * Identifier A 11 43 - * Substitute remote request (SRR) 1 44 - * Identifier extension bit (IDE) 1 45 - * Identifier B 18 46 - * Remote transmission request (RTR) 1 47 - * Reserved bits (r1, r0) 2 48 - * Data length code (DLC) 4 49 - * Data field 0...64 50 - * CRC 15 51 - * CRC delimiter 1 52 - * ACK slot 1 53 - * ACK delimiter 1 54 - * End-of-frame (EOF) 7 55 - * Inter frame spacing 3 56 - * 57 - * rounded up and ignoring bitstuffing 148 + * First part of the Inter Frame Space 149 + * (a.k.a. IMF - intermission field) 58 150 */ 59 - #define CAN_FRAME_OVERHEAD_EFF DIV_ROUND_UP(67, 8) 151 + #define CAN_INTERMISSION_BITS 3 152 + 153 + /** 154 + * can_bitstuffing_len() - Calculate the maximum length with bitstuffing 155 + * @destuffed_len: length of a destuffed bit stream 156 + * 157 + * The worst bit stuffing case is a sequence in which dominant and 158 + * recessive bits alternate every four bits: 159 + * 160 + * Destuffed: 1 1111 0000 1111 0000 1111 161 + * Stuffed: 1 1111o 0000i 1111o 0000i 1111o 162 + * 163 + * Nomenclature 164 + * 165 + * - "0": dominant bit 166 + * - "o": dominant stuff bit 167 + * - "1": recessive bit 168 + * - "i": recessive stuff bit 169 + * 170 + * Aside from the first bit, one stuff bit is added every four bits. 171 + * 172 + * Return: length of the stuffed bit stream in the worst case scenario. 173 + */ 174 + #define can_bitstuffing_len(destuffed_len) \ 175 + (destuffed_len + (destuffed_len - 1) / 4) 176 + 177 + #define __can_bitstuffing_len(bitstuffing, destuffed_len) \ 178 + (bitstuffing ? can_bitstuffing_len(destuffed_len) : \ 179 + destuffed_len) 180 + 181 + #define __can_cc_frame_bits(is_eff, bitstuffing, \ 182 + intermission, data_len) \ 183 + ( \ 184 + __can_bitstuffing_len(bitstuffing, \ 185 + (is_eff ? CAN_FRAME_HEADER_EFF_BITS : \ 186 + CAN_FRAME_HEADER_SFF_BITS) + \ 187 + (data_len) * BITS_PER_BYTE + \ 188 + CAN_FRAME_CRC_FIELD_BITS) + \ 189 + CAN_FRAME_FOOTER_BITS + \ 190 + (intermission ? CAN_INTERMISSION_BITS : 0) \ 191 + ) 192 + 193 + #define __can_fd_frame_bits(is_eff, bitstuffing, \ 194 + intermission, data_len) \ 195 + ( \ 196 + __can_bitstuffing_len(bitstuffing, \ 197 + (is_eff ? CANFD_FRAME_HEADER_EFF_BITS : \ 198 + CANFD_FRAME_HEADER_SFF_BITS) + \ 199 + (data_len) * BITS_PER_BYTE) + \ 200 + ((data_len) <= 16 ? \ 201 + CANFD_FRAME_CRC17_FIELD_BITS : \ 202 + CANFD_FRAME_CRC21_FIELD_BITS) + \ 203 + CAN_FRAME_FOOTER_BITS + \ 204 + (intermission ? CAN_INTERMISSION_BITS : 0) \ 205 + ) 206 + 207 + /** 208 + * can_frame_bits() - Calculate the number of bits on the wire in a 209 + * CAN frame 210 + * @is_fd: true: CAN-FD frame; false: Classical CAN frame. 211 + * @is_eff: true: Extended frame; false: Standard frame. 212 + * @bitstuffing: true: calculate the bitstuffing worst case; false: 213 + * calculate the bitstuffing best case (no dynamic 214 + * bitstuffing). CAN-FD's fixed stuff bits are always included. 215 + * @intermission: if and only if true, include the inter frame space 216 + * assuming no bus idle (i.e. only the intermission). Strictly 217 + * speaking, the inter frame space is not part of the 218 + * frame. However, it is needed when calculating the delay 219 + * between the Start Of Frame of two consecutive frames. 220 + * @data_len: length of the data field in bytes. Correspond to 221 + * can(fd)_frame->len. Should be zero for remote frames. No 222 + * sanitization is done on @data_len and it shall have no side 223 + * effects. 224 + * 225 + * Return: the numbers of bits on the wire of a CAN frame. 226 + */ 227 + #define can_frame_bits(is_fd, is_eff, bitstuffing, \ 228 + intermission, data_len) \ 229 + ( \ 230 + is_fd ? __can_fd_frame_bits(is_eff, bitstuffing, \ 231 + intermission, data_len) : \ 232 + __can_cc_frame_bits(is_eff, bitstuffing, \ 233 + intermission, data_len) \ 234 + ) 60 235 61 236 /* 62 - * Size of a CAN-FD Standard Frame 63 - * 64 - * Name of Field Bits 65 - * --------------------------------------------------------- 66 - * Start-of-frame 1 67 - * Identifier 11 68 - * Remote Request Substitution (RRS) 1 69 - * Identifier extension bit (IDE) 1 70 - * Flexible data rate format (FDF) 1 71 - * Reserved bit (r0) 1 72 - * Bit Rate Switch (BRS) 1 73 - * Error Status Indicator (ESI) 1 74 - * Data length code (DLC) 4 75 - * Data field 0...512 76 - * Stuff Bit Count (SBC) 4 77 - * CRC 0...16: 17 20...64:21 78 - * CRC delimiter (CD) 1 79 - * Fixed Stuff bits (FSB) 0...16: 6 20...64:7 80 - * ACK slot (AS) 1 81 - * ACK delimiter (AD) 1 82 - * End-of-frame (EOF) 7 83 - * Inter frame spacing 3 84 - * 85 - * assuming CRC21, rounded up and ignoring dynamic bitstuffing 237 + * Number of bytes in a CAN frame 238 + * (rounded up, including intermission) 86 239 */ 87 - #define CANFD_FRAME_OVERHEAD_SFF DIV_ROUND_UP(67, 8) 88 - 89 - /* 90 - * Size of a CAN-FD Extended Frame 91 - * 92 - * Name of Field Bits 93 - * --------------------------------------------------------- 94 - * Start-of-frame 1 95 - * Identifier A 11 96 - * Substitute remote request (SRR) 1 97 - * Identifier extension bit (IDE) 1 98 - * Identifier B 18 99 - * Remote Request Substitution (RRS) 1 100 - * Flexible data rate format (FDF) 1 101 - * Reserved bit (r0) 1 102 - * Bit Rate Switch (BRS) 1 103 - * Error Status Indicator (ESI) 1 104 - * Data length code (DLC) 4 105 - * Data field 0...512 106 - * Stuff Bit Count (SBC) 4 107 - * CRC 0...16: 17 20...64:21 108 - * CRC delimiter (CD) 1 109 - * Fixed Stuff bits (FSB) 0...16: 6 20...64:7 110 - * ACK slot (AS) 1 111 - * ACK delimiter (AD) 1 112 - * End-of-frame (EOF) 7 113 - * Inter frame spacing 3 114 - * 115 - * assuming CRC21, rounded up and ignoring dynamic bitstuffing 116 - */ 117 - #define CANFD_FRAME_OVERHEAD_EFF DIV_ROUND_UP(86, 8) 240 + #define can_frame_bytes(is_fd, is_eff, bitstuffing, data_len) \ 241 + DIV_ROUND_UP(can_frame_bits(is_fd, is_eff, bitstuffing, \ 242 + true, data_len), \ 243 + BITS_PER_BYTE) 118 244 119 245 /* 120 246 * Maximum size of a Classical CAN frame 121 - * (rounded up and ignoring bitstuffing) 247 + * (rounded up, ignoring bitstuffing but including intermission) 122 248 */ 123 - #define CAN_FRAME_LEN_MAX (CAN_FRAME_OVERHEAD_EFF + CAN_MAX_DLEN) 249 + #define CAN_FRAME_LEN_MAX can_frame_bytes(false, true, false, CAN_MAX_DLEN) 124 250 125 251 /* 126 252 * Maximum size of a CAN-FD frame 127 - * (rounded up and ignoring bitstuffing) 253 + * (rounded up, ignoring dynamic bitstuffing but including intermission) 128 254 */ 129 - #define CANFD_FRAME_LEN_MAX (CANFD_FRAME_OVERHEAD_EFF + CANFD_MAX_DLEN) 255 + #define CANFD_FRAME_LEN_MAX can_frame_bytes(true, true, false, CANFD_MAX_DLEN) 130 256 131 257 /* 132 258 * can_cc_dlc2len(value) - convert a given data length code (dlc) of a