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

Configure Feed

Select the types of activity you want to include in your feed.

Merge patch series "can: netlink: add CAN XL support"

Marc Kleine-Budde <mkl@pengutronix.de> says:

Similarly to how CAN FD reuses the bittiming logic of Classical CAN, CAN XL
also reuses the entirety of CAN FD features, and, on top of that, adds new
features which are specific to CAN XL.

A so-called 'mixed-mode' is intended to have (XL-tolerant) CAN FD nodes and
CAN XL nodes on one CAN segment, where the FD-controllers can talk CC/FD
and the XL-controllers can talk CC/FD/XL. This mixed-mode utilizes the
known error-signalling (ES) for sending CC/FD/XL frames. For CAN FD and CAN
XL the tranceiver delay compensation (TDC) is supported to use common CAN
and CAN-SIG transceivers.

The CANXL-only mode disables the error-signalling in the CAN XL controller.
This mode does not allow CC/FD frames to be sent but additionally offers a
CAN XL transceiver mode switching (TMS) to send CAN XL frames with up to
20Mbit/s data rate. The TMS utilizes a PWM configuration which is added to
the netlink interface.

Configured with CAN_CTRLMODE_FD and CAN_CTRLMODE_XL this leads to:

FD=0 XL=0 CC-only mode (ES=1)
FD=1 XL=0 FD/CC mixed-mode (ES=1)
FD=1 XL=1 XL/FD/CC mixed-mode (ES=1)
FD=0 XL=1 XL-only mode (ES=0, TMS optional)

Patch #1 print defined ctrlmode strings capitalized to increase the
readability and to be in line with the 'ip' tool (iproute2).

Patch #2 is a small clean-up which makes can_calc_bittiming() use
NL_SET_ERR_MSG() instead of netdev_err().

Patch #3 adds a check in can_dev_dropped_skb() to drop CAN FD frames
when CAN FD is turned off.

Patch #4 adds CAN_CTRLMODE_RESTRICTED. Note that contrary to the other
CAN_CTRL_MODE_XL_* that are introduced in the later patches, this control
mode is not specific to CAN XL. The nuance is that because this restricted
mode was only added in ISO 11898-1:2024, it is made mandatory for CAN XL
devices but optional for other protocols. This is why this patch is added
as a preparation before introducing the core CAN XL logic.

Patch #5 adds all the CAN XL features which are inherited from CAN FD: the
nominal bittiming, the data bittiming and the TDC.

Patch #6 add a new CAN_CTRLMODE_XL_TMS control mode which is specific to
CAN XL to enable the transceiver mode switching (TMS) in XL-only mode.

Patch #7 adds a check in can_dev_dropped_skb() to drop CAN CC/FD frames
when the CAN XL controller is in CAN XL-only mode. The introduced
can_dev_in_xl_only_mode() function also determines the error-signalling
configuration for the CAN XL controllers.

Patch #8 to #11 add the PWM logic for the CAN XL TMS mode.

Patch #12 to #14 add different default sample-points for standard CAN and
CAN SIG transceivers (with TDC) and CAN XL transceivers using PWM in the
CAN XL TMS mode.

Patch #15 add a dummy_can driver for netlink testing and debugging.

Patch #16 check CAN frame type (CC/FD/XL) when writing those frames to the
CAN_RAW socket and reject them if it's not supported by the CAN interface.

Patch #17 increase the resolution when printing the bitrate error and
round-up the value to 0.01% in the case the resolution would still provide
values which would lead to 0.00%.

Link: https://patch.msgid.link/20251126-canxl-v8-0-e7e3eb74f889@pengutronix.de
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

