From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CC60A306B32; Mon, 13 Oct 2025 11:02:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760353348; cv=none; b=j6ntYYJUhfpHV/XCFjDbXPuHQBKzoc7E4Go+L1iR5M/DQ428n6tkuZ3dMR9Tnv93b8OeMAnAqfCSF4Z9Blg+/xHJiQwaAO+5+4UCRmjtbdZthOUsxJ+C3zo9j5ZEwRHhZLFne4WFJgNYReVyDQvBo11+4IylGT6FiJ1wJsriOh4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760353348; c=relaxed/simple; bh=SVkz8ubG9Huc9VSDbQmkkTmS9kcmf6P1SBgnQ67oxnk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nPKMWOah2RCku35BNJkcndi0cMzFWIULjM+m+mUWmOT+H9YYvaau+Vz7IJeECCmlc69FY8qC+YFvo2VN47avXTMCb6snUXJINT7/J9eA1bH9qBTnCam7gwepOskDvlhGOpXTqVuwuGZ5OMIhjlX8NmoTgv6mjhDXTZpKd6P8hR4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EEnvAd2Q; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="EEnvAd2Q" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E546EC4CEE7; Mon, 13 Oct 2025 11:02:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760353348; bh=SVkz8ubG9Huc9VSDbQmkkTmS9kcmf6P1SBgnQ67oxnk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=EEnvAd2QfBMws7T2upWfyTIMo1N8WuPnWObRzzBjCjCV8d47Gtz3rrPJ97n2l2MC/ FFaNMOegJDbtyZG1boHN9YNq94jvSFrSrR2BI4RVM2k+D9jTjajcNKBFSQe6RE8OGG 4pH3I9depKVg9Mqz4lGPkwOSWZ4FUEo3m186fpXMQ+B22ZRhlMJ0XGz2J+oXit54Y8 7cTB8+k6SHSY/2KTXxEPXnqi1HefNhfS2jQOiHvPI2KZOdDVCOh8HY/YrcjAtVSH6N HbnLYfgWKPT4aDkWoyynI6QKx8cr1vbAU0AqPj6dw2pzExtJSt2f2IR38jN3silOzx wTNZJyb4ANGqA== From: Vincent Mailhol Date: Mon, 13 Oct 2025 20:01:29 +0900 Subject: [PATCH 7/9] can: bittiming: add PWM validation Precedence: bulk X-Mailing-List: linux-can@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20251013-canxl-netlink-v1-7-f422b7e2729f@kernel.org> References: <20251013-canxl-netlink-v1-0-f422b7e2729f@kernel.org> In-Reply-To: <20251013-canxl-netlink-v1-0-f422b7e2729f@kernel.org> To: Marc Kleine-Budde , Oliver Hartkopp Cc: Vincent Mailhol , =?utf-8?q?St=C3=A9phane_Grosjean?= , Robert Nawrath , Minh Le , Duy Nguyen , linux-can@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=5186; i=mailhol@kernel.org; h=from:subject:message-id; bh=SVkz8ubG9Huc9VSDbQmkkTmS9kcmf6P1SBgnQ67oxnk=; b=owGbwMvMwCV2McXO4Xp97WbG02pJDBlv7uglvvULsuL0Cf+tHlWcfm5HXvGy2IOv/B5xxHytM qnzLXTuKGVhEONikBVTZFlWzsmt0FHoHXboryXMHFYmkCEMXJwCMJGVdQz/fZQ57oWJ8hUwbWva /+r+XXYXhdD5D5Revyq9ZrL0/9Ez1xgZnnI0f/nX8b+RtWWZiNGkeo0KdqkizRfbd7GZrdmctP8 4KwA= X-Developer-Key: i=mailhol@kernel.org; a=openpgp; fpr=ED8F700574E67F20E574E8E2AB5FEB886DBB99C2 Add can_validate_pwm() to validate the values pwms, pwml and pwml. Error messages are added to each of the checks to inform the user on what went wrong. Refer to those error messages to understand the validation logic. The boundary values CAN_PWM_DECODE_NS (the transceiver minimum decoding margin) and CAN_PWM_NS_MAX (the maximum PWM symbol duration) are hardcoded for the moment. Note that a transceiver capable of bitrates higher than 20 Mbps may be able to handle a CAN_PWM_DECODE_NS below 5 ns. If such transceivers become commercially available, this code could be revisited to make this parameter configurable. For now, leave it static. Signed-off-by: Vincent Mailhol --- drivers/net/can/dev/bittiming.c | 63 +++++++++++++++++++++++++++++++++++++++++ include/linux/can/bittiming.h | 22 ++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/drivers/net/can/dev/bittiming.c b/drivers/net/can/dev/bittiming.c index 0b93900b1dfa..730b1b254460 100644 --- a/drivers/net/can/dev/bittiming.c +++ b/drivers/net/can/dev/bittiming.c @@ -2,6 +2,7 @@ /* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix * Copyright (C) 2006 Andrey Volkov, Varma Electronics * Copyright (C) 2008-2009 Wolfgang Grandegger + * Copyright (c) 2025 Vincent Mailhol */ #include @@ -151,3 +152,65 @@ int can_get_bittiming(const struct net_device *dev, struct can_bittiming *bt, return -EINVAL; } + +int can_validate_pwm_bittiming(const struct net_device *dev, + const struct can_pwm *pwm, + struct netlink_ext_ack *extack) +{ + const struct can_priv *priv = netdev_priv(dev); + u32 xl_bit_time_tqmin = can_bit_time_tqmin(&priv->xl.data_bittiming); + u32 nom_bit_time_tqmin = can_bit_time_tqmin(&priv->bittiming); + u32 pwms_ns = can_tqmin_to_ns(pwm->pwms, priv->clock.freq); + u32 pwml_ns = can_tqmin_to_ns(pwm->pwml, priv->clock.freq); + + if (pwms_ns + pwml_ns > CAN_PWM_NS_MAX) { + NL_SET_ERR_MSG_FMT(extack, + "The PWM symbol duration: %u ns may no exceed %u ns", + pwms_ns + pwml_ns, CAN_PWM_NS_MAX); + return -EINVAL; + } + + if (pwms_ns < CAN_PWM_DECODE_NS) { + NL_SET_ERR_MSG_FMT(extack, + "PWMS: %u ns shall be at least %u ns", + pwms_ns, CAN_PWM_DECODE_NS); + return -EINVAL; + } + + if (pwm->pwms >= pwm->pwml) { + NL_SET_ERR_MSG_FMT(extack, + "PWMS: %u tqmin shall be smaller than PWML: %u tqmin", + pwm->pwms, pwm->pwml); + return -EINVAL; + } + + if (pwml_ns - pwms_ns < 2 * CAN_PWM_DECODE_NS) { + NL_SET_ERR_MSG_FMT(extack, + "At least %u ns shall separate PWMS: %u ns from PMWL: %u ns", + 2 * CAN_PWM_DECODE_NS, pwms_ns, pwml_ns); + return -EINVAL; + } + + if (xl_bit_time_tqmin % (pwm->pwms + pwm->pwml) != 0) { + NL_SET_ERR_MSG_FMT(extack, + "PWM duration: %u tqmin does not divide XL's bit time: %u tqmin", + pwm->pwms + pwm->pwml, xl_bit_time_tqmin); + return -EINVAL; + } + + if (pwm->pwmo >= pwm->pwms + pwm->pwml) { + NL_SET_ERR_MSG_FMT(extack, + "PWMO: %u tqmin can not be greater than PWMS + PWML: %u tqmin", + pwm->pwmo, pwm->pwms + pwm->pwml); + return -EINVAL; + } + + if (nom_bit_time_tqmin % (pwm->pwms + pwm->pwml) != pwm->pwmo) { + NL_SET_ERR_MSG_FMT(extack, + "Can not assemble nominal bit time: %u tqmin out of PWMS + PMWL and PWMO", + nom_bit_time_tqmin); + return -EINVAL; + } + + return 0; +} diff --git a/include/linux/can/bittiming.h b/include/linux/can/bittiming.h index 14ad249aa8cd..02cf9541a1dd 100644 --- a/include/linux/can/bittiming.h +++ b/include/linux/can/bittiming.h @@ -87,6 +87,11 @@ struct can_tdc { u32 tdcf; }; +/* The transceiver decoding margin corresponds to t_Decode in ISO 11898-2 */ +#define CAN_PWM_DECODE_NS 5 +/* Maximum PWM symbol duration. Corresponds to t_SymbolNom_MAX - t_Decode */ +#define CAN_PWM_NS_MAX (205 - CAN_PWM_DECODE_NS) + /* * struct can_tdc_const - CAN hardware-dependent constant for * Transmission Delay Compensation @@ -203,6 +208,10 @@ int can_get_bittiming(const struct net_device *dev, struct can_bittiming *bt, const unsigned int bitrate_const_cnt, struct netlink_ext_ack *extack); +int can_validate_pwm_bittiming(const struct net_device *dev, + const struct can_pwm *pwm, + struct netlink_ext_ack *extack); + /* * can_get_relative_tdco() - TDCO relative to the sample point * @@ -245,4 +254,17 @@ static inline unsigned int can_bit_time(const struct can_bittiming *bt) return CAN_SYNC_SEG + bt->prop_seg + bt->phase_seg1 + bt->phase_seg2; } +/* Duration of one bit in minimum time quantum */ +static inline unsigned int can_bit_time_tqmin(const struct can_bittiming *bt) +{ + return can_bit_time(bt) * bt->brp; +} + +/* Convert a duration from minimum a minimum time quantum to nano seconds */ +static inline u32 can_tqmin_to_ns(u32 tqmin, u32 clock_freq) +{ + return DIV_U64_ROUND_CLOSEST(mul_u32_u32(tqmin, NSEC_PER_SEC), + clock_freq); +} + #endif /* !_CAN_BITTIMING_H */ -- 2.49.1