+990 -88
+17
drivers/net/can/Kconfig
··· 124 124 125 125 If this driver is built as a module, it will be called can327. 126 126 127 + config CAN_DUMMY 128 + tristate "Dummy CAN" 129 + help 130 + A dummy CAN module supporting Classical CAN, CAN FD and CAN XL. It 131 + exposes bittiming values which can be configured through the netlink 132 + interface. 133 + 134 + The module will simply echo any frame sent to it. If debug messages 135 + are activated, it prints all the CAN bittiming information in the 136 + kernel log. Aside from that it does nothing. 137 + 138 + This is convenient for testing the CAN netlink interface. Most of the 139 + users will never need this. If unsure, say NO. 140 + 141 + To compile this driver as a module, choose M here: the module will be 142 + called dummy-can. 143 + 127 144 config CAN_FLEXCAN 128 145 tristate "Support for Freescale FLEXCAN based chips" 129 146 depends on OF || COLDFIRE || COMPILE_TEST
+1
drivers/net/can/Makefile
··· 21 21 obj-$(CONFIG_CAN_CC770) += cc770/ 22 22 obj-$(CONFIG_CAN_C_CAN) += c_can/ 23 23 obj-$(CONFIG_CAN_CTUCANFD) += ctucanfd/ 24 + obj-$(CONFIG_CAN_DUMMY) += dummy_can.o 24 25 obj-$(CONFIG_CAN_FLEXCAN) += flexcan/ 25 26 obj-$(CONFIG_CAN_GRCAN) += grcan.o 26 27 obj-$(CONFIG_CAN_IFI_CANFD) += ifi_canfd/
+63
drivers/net/can/dev/bittiming.c
··· 2 2 /* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix 3 3 * Copyright (C) 2006 Andrey Volkov, Varma Electronics 4 4 * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com> 5 + * Copyright (c) 2025 Vincent Mailhol <mailhol@kernel.org> 5 6 */ 6 7 7 8 #include <linux/can/dev.h> ··· 151 150 bitrate_const_cnt, extack); 152 151 153 152 return -EINVAL; 153 + } 154 + 155 + int can_validate_pwm_bittiming(const struct net_device *dev, 156 + const struct can_pwm *pwm, 157 + struct netlink_ext_ack *extack) 158 + { 159 + const struct can_priv *priv = netdev_priv(dev); 160 + u32 xl_bit_time_tqmin = can_bit_time_tqmin(&priv->xl.data_bittiming); 161 + u32 nom_bit_time_tqmin = can_bit_time_tqmin(&priv->bittiming); 162 + u32 pwms_ns = can_tqmin_to_ns(pwm->pwms, priv->clock.freq); 163 + u32 pwml_ns = can_tqmin_to_ns(pwm->pwml, priv->clock.freq); 164 + 165 + if (pwms_ns + pwml_ns > CAN_PWM_NS_MAX) { 166 + NL_SET_ERR_MSG_FMT(extack, 167 + "The PWM symbol duration: %u ns may not exceed %u ns", 168 + pwms_ns + pwml_ns, CAN_PWM_NS_MAX); 169 + return -EINVAL; 170 + } 171 + 172 + if (pwms_ns < CAN_PWM_DECODE_NS) { 173 + NL_SET_ERR_MSG_FMT(extack, 174 + "PWMS: %u ns shall be at least %u ns", 175 + pwms_ns, CAN_PWM_DECODE_NS); 176 + return -EINVAL; 177 + } 178 + 179 + if (pwm->pwms >= pwm->pwml) { 180 + NL_SET_ERR_MSG_FMT(extack, 181 + "PWMS: %u tqmin shall be smaller than PWML: %u tqmin", 182 + pwm->pwms, pwm->pwml); 183 + return -EINVAL; 184 + } 185 + 186 + if (pwml_ns - pwms_ns < 2 * CAN_PWM_DECODE_NS) { 187 + NL_SET_ERR_MSG_FMT(extack, 188 + "At least %u ns shall separate PWMS: %u ns from PMWL: %u ns", 189 + 2 * CAN_PWM_DECODE_NS, pwms_ns, pwml_ns); 190 + return -EINVAL; 191 + } 192 + 193 + if (xl_bit_time_tqmin % (pwm->pwms + pwm->pwml) != 0) { 194 + NL_SET_ERR_MSG_FMT(extack, 195 + "PWM duration: %u tqmin does not divide XL's bit time: %u tqmin", 196 + pwm->pwms + pwm->pwml, xl_bit_time_tqmin); 197 + return -EINVAL; 198 + } 199 + 200 + if (pwm->pwmo >= pwm->pwms + pwm->pwml) { 201 + NL_SET_ERR_MSG_FMT(extack, 202 + "PWMO: %u tqmin can not be greater than PWMS + PWML: %u tqmin", 203 + pwm->pwmo, pwm->pwms + pwm->pwml); 204 + return -EINVAL; 205 + } 206 + 207 + if (nom_bit_time_tqmin % (pwm->pwms + pwm->pwml) != pwm->pwmo) { 208 + NL_SET_ERR_MSG_FMT(extack, 209 + "Can not assemble nominal bit time: %u tqmin out of PWMS + PMWL and PWMO", 210 + nom_bit_time_tqmin); 211 + return -EINVAL; 212 + } 213 + 214 + return 0; 154 215 }
+88 -26
drivers/net/can/dev/calc_bittiming.c
··· 2 2 /* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix 3 3 * Copyright (C) 2006 Andrey Volkov, Varma Electronics 4 4 * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com> 5 + * Copyright (C) 2021-2025 Vincent Mailhol <mailhol@kernel.org> 5 6 */ 6 7 7 8 #include <linux/units.h> 8 9 #include <linux/can/dev.h> 9 10 10 11 #define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */ 12 + 13 + /* CiA recommended sample points for Non Return to Zero encoding. */ 14 + static int can_calc_sample_point_nrz(const struct can_bittiming *bt) 15 + { 16 + if (bt->bitrate > 800 * KILO /* BPS */) 17 + return 750; 18 + 19 + if (bt->bitrate > 500 * KILO /* BPS */) 20 + return 800; 21 + 22 + return 875; 23 + } 24 + 25 + /* Sample points for Pulse-Width Modulation encoding. */ 26 + static int can_calc_sample_point_pwm(const struct can_bittiming *bt) 27 + { 28 + if (bt->bitrate > 15 * MEGA /* BPS */) 29 + return 625; 30 + 31 + if (bt->bitrate > 9 * MEGA /* BPS */) 32 + return 600; 33 + 34 + if (bt->bitrate > 4 * MEGA /* BPS */) 35 + return 560; 36 + 37 + return 520; 38 + } 11 39 12 40 /* Bit-timing calculation derived from: 13 41 * ··· 51 23 */ 52 24 static int 53 25 can_update_sample_point(const struct can_bittiming_const *btc, 54 - const unsigned int sample_point_nominal, const unsigned int tseg, 26 + const unsigned int sample_point_reference, const unsigned int tseg, 55 27 unsigned int *tseg1_ptr, unsigned int *tseg2_ptr, 56 28 unsigned int *sample_point_error_ptr) 57 29 { ··· 62 34 63 35 for (i = 0; i <= 1; i++) { 64 36 tseg2 = tseg + CAN_SYNC_SEG - 65 - (sample_point_nominal * (tseg + CAN_SYNC_SEG)) / 37 + (sample_point_reference * (tseg + CAN_SYNC_SEG)) / 66 38 1000 - i; 67 39 tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max); 68 40 tseg1 = tseg - tseg2; ··· 73 45 74 46 sample_point = 1000 * (tseg + CAN_SYNC_SEG - tseg2) / 75 47 (tseg + CAN_SYNC_SEG); 76 - sample_point_error = abs(sample_point_nominal - sample_point); 48 + sample_point_error = abs(sample_point_reference - sample_point); 77 49 78 - if (sample_point <= sample_point_nominal && 50 + if (sample_point <= sample_point_reference && 79 51 sample_point_error < best_sample_point_error) { 80 52 best_sample_point = sample_point; 81 53 best_sample_point_error = sample_point_error; ··· 95 67 { 96 68 struct can_priv *priv = netdev_priv(dev); 97 69 unsigned int bitrate; /* current bitrate */ 98 - unsigned int bitrate_error; /* difference between current and nominal value */ 70 + unsigned int bitrate_error; /* diff between calculated and reference value */ 99 71 unsigned int best_bitrate_error = UINT_MAX; 100 - unsigned int sample_point_error; /* difference between current and nominal value */ 72 + unsigned int sample_point_error; /* diff between calculated and reference value */ 101 73 unsigned int best_sample_point_error = UINT_MAX; 102 - unsigned int sample_point_nominal; /* nominal sample point */ 74 + unsigned int sample_point_reference; /* reference sample point */ 103 75 unsigned int best_tseg = 0; /* current best value for tseg */ 104 76 unsigned int best_brp = 0; /* current best value for brp */ 105 77 unsigned int brp, tsegall, tseg, tseg1 = 0, tseg2 = 0; 106 78 u64 v64; 107 79 int err; 108 80 109 - /* Use CiA recommended sample points */ 110 - if (bt->sample_point) { 111 - sample_point_nominal = bt->sample_point; 112 - } else { 113 - if (bt->bitrate > 800 * KILO /* BPS */) 114 - sample_point_nominal = 750; 115 - else if (bt->bitrate > 500 * KILO /* BPS */) 116 - sample_point_nominal = 800; 117 - else 118 - sample_point_nominal = 875; 119 - } 81 + if (bt->sample_point) 82 + sample_point_reference = bt->sample_point; 83 + else if (btc == priv->xl.data_bittiming_const && 84 + (priv->ctrlmode & CAN_CTRLMODE_XL_TMS)) 85 + sample_point_reference = can_calc_sample_point_pwm(bt); 86 + else 87 + sample_point_reference = can_calc_sample_point_nrz(bt); 120 88 121 89 /* tseg even = round down, odd = round up */ 122 90 for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1; ··· 138 114 if (bitrate_error < best_bitrate_error) 139 115 best_sample_point_error = UINT_MAX; 140 116 141 - can_update_sample_point(btc, sample_point_nominal, tseg / 2, 117 + can_update_sample_point(btc, sample_point_reference, tseg / 2, 142 118 &tseg1, &tseg2, &sample_point_error); 143 119 if (sample_point_error >= best_sample_point_error) 144 120 continue; ··· 153 129 } 154 130 155 131 if (best_bitrate_error) { 156 - /* Error in one-tenth of a percent */ 157 - v64 = (u64)best_bitrate_error * 1000; 132 + /* Error in one-hundredth of a percent */ 133 + v64 = (u64)best_bitrate_error * 10000; 158 134 do_div(v64, bt->bitrate); 159 135 bitrate_error = (u32)v64; 136 + /* print at least 0.01% if the error is smaller */ 137 + bitrate_error = max(bitrate_error, 1U); 160 138 if (bitrate_error > CAN_CALC_MAX_ERROR) { 161 139 NL_SET_ERR_MSG_FMT(extack, 162 - "bitrate error: %u.%u%% too high", 163 - bitrate_error / 10, bitrate_error % 10); 140 + "bitrate error: %u.%02u%% too high", 141 + bitrate_error / 100, 142 + bitrate_error % 100); 164 143 return -EINVAL; 165 144 } 166 145 NL_SET_ERR_MSG_FMT(extack, 167 - "bitrate error: %u.%u%%", 168 - bitrate_error / 10, bitrate_error % 10); 146 + "bitrate error: %u.%02u%%", 147 + bitrate_error / 100, bitrate_error % 100); 169 148 } 170 149 171 150 /* real sample point */ 172 - bt->sample_point = can_update_sample_point(btc, sample_point_nominal, 151 + bt->sample_point = can_update_sample_point(btc, sample_point_reference, 173 152 best_tseg, &tseg1, &tseg2, 174 153 NULL); 175 154 ··· 224 197 tdc->tdco = min(sample_point_in_tc, tdc_const->tdco_max); 225 198 *ctrlmode |= tdc_auto; 226 199 } 200 + } 201 + 202 + int can_calc_pwm(struct net_device *dev, struct netlink_ext_ack *extack) 203 + { 204 + struct can_priv *priv = netdev_priv(dev); 205 + const struct can_pwm_const *pwm_const = priv->xl.pwm_const; 206 + struct can_pwm *pwm = &priv->xl.pwm; 207 + u32 xl_tqmin = can_bit_time_tqmin(&priv->xl.data_bittiming); 208 + u32 xl_ns = can_tqmin_to_ns(xl_tqmin, priv->clock.freq); 209 + u32 nom_tqmin = can_bit_time_tqmin(&priv->bittiming); 210 + int pwm_per_bit_max = xl_tqmin / (pwm_const->pwms_min + pwm_const->pwml_min); 211 + int pwm_per_bit; 212 + u32 pwm_tqmin; 213 + 214 + /* For 5 MB/s databitrate or greater, xl_ns < CAN_PWM_NS_MAX 215 + * giving us a pwm_per_bit of 1 and the loop immediately breaks 216 + */ 217 + for (pwm_per_bit = DIV_ROUND_UP(xl_ns, CAN_PWM_NS_MAX); 218 + pwm_per_bit <= pwm_per_bit_max; pwm_per_bit++) 219 + if (xl_tqmin % pwm_per_bit == 0) 220 + break; 221 + 222 + if (pwm_per_bit > pwm_per_bit_max) { 223 + NL_SET_ERR_MSG_FMT(extack, 224 + "Can not divide the XL data phase's bit time: %u tqmin into multiple PWM symbols", 225 + xl_tqmin); 226 + return -EINVAL; 227 + } 228 + 229 + pwm_tqmin = xl_tqmin / pwm_per_bit; 230 + pwm->pwms = DIV_ROUND_UP_POW2(pwm_tqmin, 4); 231 + pwm->pwml = pwm_tqmin - pwm->pwms; 232 + pwm->pwmo = nom_tqmin % pwm_tqmin; 233 + 234 + return 0; 227 235 }
+29 -13
drivers/net/can/dev/dev.c
··· 92 92 { 93 93 switch (ctrlmode & ~(ctrlmode - 1)) { 94 94 case 0: 95 - return "none"; 95 + return "(none)"; 96 96 case CAN_CTRLMODE_LOOPBACK: 97 - return "loopback"; 97 + return "LOOPBACK"; 98 98 case CAN_CTRLMODE_LISTENONLY: 99 - return "listen-only"; 99 + return "LISTEN-ONLY"; 100 100 case CAN_CTRLMODE_3_SAMPLES: 101 - return "triple-sampling"; 101 + return "TRIPLE-SAMPLING"; 102 102 case CAN_CTRLMODE_ONE_SHOT: 103 - return "one-shot"; 103 + return "ONE-SHOT"; 104 104 case CAN_CTRLMODE_BERR_REPORTING: 105 - return "berr-reporting"; 105 + return "BERR-REPORTING"; 106 106 case CAN_CTRLMODE_FD: 107 - return "fd"; 107 + return "FD"; 108 108 case CAN_CTRLMODE_PRESUME_ACK: 109 - return "presume-ack"; 109 + return "PRESUME-ACK"; 110 110 case CAN_CTRLMODE_FD_NON_ISO: 111 - return "fd-non-iso"; 111 + return "FD-NON-ISO"; 112 112 case CAN_CTRLMODE_CC_LEN8_DLC: 113 - return "cc-len8-dlc"; 113 + return "CC-LEN8-DLC"; 114 114 case CAN_CTRLMODE_TDC_AUTO: 115 - return "fd-tdc-auto"; 115 + return "TDC-AUTO"; 116 116 case CAN_CTRLMODE_TDC_MANUAL: 117 - return "fd-tdc-manual"; 117 + return "TDC-MANUAL"; 118 + case CAN_CTRLMODE_RESTRICTED: 119 + return "RESTRICTED"; 120 + case CAN_CTRLMODE_XL: 121 + return "XL"; 122 + case CAN_CTRLMODE_XL_TDC_AUTO: 123 + return "XL-TDC-AUTO"; 124 + case CAN_CTRLMODE_XL_TDC_MANUAL: 125 + return "XL-TDC-MANUAL"; 126 + case CAN_CTRLMODE_XL_TMS: 127 + return "TMS"; 118 128 default: 119 129 return "<unknown>"; 120 130 } ··· 358 348 { 359 349 struct can_priv *priv = netdev_priv(dev); 360 350 361 - if (priv->ctrlmode & CAN_CTRLMODE_FD) { 351 + if (priv->ctrlmode & CAN_CTRLMODE_XL) { 352 + if (can_is_canxl_dev_mtu(dev->mtu)) 353 + return; 354 + dev->mtu = CANXL_MTU; 355 + dev->min_mtu = CANXL_MIN_MTU; 356 + dev->max_mtu = CANXL_MAX_MTU; 357 + } else if (priv->ctrlmode & CAN_CTRLMODE_FD) { 362 358 dev->mtu = CANFD_MTU; 363 359 dev->min_mtu = CANFD_MTU; 364 360 dev->max_mtu = CANFD_MTU;
+300 -19
drivers/net/can/dev/netlink.c
··· 2 2 /* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix 3 3 * Copyright (C) 2006 Andrey Volkov, Varma Electronics 4 4 * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com> 5 - * Copyright (C) 2021 Vincent Mailhol <mailhol.vincent@wanadoo.fr> 5 + * Copyright (C) 2021-2025 Vincent Mailhol <mailhol@kernel.org> 6 6 */ 7 7 8 8 #include <linux/can/dev.h> ··· 22 22 [IFLA_CAN_TERMINATION] = { .type = NLA_U16 }, 23 23 [IFLA_CAN_TDC] = { .type = NLA_NESTED }, 24 24 [IFLA_CAN_CTRLMODE_EXT] = { .type = NLA_NESTED }, 25 + [IFLA_CAN_XL_DATA_BITTIMING] = { .len = sizeof(struct can_bittiming) }, 26 + [IFLA_CAN_XL_DATA_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) }, 27 + [IFLA_CAN_XL_TDC] = { .type = NLA_NESTED }, 28 + [IFLA_CAN_XL_PWM] = { .type = NLA_NESTED }, 25 29 }; 26 30 27 31 static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = { ··· 38 34 [IFLA_CAN_TDC_TDCV] = { .type = NLA_U32 }, 39 35 [IFLA_CAN_TDC_TDCO] = { .type = NLA_U32 }, 40 36 [IFLA_CAN_TDC_TDCF] = { .type = NLA_U32 }, 37 + }; 38 + 39 + static const struct nla_policy can_pwm_policy[IFLA_CAN_PWM_MAX + 1] = { 40 + [IFLA_CAN_PWM_PWMS_MIN] = { .type = NLA_U32 }, 41 + [IFLA_CAN_PWM_PWMS_MAX] = { .type = NLA_U32 }, 42 + [IFLA_CAN_PWM_PWML_MIN] = { .type = NLA_U32 }, 43 + [IFLA_CAN_PWM_PWML_MAX] = { .type = NLA_U32 }, 44 + [IFLA_CAN_PWM_PWMO_MIN] = { .type = NLA_U32 }, 45 + [IFLA_CAN_PWM_PWMO_MAX] = { .type = NLA_U32 }, 46 + [IFLA_CAN_PWM_PWMS] = { .type = NLA_U32 }, 47 + [IFLA_CAN_PWM_PWML] = { .type = NLA_U32 }, 48 + [IFLA_CAN_PWM_PWMO] = { .type = NLA_U32 }, 41 49 }; 42 50 43 51 static int can_validate_bittiming(struct nlattr *data[], ··· 86 70 return -EOPNOTSUPP; 87 71 } 88 72 89 - /* If one of the CAN_CTRLMODE_TDC_* flag is set then TDC 73 + /* If one of the CAN_CTRLMODE_{,XL}_TDC_* flags is set then TDC 90 74 * must be set and vice-versa 91 75 */ 92 76 if ((tdc_auto || tdc_manual) && !data_tdc) { ··· 98 82 return -EOPNOTSUPP; 99 83 } 100 84 101 - /* If providing TDC parameters, at least TDCO is needed. TDCV 102 - * is needed if and only if CAN_CTRLMODE_TDC_MANUAL is set 85 + /* If providing TDC parameters, at least TDCO is needed. TDCV is 86 + * needed if and only if CAN_CTRLMODE_{,XL}_TDC_MANUAL is set 103 87 */ 104 88 if (data_tdc) { 105 89 struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1]; ··· 132 116 return 0; 133 117 } 134 118 119 + static int can_validate_pwm(struct nlattr *data[], 120 + struct netlink_ext_ack *extack, u32 flags) 121 + { 122 + struct nlattr *tb_pwm[IFLA_CAN_PWM_MAX + 1]; 123 + int err; 124 + 125 + if (!data[IFLA_CAN_XL_PWM]) 126 + return 0; 127 + 128 + if (!(flags & CAN_CTRLMODE_XL_TMS)) { 129 + NL_SET_ERR_MSG(extack, "PWM requires TMS"); 130 + return -EOPNOTSUPP; 131 + } 132 + 133 + err = nla_parse_nested(tb_pwm, IFLA_CAN_PWM_MAX, data[IFLA_CAN_XL_PWM], 134 + can_pwm_policy, extack); 135 + if (err) 136 + return err; 137 + 138 + if (!tb_pwm[IFLA_CAN_PWM_PWMS] != !tb_pwm[IFLA_CAN_PWM_PWML]) { 139 + NL_SET_ERR_MSG(extack, 140 + "Provide either both PWMS and PWML, or none for automatic calculation"); 141 + return -EOPNOTSUPP; 142 + } 143 + 144 + if (tb_pwm[IFLA_CAN_PWM_PWMO] && 145 + (!tb_pwm[IFLA_CAN_PWM_PWMS] || !tb_pwm[IFLA_CAN_PWM_PWML])) { 146 + NL_SET_ERR_MSG(extack, "PWMO requires both PWMS and PWML"); 147 + return -EOPNOTSUPP; 148 + } 149 + 150 + return 0; 151 + } 152 + 135 153 static int can_validate_databittiming(struct nlattr *data[], 136 154 struct netlink_ext_ack *extack, 137 155 int ifla_can_data_bittiming, u32 flags) ··· 176 126 bool is_on; 177 127 int err; 178 128 179 - /* Make sure that valid CAN FD configurations always consist of 129 + /* Make sure that valid CAN FD/XL configurations always consist of 180 130 * - nominal/arbitration bittiming 181 131 * - data bittiming 182 - * - control mode with CAN_CTRLMODE_FD set 132 + * - control mode with CAN_CTRLMODE_{FD,XL} set 183 133 * - TDC parameters are coherent (details in can_validate_tdc()) 184 134 */ 185 135 ··· 189 139 is_on = flags & CAN_CTRLMODE_FD; 190 140 type = "FD"; 191 141 } else { 192 - return -EOPNOTSUPP; /* Place holder for CAN XL */ 142 + data_tdc = data[IFLA_CAN_XL_TDC]; 143 + tdc_flags = flags & CAN_CTRLMODE_XL_TDC_MASK; 144 + is_on = flags & CAN_CTRLMODE_XL; 145 + type = "XL"; 193 146 } 194 147 195 148 if (is_on) { ··· 228 175 return 0; 229 176 } 230 177 178 + static int can_validate_xl_flags(struct netlink_ext_ack *extack, 179 + u32 masked_flags, u32 mask) 180 + { 181 + if (masked_flags & CAN_CTRLMODE_XL) { 182 + if (masked_flags & CAN_CTRLMODE_XL_TMS) { 183 + const u32 tms_conflicts_mask = CAN_CTRLMODE_FD | 184 + CAN_CTRLMODE_XL_TDC_MASK; 185 + u32 tms_conflicts = masked_flags & tms_conflicts_mask; 186 + 187 + if (tms_conflicts) { 188 + NL_SET_ERR_MSG_FMT(extack, 189 + "TMS and %s are mutually exclusive", 190 + can_get_ctrlmode_str(tms_conflicts)); 191 + return -EOPNOTSUPP; 192 + } 193 + } 194 + } else { 195 + if (mask & CAN_CTRLMODE_XL_TMS) { 196 + NL_SET_ERR_MSG(extack, "TMS requires CAN XL"); 197 + return -EOPNOTSUPP; 198 + } 199 + } 200 + 201 + return 0; 202 + } 203 + 231 204 static int can_validate(struct nlattr *tb[], struct nlattr *data[], 232 205 struct netlink_ext_ack *extack) 233 206 { ··· 267 188 struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]); 268 189 269 190 flags = cm->flags & cm->mask; 191 + 192 + if ((flags & CAN_CTRLMODE_LISTENONLY) && 193 + (flags & CAN_CTRLMODE_RESTRICTED)) { 194 + NL_SET_ERR_MSG(extack, 195 + "LISTEN-ONLY and RESTRICTED modes are mutually exclusive"); 196 + return -EOPNOTSUPP; 197 + } 198 + 199 + err = can_validate_xl_flags(extack, flags, cm->mask); 200 + if (err) 201 + return err; 270 202 } 271 203 272 204 err = can_validate_bittiming(data, extack, IFLA_CAN_BITTIMING); ··· 286 196 287 197 err = can_validate_databittiming(data, extack, 288 198 IFLA_CAN_DATA_BITTIMING, flags); 199 + if (err) 200 + return err; 201 + 202 + err = can_validate_databittiming(data, extack, 203 + IFLA_CAN_XL_DATA_BITTIMING, flags); 204 + if (err) 205 + return err; 206 + 207 + err = can_validate_pwm(data, extack, flags); 289 208 if (err) 290 209 return err; 291 210 ··· 307 208 { 308 209 struct can_priv *priv = netdev_priv(dev); 309 210 struct can_ctrlmode *cm; 310 - u32 ctrlstatic, maskedflags, notsupp, ctrlstatic_missing; 211 + u32 ctrlstatic, maskedflags, deactivated, notsupp, ctrlstatic_missing; 311 212 312 213 if (!data[IFLA_CAN_CTRLMODE]) 313 214 return 0; ··· 319 220 cm = nla_data(data[IFLA_CAN_CTRLMODE]); 320 221 ctrlstatic = can_get_static_ctrlmode(priv); 321 222 maskedflags = cm->flags & cm->mask; 223 + deactivated = ~cm->flags & cm->mask; 322 224 notsupp = maskedflags & ~(priv->ctrlmode_supported | ctrlstatic); 323 225 ctrlstatic_missing = (maskedflags & ctrlstatic) ^ ctrlstatic; 324 226 ··· 341 241 return -EOPNOTSUPP; 342 242 } 343 243 244 + /* If FD was active and is not turned off, check for XL conflicts */ 245 + if (priv->ctrlmode & CAN_CTRLMODE_FD & ~deactivated) { 246 + if (maskedflags & CAN_CTRLMODE_XL_TMS) { 247 + NL_SET_ERR_MSG(extack, 248 + "TMS can not be activated while CAN FD is on"); 249 + return -EOPNOTSUPP; 250 + } 251 + } 252 + 344 253 /* If a top dependency flag is provided, reset all its dependencies */ 345 254 if (cm->mask & CAN_CTRLMODE_FD) 346 255 priv->ctrlmode &= ~CAN_CTRLMODE_FD_TDC_MASK; 256 + if (cm->mask & CAN_CTRLMODE_XL) 257 + priv->ctrlmode &= ~(CAN_CTRLMODE_XL_TDC_MASK | 258 + CAN_CTRLMODE_XL_TMS); 347 259 348 260 /* clear bits to be modified and copy the flag values */ 349 261 priv->ctrlmode &= ~cm->mask; 350 262 priv->ctrlmode |= maskedflags; 351 263 352 - /* Wipe potential leftovers from previous CAN FD config */ 264 + /* Wipe potential leftovers from previous CAN FD/XL config */ 353 265 if (!(priv->ctrlmode & CAN_CTRLMODE_FD)) { 354 266 memset(&priv->fd.data_bittiming, 0, 355 267 sizeof(priv->fd.data_bittiming)); 356 268 priv->ctrlmode &= ~CAN_CTRLMODE_FD_TDC_MASK; 357 269 memset(&priv->fd.tdc, 0, sizeof(priv->fd.tdc)); 270 + } 271 + if (!(priv->ctrlmode & CAN_CTRLMODE_XL)) { 272 + memset(&priv->xl.data_bittiming, 0, 273 + sizeof(priv->fd.data_bittiming)); 274 + priv->ctrlmode &= ~CAN_CTRLMODE_XL_TDC_MASK; 275 + memset(&priv->xl.tdc, 0, sizeof(priv->xl.tdc)); 276 + memset(&priv->xl.pwm, 0, sizeof(priv->xl.pwm)); 358 277 } 359 278 360 279 can_set_default_mtu(dev); ··· 449 330 dbt_params = &priv->fd; 450 331 tdc_mask = CAN_CTRLMODE_FD_TDC_MASK; 451 332 } else { 452 - return -EOPNOTSUPP; /* Place holder for CAN XL */ 333 + data_bittiming = data[IFLA_CAN_XL_DATA_BITTIMING]; 334 + data_tdc = data[IFLA_CAN_XL_TDC]; 335 + dbt_params = &priv->xl; 336 + tdc_mask = CAN_CTRLMODE_XL_TDC_MASK; 453 337 } 454 338 455 339 if (!data_bittiming) ··· 488 366 if (data[IFLA_CAN_CTRLMODE]) { 489 367 struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]); 490 368 491 - need_tdc_calc = !(cm->mask & tdc_mask); 369 + if (fd || !(priv->ctrlmode & CAN_CTRLMODE_XL_TMS)) 370 + need_tdc_calc = !(cm->mask & tdc_mask); 492 371 } 493 372 if (data_tdc) { 494 373 /* TDC parameters are provided: use them */ ··· 504 381 */ 505 382 can_calc_tdco(&dbt_params->tdc, dbt_params->tdc_const, &dbt, 506 383 tdc_mask, &priv->ctrlmode, priv->ctrlmode_supported); 507 - } /* else: both CAN_CTRLMODE_TDC_{AUTO,MANUAL} are explicitly 384 + } /* else: both CAN_CTRLMODE_{,XL}_TDC_{AUTO,MANUAL} are explicitly 508 385 * turned off. TDC is disabled: do nothing 509 386 */ 510 387 ··· 517 394 return err; 518 395 } 519 396 397 + return 0; 398 + } 399 + 400 + static int can_pwm_changelink(struct net_device *dev, 401 + const struct nlattr *pwm_nla, 402 + struct netlink_ext_ack *extack) 403 + { 404 + struct can_priv *priv = netdev_priv(dev); 405 + const struct can_pwm_const *pwm_const = priv->xl.pwm_const; 406 + struct nlattr *tb_pwm[IFLA_CAN_PWM_MAX + 1]; 407 + struct can_pwm pwm = { 0 }; 408 + int err; 409 + 410 + if (!(priv->ctrlmode & CAN_CTRLMODE_XL_TMS)) 411 + return 0; 412 + 413 + if (!pwm_const) { 414 + NL_SET_ERR_MSG(extack, "The device does not support PWM"); 415 + return -EOPNOTSUPP; 416 + } 417 + 418 + if (!pwm_nla) 419 + return can_calc_pwm(dev, extack); 420 + 421 + err = nla_parse_nested(tb_pwm, IFLA_CAN_PWM_MAX, pwm_nla, 422 + can_pwm_policy, extack); 423 + if (err) 424 + return err; 425 + 426 + if (tb_pwm[IFLA_CAN_PWM_PWMS]) { 427 + pwm.pwms = nla_get_u32(tb_pwm[IFLA_CAN_PWM_PWMS]); 428 + if (pwm.pwms < pwm_const->pwms_min || 429 + pwm.pwms > pwm_const->pwms_max) { 430 + NL_SET_ERR_MSG_FMT(extack, 431 + "PWMS: %u tqmin is out of range: %u...%u", 432 + pwm.pwms, pwm_const->pwms_min, 433 + pwm_const->pwms_max); 434 + return -EINVAL; 435 + } 436 + } 437 + 438 + if (tb_pwm[IFLA_CAN_PWM_PWML]) { 439 + pwm.pwml = nla_get_u32(tb_pwm[IFLA_CAN_PWM_PWML]); 440 + if (pwm.pwml < pwm_const->pwml_min || 441 + pwm.pwml > pwm_const->pwml_max) { 442 + NL_SET_ERR_MSG_FMT(extack, 443 + "PWML: %u tqmin is out of range: %u...%u", 444 + pwm.pwml, pwm_const->pwml_min, 445 + pwm_const->pwml_max); 446 + return -EINVAL; 447 + } 448 + } 449 + 450 + if (tb_pwm[IFLA_CAN_PWM_PWMO]) { 451 + pwm.pwmo = nla_get_u32(tb_pwm[IFLA_CAN_PWM_PWMO]); 452 + if (pwm.pwmo < pwm_const->pwmo_min || 453 + pwm.pwmo > pwm_const->pwmo_max) { 454 + NL_SET_ERR_MSG_FMT(extack, 455 + "PWMO: %u tqmin is out of range: %u...%u", 456 + pwm.pwmo, pwm_const->pwmo_min, 457 + pwm_const->pwmo_max); 458 + return -EINVAL; 459 + } 460 + } 461 + 462 + err = can_validate_pwm_bittiming(dev, &pwm, extack); 463 + if (err) 464 + return err; 465 + 466 + priv->xl.pwm = pwm; 520 467 return 0; 521 468 } 522 469 ··· 679 486 if (err) 680 487 return err; 681 488 489 + /* CAN XL */ 490 + err = can_dbt_changelink(dev, data, false, extack); 491 + if (err) 492 + return err; 493 + err = can_pwm_changelink(dev, data[IFLA_CAN_XL_PWM], extack); 494 + if (err) 495 + return err; 496 + 682 497 if (data[IFLA_CAN_TERMINATION]) { 683 498 const u16 termval = nla_get_u16(data[IFLA_CAN_TERMINATION]); 684 499 const unsigned int num_term = priv->termination_const_cnt; ··· 754 553 { 755 554 size_t size = 0; 756 555 757 - if (dbt_params->data_bittiming.bitrate) /* IFLA_CAN_DATA_BITTIMING */ 556 + if (dbt_params->data_bittiming.bitrate) /* IFLA_CAN_{,XL}_DATA_BITTIMING */ 758 557 size += nla_total_size(sizeof(dbt_params->data_bittiming)); 759 - if (dbt_params->data_bittiming_const) /* IFLA_CAN_DATA_BITTIMING_CONST */ 558 + if (dbt_params->data_bittiming_const) /* IFLA_CAN_{,XL}_DATA_BITTIMING_CONST */ 760 559 size += nla_total_size(sizeof(*dbt_params->data_bittiming_const)); 761 - if (dbt_params->data_bitrate_const) /* IFLA_CAN_DATA_BITRATE_CONST */ 560 + if (dbt_params->data_bitrate_const) /* IFLA_CAN_{,XL}_DATA_BITRATE_CONST */ 762 561 size += nla_total_size(sizeof(*dbt_params->data_bitrate_const) * 763 562 dbt_params->data_bitrate_const_cnt); 764 - size += can_tdc_get_size(dbt_params, tdc_flags);/* IFLA_CAN_TDC */ 563 + size += can_tdc_get_size(dbt_params, tdc_flags);/* IFLA_CAN_{,XL}_TDC */ 765 564 766 565 return size; 767 566 } ··· 770 569 { 771 570 return nla_total_size(0) + /* nest IFLA_CAN_CTRLMODE_EXT */ 772 571 nla_total_size(sizeof(u32)); /* IFLA_CAN_CTRLMODE_SUPPORTED */ 572 + } 573 + 574 + static size_t can_pwm_get_size(const struct can_pwm_const *pwm_const, 575 + bool pwm_on) 576 + { 577 + size_t size; 578 + 579 + if (!pwm_const || !pwm_on) 580 + return 0; 581 + 582 + size = nla_total_size(0); /* nest IFLA_CAN_PWM */ 583 + 584 + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMS_MIN */ 585 + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMS_MAX */ 586 + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWML_MIN */ 587 + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWML_MAX */ 588 + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMO_MIN */ 589 + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMO_MAX */ 590 + 591 + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMS */ 592 + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWML */ 593 + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMO */ 594 + 595 + return size; 773 596 } 774 597 775 598 static size_t can_get_size(const struct net_device *dev) ··· 824 599 825 600 size += can_data_bittiming_get_size(&priv->fd, 826 601 priv->ctrlmode & CAN_CTRLMODE_FD_TDC_MASK); 602 + 603 + size += can_data_bittiming_get_size(&priv->xl, 604 + priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MASK); 605 + size += can_pwm_get_size(priv->xl.pwm_const, /* IFLA_CAN_XL_PWM */ 606 + priv->ctrlmode & CAN_CTRLMODE_XL_TMS); 827 607 828 608 return size; 829 609 } ··· 874 644 tdc_is_enabled = can_fd_tdc_is_enabled(priv); 875 645 tdc_manual = priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL; 876 646 } else { 877 - return -EOPNOTSUPP; /* Place holder for CAN XL */ 647 + dbt_params = &priv->xl; 648 + tdc_is_enabled = can_xl_tdc_is_enabled(priv); 649 + tdc_manual = priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MANUAL; 878 650 } 879 651 tdc_const = dbt_params->tdc_const; 880 652 tdc = &dbt_params->tdc; ··· 916 684 goto err_cancel; 917 685 if (tdc_const->tdcf_max && 918 686 nla_put_u32(skb, IFLA_CAN_TDC_TDCF, tdc->tdcf)) 687 + goto err_cancel; 688 + } 689 + 690 + nla_nest_end(skb, nest); 691 + return 0; 692 + 693 + err_cancel: 694 + nla_nest_cancel(skb, nest); 695 + return -EMSGSIZE; 696 + } 697 + 698 + static int can_pwm_fill_info(struct sk_buff *skb, const struct can_priv *priv) 699 + { 700 + const struct can_pwm_const *pwm_const = priv->xl.pwm_const; 701 + const struct can_pwm *pwm = &priv->xl.pwm; 702 + struct nlattr *nest; 703 + 704 + if (!pwm_const) 705 + return 0; 706 + 707 + nest = nla_nest_start(skb, IFLA_CAN_XL_PWM); 708 + if (!nest) 709 + return -EMSGSIZE; 710 + 711 + if (nla_put_u32(skb, IFLA_CAN_PWM_PWMS_MIN, pwm_const->pwms_min) || 712 + nla_put_u32(skb, IFLA_CAN_PWM_PWMS_MAX, pwm_const->pwms_max) || 713 + nla_put_u32(skb, IFLA_CAN_PWM_PWML_MIN, pwm_const->pwml_min) || 714 + nla_put_u32(skb, IFLA_CAN_PWM_PWML_MAX, pwm_const->pwml_max) || 715 + nla_put_u32(skb, IFLA_CAN_PWM_PWMO_MIN, pwm_const->pwmo_min) || 716 + nla_put_u32(skb, IFLA_CAN_PWM_PWMO_MAX, pwm_const->pwmo_max)) 717 + goto err_cancel; 718 + 719 + if (priv->ctrlmode & CAN_CTRLMODE_XL_TMS) { 720 + if (nla_put_u32(skb, IFLA_CAN_PWM_PWMS, pwm->pwms) || 721 + nla_put_u32(skb, IFLA_CAN_PWM_PWML, pwm->pwml) || 722 + nla_put_u32(skb, IFLA_CAN_PWM_PWMO, pwm->pwmo)) 919 723 goto err_cancel; 920 724 } 921 725 ··· 1034 766 1035 767 can_tdc_fill_info(skb, dev, IFLA_CAN_TDC) || 1036 768 1037 - can_ctrlmode_ext_fill_info(skb, priv) 1038 - ) 769 + can_ctrlmode_ext_fill_info(skb, priv) || 1039 770 771 + can_bittiming_fill_info(skb, IFLA_CAN_XL_DATA_BITTIMING, 772 + &priv->xl.data_bittiming) || 773 + 774 + can_bittiming_const_fill_info(skb, IFLA_CAN_XL_DATA_BITTIMING_CONST, 775 + priv->xl.data_bittiming_const) || 776 + 777 + can_bitrate_const_fill_info(skb, IFLA_CAN_XL_DATA_BITRATE_CONST, 778 + priv->xl.data_bitrate_const, 779 + priv->xl.data_bitrate_const_cnt) || 780 + 781 + can_tdc_fill_info(skb, dev, IFLA_CAN_XL_TDC) || 782 + 783 + can_pwm_fill_info(skb, priv) 784 + ) 1040 785 return -EMSGSIZE; 1041 786 1042 787 return 0;
+285
drivers/net/can/dummy_can.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + /* Copyright (c) 2025 Vincent Mailhol <mailhol@kernel.org> */ 4 + 5 + #include <linux/array_size.h> 6 + #include <linux/errno.h> 7 + #include <linux/init.h> 8 + #include <linux/kernel.h> 9 + #include <linux/module.h> 10 + #include <linux/netdevice.h> 11 + #include <linux/units.h> 12 + #include <linux/string_choices.h> 13 + 14 + #include <linux/can.h> 15 + #include <linux/can/bittiming.h> 16 + #include <linux/can/dev.h> 17 + #include <linux/can/skb.h> 18 + 19 + struct dummy_can { 20 + struct can_priv can; 21 + struct net_device *dev; 22 + }; 23 + 24 + static struct dummy_can *dummy_can; 25 + 26 + static const struct can_bittiming_const dummy_can_bittiming_const = { 27 + .name = "dummy_can CC", 28 + .tseg1_min = 2, 29 + .tseg1_max = 256, 30 + .tseg2_min = 2, 31 + .tseg2_max = 128, 32 + .sjw_max = 128, 33 + .brp_min = 1, 34 + .brp_max = 512, 35 + .brp_inc = 1 36 + }; 37 + 38 + static const struct can_bittiming_const dummy_can_fd_databittiming_const = { 39 + .name = "dummy_can FD", 40 + .tseg1_min = 2, 41 + .tseg1_max = 256, 42 + .tseg2_min = 2, 43 + .tseg2_max = 128, 44 + .sjw_max = 128, 45 + .brp_min = 1, 46 + .brp_max = 512, 47 + .brp_inc = 1 48 + }; 49 + 50 + static const struct can_tdc_const dummy_can_fd_tdc_const = { 51 + .tdcv_min = 0, 52 + .tdcv_max = 0, /* Manual mode not supported. */ 53 + .tdco_min = 0, 54 + .tdco_max = 127, 55 + .tdcf_min = 0, 56 + .tdcf_max = 127 57 + }; 58 + 59 + static const struct can_bittiming_const dummy_can_xl_databittiming_const = { 60 + .name = "dummy_can XL", 61 + .tseg1_min = 2, 62 + .tseg1_max = 256, 63 + .tseg2_min = 2, 64 + .tseg2_max = 128, 65 + .sjw_max = 128, 66 + .brp_min = 1, 67 + .brp_max = 512, 68 + .brp_inc = 1 69 + }; 70 + 71 + static const struct can_tdc_const dummy_can_xl_tdc_const = { 72 + .tdcv_min = 0, 73 + .tdcv_max = 0, /* Manual mode not supported. */ 74 + .tdco_min = 0, 75 + .tdco_max = 127, 76 + .tdcf_min = 0, 77 + .tdcf_max = 127 78 + }; 79 + 80 + static const struct can_pwm_const dummy_can_pwm_const = { 81 + .pwms_min = 1, 82 + .pwms_max = 8, 83 + .pwml_min = 2, 84 + .pwml_max = 24, 85 + .pwmo_min = 0, 86 + .pwmo_max = 16, 87 + }; 88 + 89 + static void dummy_can_print_bittiming(struct net_device *dev, 90 + struct can_bittiming *bt) 91 + { 92 + netdev_dbg(dev, "\tbitrate: %u\n", bt->bitrate); 93 + netdev_dbg(dev, "\tsample_point: %u\n", bt->sample_point); 94 + netdev_dbg(dev, "\ttq: %u\n", bt->tq); 95 + netdev_dbg(dev, "\tprop_seg: %u\n", bt->prop_seg); 96 + netdev_dbg(dev, "\tphase_seg1: %u\n", bt->phase_seg1); 97 + netdev_dbg(dev, "\tphase_seg2: %u\n", bt->phase_seg2); 98 + netdev_dbg(dev, "\tsjw: %u\n", bt->sjw); 99 + netdev_dbg(dev, "\tbrp: %u\n", bt->brp); 100 + } 101 + 102 + static void dummy_can_print_tdc(struct net_device *dev, struct can_tdc *tdc) 103 + { 104 + netdev_dbg(dev, "\t\ttdcv: %u\n", tdc->tdcv); 105 + netdev_dbg(dev, "\t\ttdco: %u\n", tdc->tdco); 106 + netdev_dbg(dev, "\t\ttdcf: %u\n", tdc->tdcf); 107 + } 108 + 109 + static void dummy_can_print_pwm(struct net_device *dev, struct can_pwm *pwm, 110 + struct can_bittiming *dbt) 111 + { 112 + netdev_dbg(dev, "\t\tpwms: %u\n", pwm->pwms); 113 + netdev_dbg(dev, "\t\tpwml: %u\n", pwm->pwml); 114 + netdev_dbg(dev, "\t\tpwmo: %u\n", pwm->pwmo); 115 + } 116 + 117 + static void dummy_can_print_ctrlmode(struct net_device *dev) 118 + { 119 + struct dummy_can *priv = netdev_priv(dev); 120 + struct can_priv *can_priv = &priv->can; 121 + unsigned long supported = can_priv->ctrlmode_supported; 122 + u32 enabled = can_priv->ctrlmode; 123 + 124 + netdev_dbg(dev, "Control modes:\n"); 125 + netdev_dbg(dev, "\tsupported: 0x%08x\n", (u32)supported); 126 + netdev_dbg(dev, "\tenabled: 0x%08x\n", enabled); 127 + 128 + if (supported) { 129 + int idx; 130 + 131 + netdev_dbg(dev, "\tlist:"); 132 + for_each_set_bit(idx, &supported, BITS_PER_TYPE(u32)) 133 + netdev_dbg(dev, "\t\t%s: %s\n", 134 + can_get_ctrlmode_str(BIT(idx)), 135 + enabled & BIT(idx) ? "on" : "off"); 136 + } 137 + } 138 + 139 + static void dummy_can_print_bittiming_info(struct net_device *dev) 140 + { 141 + struct dummy_can *priv = netdev_priv(dev); 142 + struct can_priv *can_priv = &priv->can; 143 + 144 + netdev_dbg(dev, "Clock frequency: %u\n", can_priv->clock.freq); 145 + netdev_dbg(dev, "Maximum bitrate: %u\n", can_priv->bitrate_max); 146 + netdev_dbg(dev, "MTU: %u\n", dev->mtu); 147 + netdev_dbg(dev, "\n"); 148 + 149 + dummy_can_print_ctrlmode(dev); 150 + netdev_dbg(dev, "\n"); 151 + 152 + netdev_dbg(dev, "Classical CAN nominal bittiming:\n"); 153 + dummy_can_print_bittiming(dev, &can_priv->bittiming); 154 + netdev_dbg(dev, "\n"); 155 + 156 + if (can_priv->ctrlmode & CAN_CTRLMODE_FD) { 157 + netdev_dbg(dev, "CAN FD databittiming:\n"); 158 + dummy_can_print_bittiming(dev, &can_priv->fd.data_bittiming); 159 + if (can_fd_tdc_is_enabled(can_priv)) { 160 + netdev_dbg(dev, "\tCAN FD TDC:\n"); 161 + dummy_can_print_tdc(dev, &can_priv->fd.tdc); 162 + } 163 + } 164 + netdev_dbg(dev, "\n"); 165 + 166 + if (can_priv->ctrlmode & CAN_CTRLMODE_XL) { 167 + netdev_dbg(dev, "CAN XL databittiming:\n"); 168 + dummy_can_print_bittiming(dev, &can_priv->xl.data_bittiming); 169 + if (can_xl_tdc_is_enabled(can_priv)) { 170 + netdev_dbg(dev, "\tCAN XL TDC:\n"); 171 + dummy_can_print_tdc(dev, &can_priv->xl.tdc); 172 + } 173 + if (can_priv->ctrlmode & CAN_CTRLMODE_XL_TMS) { 174 + netdev_dbg(dev, "\tCAN XL PWM:\n"); 175 + dummy_can_print_pwm(dev, &can_priv->xl.pwm, 176 + &can_priv->xl.data_bittiming); 177 + } 178 + } 179 + netdev_dbg(dev, "\n"); 180 + } 181 + 182 + static int dummy_can_netdev_open(struct net_device *dev) 183 + { 184 + int ret; 185 + struct can_priv *priv = netdev_priv(dev); 186 + 187 + dummy_can_print_bittiming_info(dev); 188 + netdev_dbg(dev, "error-signalling is %s\n", 189 + str_enabled_disabled(!can_dev_in_xl_only_mode(priv))); 190 + 191 + ret = open_candev(dev); 192 + if (ret) 193 + return ret; 194 + netif_start_queue(dev); 195 + netdev_dbg(dev, "dummy-can is up\n"); 196 + 197 + return 0; 198 + } 199 + 200 + static int dummy_can_netdev_close(struct net_device *dev) 201 + { 202 + netif_stop_queue(dev); 203 + close_candev(dev); 204 + netdev_dbg(dev, "dummy-can is down\n"); 205 + 206 + return 0; 207 + } 208 + 209 + static netdev_tx_t dummy_can_start_xmit(struct sk_buff *skb, 210 + struct net_device *dev) 211 + { 212 + if (can_dev_dropped_skb(dev, skb)) 213 + return NETDEV_TX_OK; 214 + 215 + can_put_echo_skb(skb, dev, 0, 0); 216 + dev->stats.tx_packets++; 217 + dev->stats.tx_bytes += can_get_echo_skb(dev, 0, NULL); 218 + 219 + return NETDEV_TX_OK; 220 + } 221 + 222 + static const struct net_device_ops dummy_can_netdev_ops = { 223 + .ndo_open = dummy_can_netdev_open, 224 + .ndo_stop = dummy_can_netdev_close, 225 + .ndo_start_xmit = dummy_can_start_xmit, 226 + }; 227 + 228 + static const struct ethtool_ops dummy_can_ethtool_ops = { 229 + .get_ts_info = ethtool_op_get_ts_info, 230 + }; 231 + 232 + static int __init dummy_can_init(void) 233 + { 234 + struct net_device *dev; 235 + struct dummy_can *priv; 236 + int ret; 237 + 238 + dev = alloc_candev(sizeof(*priv), 1); 239 + if (!dev) 240 + return -ENOMEM; 241 + 242 + dev->netdev_ops = &dummy_can_netdev_ops; 243 + dev->ethtool_ops = &dummy_can_ethtool_ops; 244 + priv = netdev_priv(dev); 245 + priv->can.bittiming_const = &dummy_can_bittiming_const; 246 + priv->can.bitrate_max = 20 * MEGA /* BPS */; 247 + priv->can.clock.freq = 160 * MEGA /* Hz */; 248 + priv->can.fd.data_bittiming_const = &dummy_can_fd_databittiming_const; 249 + priv->can.fd.tdc_const = &dummy_can_fd_tdc_const; 250 + priv->can.xl.data_bittiming_const = &dummy_can_xl_databittiming_const; 251 + priv->can.xl.tdc_const = &dummy_can_xl_tdc_const; 252 + priv->can.xl.pwm_const = &dummy_can_pwm_const; 253 + priv->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY | 254 + CAN_CTRLMODE_FD | CAN_CTRLMODE_TDC_AUTO | 255 + CAN_CTRLMODE_RESTRICTED | CAN_CTRLMODE_XL | 256 + CAN_CTRLMODE_XL_TDC_AUTO | CAN_CTRLMODE_XL_TMS; 257 + priv->dev = dev; 258 + 259 + ret = register_candev(priv->dev); 260 + if (ret) { 261 + free_candev(priv->dev); 262 + return ret; 263 + } 264 + 265 + dummy_can = priv; 266 + netdev_dbg(dev, "dummy-can ready\n"); 267 + 268 + return 0; 269 + } 270 + 271 + static void __exit dummy_can_exit(void) 272 + { 273 + struct net_device *dev = dummy_can->dev; 274 + 275 + netdev_dbg(dev, "dummy-can bye bye\n"); 276 + unregister_candev(dev); 277 + free_candev(dev); 278 + } 279 + 280 + module_init(dummy_can_init); 281 + module_exit(dummy_can_exit); 282 + 283 + MODULE_DESCRIPTION("A dummy CAN driver, mainly to test the netlink interface"); 284 + MODULE_LICENSE("GPL"); 285 + MODULE_AUTHOR("Vincent Mailhol <mailhol@kernel.org>");
+76 -5
include/linux/can/bittiming.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 2 /* Copyright (c) 2020 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de> 3 - * Copyright (c) 2021 Vincent Mailhol <mailhol.vincent@wanadoo.fr> 3 + * Copyright (c) 2021-2025 Vincent Mailhol <mailhol@kernel.org> 4 4 */ 5 5 6 6 #ifndef _CAN_BITTIMING_H ··· 16 16 17 17 #define CAN_CTRLMODE_FD_TDC_MASK \ 18 18 (CAN_CTRLMODE_TDC_AUTO | CAN_CTRLMODE_TDC_MANUAL) 19 + #define CAN_CTRLMODE_XL_TDC_MASK \ 20 + (CAN_CTRLMODE_XL_TDC_AUTO | CAN_CTRLMODE_XL_TDC_MANUAL) 19 21 #define CAN_CTRLMODE_TDC_AUTO_MASK \ 20 - (CAN_CTRLMODE_TDC_AUTO) 22 + (CAN_CTRLMODE_TDC_AUTO | CAN_CTRLMODE_XL_TDC_AUTO) 21 23 #define CAN_CTRLMODE_TDC_MANUAL_MASK \ 22 - (CAN_CTRLMODE_TDC_MANUAL) 24 + (CAN_CTRLMODE_TDC_MANUAL | CAN_CTRLMODE_XL_TDC_MANUAL) 23 25 24 26 /* 25 27 * struct can_tdc - CAN FD Transmission Delay Compensation parameters ··· 87 85 u32 tdcf; 88 86 }; 89 87 88 + /* The transceiver decoding margin corresponds to t_Decode in ISO 11898-2 */ 89 + #define CAN_PWM_DECODE_NS 5 90 + /* Maximum PWM symbol duration. Corresponds to t_SymbolNom_MAX - t_Decode */ 91 + #define CAN_PWM_NS_MAX (205 - CAN_PWM_DECODE_NS) 92 + 90 93 /* 91 94 * struct can_tdc_const - CAN hardware-dependent constant for 92 95 * Transmission Delay Compensation ··· 125 118 u32 tdcf_max; 126 119 }; 127 120 121 + /* 122 + * struct can_pwm - CAN Pulse-Width Modulation (PWM) parameters 123 + * 124 + * @pwms: pulse width modulation short phase 125 + * @pwml: pulse width modulation long phase 126 + * @pwmo: pulse width modulation offset 127 + */ 128 + struct can_pwm { 129 + u32 pwms; 130 + u32 pwml; 131 + u32 pwmo; 132 + }; 133 + 134 + /* 135 + * struct can_pwm - CAN hardware-dependent constants for Pulse-Width 136 + * Modulation (PWM) 137 + * 138 + * @pwms_min: PWM short phase minimum value. Must be at least 1. 139 + * @pwms_max: PWM short phase maximum value 140 + * @pwml_min: PWM long phase minimum value. Must be at least 1. 141 + * @pwml_max: PWM long phase maximum value 142 + * @pwmo_min: PWM offset phase minimum value 143 + * @pwmo_max: PWM offset phase maximum value 144 + */ 145 + struct can_pwm_const { 146 + u32 pwms_min; 147 + u32 pwms_max; 148 + u32 pwml_min; 149 + u32 pwml_max; 150 + u32 pwmo_min; 151 + u32 pwmo_max; 152 + }; 153 + 128 154 struct data_bittiming_params { 129 155 const struct can_bittiming_const *data_bittiming_const; 130 156 struct can_bittiming data_bittiming; 131 157 const struct can_tdc_const *tdc_const; 132 - struct can_tdc tdc; 158 + const struct can_pwm_const *pwm_const; 159 + union { 160 + struct can_tdc tdc; 161 + struct can_pwm pwm; 162 + }; 133 163 const u32 *data_bitrate_const; 134 164 unsigned int data_bitrate_const_cnt; 135 165 int (*do_set_data_bittiming)(struct net_device *dev); ··· 180 136 void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const, 181 137 const struct can_bittiming *dbt, 182 138 u32 tdc_mask, u32 *ctrlmode, u32 ctrlmode_supported); 139 + 140 + int can_calc_pwm(struct net_device *dev, struct netlink_ext_ack *extack); 183 141 #else /* !CONFIG_CAN_CALC_BITTIMING */ 184 142 static inline int 185 143 can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt, 186 144 const struct can_bittiming_const *btc, struct netlink_ext_ack *extack) 187 145 { 188 - netdev_err(dev, "bit-timing calculation not available\n"); 146 + NL_SET_ERR_MSG(extack, "bit-timing calculation not available\n"); 189 147 return -EINVAL; 190 148 } 191 149 ··· 196 150 const struct can_bittiming *dbt, 197 151 u32 tdc_mask, u32 *ctrlmode, u32 ctrlmode_supported) 198 152 { 153 + } 154 + 155 + static inline int 156 + can_calc_pwm(struct net_device *dev, struct netlink_ext_ack *extack) 157 + { 158 + NL_SET_ERR_MSG(extack, 159 + "bit-timing calculation not available: manually provide PWML and PWMS\n"); 160 + return -EINVAL; 199 161 } 200 162 #endif /* CONFIG_CAN_CALC_BITTIMING */ 201 163 ··· 217 163 const u32 *bitrate_const, 218 164 const unsigned int bitrate_const_cnt, 219 165 struct netlink_ext_ack *extack); 166 + 167 + int can_validate_pwm_bittiming(const struct net_device *dev, 168 + const struct can_pwm *pwm, 169 + struct netlink_ext_ack *extack); 220 170 221 171 /* 222 172 * can_get_relative_tdco() - TDCO relative to the sample point ··· 262 204 static inline unsigned int can_bit_time(const struct can_bittiming *bt) 263 205 { 264 206 return CAN_SYNC_SEG + bt->prop_seg + bt->phase_seg1 + bt->phase_seg2; 207 + } 208 + 209 + /* Duration of one bit in minimum time quantum */ 210 + static inline unsigned int can_bit_time_tqmin(const struct can_bittiming *bt) 211 + { 212 + return can_bit_time(bt) * bt->brp; 213 + } 214 + 215 + /* Convert a duration from minimum a minimum time quantum to nano seconds */ 216 + static inline u32 can_tqmin_to_ns(u32 tqmin, u32 clock_freq) 217 + { 218 + return DIV_U64_ROUND_CLOSEST(mul_u32_u32(tqmin, NSEC_PER_SEC), 219 + clock_freq); 265 220 } 266 221 267 222 #endif /* !_CAN_BITTIMING_H */
+51 -17
include/linux/can/dev.h
··· 47 47 48 48 const struct can_bittiming_const *bittiming_const; 49 49 struct can_bittiming bittiming; 50 - struct data_bittiming_params fd; 50 + struct data_bittiming_params fd, xl; 51 51 unsigned int bitrate_const_cnt; 52 52 const u32 *bitrate_const; 53 53 u32 bitrate_max; ··· 85 85 return !!(priv->ctrlmode & CAN_CTRLMODE_FD_TDC_MASK); 86 86 } 87 87 88 + static inline bool can_xl_tdc_is_enabled(const struct can_priv *priv) 89 + { 90 + return !!(priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MASK); 91 + } 92 + 88 93 static inline u32 can_get_static_ctrlmode(struct can_priv *priv) 89 94 { 90 95 return priv->ctrlmode & ~priv->ctrlmode_supported; ··· 98 93 static inline bool can_is_canxl_dev_mtu(unsigned int mtu) 99 94 { 100 95 return (mtu >= CANXL_MIN_MTU && mtu <= CANXL_MAX_MTU); 101 - } 102 - 103 - /* drop skb if it does not contain a valid CAN frame for sending */ 104 - static inline bool can_dev_dropped_skb(struct net_device *dev, struct sk_buff *skb) 105 - { 106 - struct can_priv *priv = netdev_priv(dev); 107 - 108 - if (priv->ctrlmode & CAN_CTRLMODE_LISTENONLY) { 109 - netdev_info_once(dev, 110 - "interface in listen only mode, dropping skb\n"); 111 - kfree_skb(skb); 112 - dev->stats.tx_dropped++; 113 - return true; 114 - } 115 - 116 - return can_dropped_invalid_skb(dev, skb); 117 96 } 118 97 119 98 void can_setup(struct net_device *dev); ··· 134 145 135 146 const char *can_get_state_str(const enum can_state state); 136 147 const char *can_get_ctrlmode_str(u32 ctrlmode); 148 + 149 + static inline bool can_dev_in_xl_only_mode(struct can_priv *priv) 150 + { 151 + const u32 mixed_mode = CAN_CTRLMODE_FD | CAN_CTRLMODE_XL; 152 + 153 + /* When CAN XL is enabled but FD is disabled we are running in 154 + * the so-called 'CANXL-only mode' where the error signalling is 155 + * disabled. This helper function determines the required value 156 + * to disable error signalling in the CAN XL controller. 157 + * The so-called CC/FD/XL 'mixed mode' requires error signalling. 158 + */ 159 + return ((priv->ctrlmode & mixed_mode) == CAN_CTRLMODE_XL); 160 + } 161 + 162 + /* drop skb if it does not contain a valid CAN frame for sending */ 163 + static inline bool can_dev_dropped_skb(struct net_device *dev, struct sk_buff *skb) 164 + { 165 + struct can_priv *priv = netdev_priv(dev); 166 + u32 silent_mode = priv->ctrlmode & (CAN_CTRLMODE_LISTENONLY | 167 + CAN_CTRLMODE_RESTRICTED); 168 + 169 + if (silent_mode) { 170 + netdev_info_once(dev, "interface in %s mode, dropping skb\n", 171 + can_get_ctrlmode_str(silent_mode)); 172 + goto invalid_skb; 173 + } 174 + 175 + if (!(priv->ctrlmode & CAN_CTRLMODE_FD) && can_is_canfd_skb(skb)) { 176 + netdev_info_once(dev, "CAN FD is disabled, dropping skb\n"); 177 + goto invalid_skb; 178 + } 179 + 180 + if (can_dev_in_xl_only_mode(priv) && !can_is_canxl_skb(skb)) { 181 + netdev_info_once(dev, 182 + "Error signaling is disabled, dropping skb\n"); 183 + goto invalid_skb; 184 + } 185 + 186 + return can_dropped_invalid_skb(dev, skb); 187 + 188 + invalid_skb: 189 + kfree_skb(skb); 190 + dev->stats.tx_dropped++; 191 + return true; 192 + } 137 193 138 194 void can_state_get_by_berr_counter(const struct net_device *dev, 139 195 const struct can_berr_counter *bec,
+34
include/uapi/linux/can/netlink.h
··· 5 5 * Definitions for the CAN netlink interface 6 6 * 7 7 * Copyright (c) 2009 Wolfgang Grandegger <wg@grandegger.com> 8 + * Copyright (c) 2021-2025 Vincent Mailhol <mailhol@kernel.org> 8 9 * 9 10 * This program is free software; you can redistribute it and/or modify 10 11 * it under the terms of the version 2 of the GNU General Public License ··· 104 103 #define CAN_CTRLMODE_CC_LEN8_DLC 0x100 /* Classic CAN DLC option */ 105 104 #define CAN_CTRLMODE_TDC_AUTO 0x200 /* FD transceiver automatically calculates TDCV */ 106 105 #define CAN_CTRLMODE_TDC_MANUAL 0x400 /* FD TDCV is manually set up by user */ 106 + #define CAN_CTRLMODE_RESTRICTED 0x800 /* Restricted operation mode */ 107 + #define CAN_CTRLMODE_XL 0x1000 /* CAN XL mode */ 108 + #define CAN_CTRLMODE_XL_TDC_AUTO 0x2000 /* XL transceiver automatically calculates TDCV */ 109 + #define CAN_CTRLMODE_XL_TDC_MANUAL 0x4000 /* XL TDCV is manually set up by user */ 110 + #define CAN_CTRLMODE_XL_TMS 0x8000 /* Transceiver Mode Switching */ 107 111 108 112 /* 109 113 * CAN device statistics ··· 144 138 IFLA_CAN_BITRATE_MAX, 145 139 IFLA_CAN_TDC, /* FD */ 146 140 IFLA_CAN_CTRLMODE_EXT, 141 + IFLA_CAN_XL_DATA_BITTIMING, 142 + IFLA_CAN_XL_DATA_BITTIMING_CONST, 143 + IFLA_CAN_XL_DATA_BITRATE_CONST, 144 + IFLA_CAN_XL_TDC, 145 + IFLA_CAN_XL_PWM, 147 146 148 147 /* add new constants above here */ 149 148 __IFLA_CAN_MAX, ··· 188 177 /* add new constants above here */ 189 178 __IFLA_CAN_CTRLMODE, 190 179 IFLA_CAN_CTRLMODE_MAX = __IFLA_CAN_CTRLMODE - 1 180 + }; 181 + 182 + /* 183 + * CAN FD/XL Pulse-Width Modulation (PWM) 184 + * 185 + * Please refer to struct can_pwm_const and can_pwm in 186 + * include/linux/can/bittiming.h for further details. 187 + */ 188 + enum { 189 + IFLA_CAN_PWM_UNSPEC, 190 + IFLA_CAN_PWM_PWMS_MIN, /* u32 */ 191 + IFLA_CAN_PWM_PWMS_MAX, /* u32 */ 192 + IFLA_CAN_PWM_PWML_MIN, /* u32 */ 193 + IFLA_CAN_PWM_PWML_MAX, /* u32 */ 194 + IFLA_CAN_PWM_PWMO_MIN, /* u32 */ 195 + IFLA_CAN_PWM_PWMO_MAX, /* u32 */ 196 + IFLA_CAN_PWM_PWMS, /* u32 */ 197 + IFLA_CAN_PWM_PWML, /* u32 */ 198 + IFLA_CAN_PWM_PWMO, /* u32 */ 199 + 200 + /* add new constants above here */ 201 + __IFLA_CAN_PWM, 202 + IFLA_CAN_PWM_MAX = __IFLA_CAN_PWM - 1 191 203 }; 192 204 193 205 /* u16 termination range: 1..65535 Ohms */
+46 -8
net/can/raw.c
··· 892 892 } 893 893 } 894 894 895 - static unsigned int raw_check_txframe(struct raw_sock *ro, struct sk_buff *skb, int mtu) 895 + static inline bool raw_dev_cc_enabled(struct net_device *dev, 896 + struct can_priv *priv) 896 897 { 897 - /* Classical CAN -> no checks for flags and device capabilities */ 898 - if (can_is_can_skb(skb)) 898 + /* The CANXL-only mode disables error-signalling on the CAN bus 899 + * which is needed to send CAN CC/FD frames 900 + */ 901 + if (priv) 902 + return !can_dev_in_xl_only_mode(priv); 903 + 904 + /* virtual CAN interfaces always support CAN CC */ 905 + return true; 906 + } 907 + 908 + static inline bool raw_dev_fd_enabled(struct net_device *dev, 909 + struct can_priv *priv) 910 + { 911 + /* check FD ctrlmode on real CAN interfaces */ 912 + if (priv) 913 + return (priv->ctrlmode & CAN_CTRLMODE_FD); 914 + 915 + /* check MTU for virtual CAN FD interfaces */ 916 + return (READ_ONCE(dev->mtu) >= CANFD_MTU); 917 + } 918 + 919 + static inline bool raw_dev_xl_enabled(struct net_device *dev, 920 + struct can_priv *priv) 921 + { 922 + /* check XL ctrlmode on real CAN interfaces */ 923 + if (priv) 924 + return (priv->ctrlmode & CAN_CTRLMODE_XL); 925 + 926 + /* check MTU for virtual CAN XL interfaces */ 927 + return can_is_canxl_dev_mtu(READ_ONCE(dev->mtu)); 928 + } 929 + 930 + static unsigned int raw_check_txframe(struct raw_sock *ro, struct sk_buff *skb, 931 + struct net_device *dev) 932 + { 933 + struct can_priv *priv = safe_candev_priv(dev); 934 + 935 + /* Classical CAN */ 936 + if (can_is_can_skb(skb) && raw_dev_cc_enabled(dev, priv)) 899 937 return CAN_MTU; 900 938 901 - /* CAN FD -> needs to be enabled and a CAN FD or CAN XL device */ 939 + /* CAN FD */ 902 940 if (ro->fd_frames && can_is_canfd_skb(skb) && 903 - (mtu == CANFD_MTU || can_is_canxl_dev_mtu(mtu))) 941 + raw_dev_fd_enabled(dev, priv)) 904 942 return CANFD_MTU; 905 943 906 - /* CAN XL -> needs to be enabled and a CAN XL device */ 944 + /* CAN XL */ 907 945 if (ro->xl_frames && can_is_canxl_skb(skb) && 908 - can_is_canxl_dev_mtu(mtu)) 946 + raw_dev_xl_enabled(dev, priv)) 909 947 return CANXL_MTU; 910 948 911 949 return 0; ··· 999 961 err = -EINVAL; 1000 962 1001 963 /* check for valid CAN (CC/FD/XL) frame content */ 1002 - txmtu = raw_check_txframe(ro, skb, READ_ONCE(dev->mtu)); 964 + txmtu = raw_check_txframe(ro, skb, dev); 1003 965 if (!txmtu) 1004 966 goto free_skb; 1005 967