Skip to content

Commit

Permalink
Merge tag 'linux-can-next-for-6.3-20230206' of git://git.kernel.org/p…
Browse files Browse the repository at this point in the history
…ub/scm/linux/kernel/git/mkl/linux-can-next

Marc Kleine-Budde says:

====================
pull-request: can-next 2023-02-06

this is a pull request of 47 patches for net-next/master.

The first two patch is by Oliver Hartkopp. One adds missing error
checking to the CAN_GW protocol, the other adds a missing CAN address
family check to the CAN ISO TP protocol.

Thomas Kopp contributes a performance optimization to the mcp251xfd
driver.

The next 11 patches are by Geert Uytterhoeven and add support for
R-Car V4H systems to the rcar_canfd driver.

Stephane Grosjean and Lukas Magel contribute 8 patches to the peak_usb
driver, which add support for configurable CAN channel ID.

The last 17 patches are by me and target the CAN bit timing
configuration. The bit timing is cleaned up, error messages are
improved and forwarded to user space via NL_SET_ERR_MSG_FMT() instead
of netdev_err(), and the SJW handling is updated, including the
definition of a new default value that will benefit CAN-FD
controllers, by increasing their oscillator tolerance.

* tag 'linux-can-next-for-6.3-20230206' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next: (47 commits)
  can: bittiming: can_validate_bitrate(): report error via netlink
  can: bittiming: can_calc_bittiming(): convert from netdev_err() to NL_SET_ERR_MSG_FMT()
  can: bittiming: can_calc_bittiming(): clean up SJW handling
  can: bittiming: can_sjw_set_default(): use Phase Seg2 / 2 as default for SJW
  can: bittiming: can_sjw_check(): check that SJW is not longer than either Phase Buffer Segment
  can: bittiming: can_sjw_check(): report error via netlink and harmonize error value
  can: bittiming: can_fixup_bittiming(): report error via netlink and harmonize error value
  can: bittiming: factor out can_sjw_set_default() and can_sjw_check()
  can: bittiming: can_changelink() pass extack down callstack
  can: netlink: can_changelink(): convert from netdev_err() to NL_SET_ERR_MSG_FMT()
  can: netlink: can_validate(): validate sample point for CAN and CAN-FD
  can: dev: register_candev(): bail out if both fixed bit rates and bit timing constants are provided
  can: dev: register_candev(): ensure that bittiming const are valid
  can: bittiming: can_get_bittiming(): use direct return and remove unneeded else
  can: bittiming: can_fixup_bittiming(): set effective tq
  can: bittiming: can_fixup_bittiming(): use CAN_SYNC_SEG instead of 1
  can: bittiming(): replace open coded variants of can_bit_time()
  can: peak_usb: Reorder include directives alphabetically
  can: peak_usb: align CAN channel ID format in log with sysfs attribute
  can: peak_usb: export PCAN CAN channel ID as sysfs device attribute
  ...
====================

Link: https://lore.kernel.org/r/20230206131620.2758724-1-mkl@pengutronix.de
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Paolo Abeni committed Feb 7, 2023
2 parents ca8e4cb + 3dafbe5 commit 61d731e
Show file tree
Hide file tree
Showing 19 changed files with 728 additions and 251 deletions.
19 changes: 19 additions & 0 deletions Documentation/ABI/testing/sysfs-class-net-peak_usb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

What: /sys/class/net/<iface>/peak_usb/can_channel_id
Date: November 2022
KernelVersion: 6.2
Contact: Stephane Grosjean <s.grosjean@peak-system.com>
Description:
PEAK PCAN-USB devices support user-configurable CAN channel
identifiers. Contrary to a USB serial number, these identifiers
are writable and can be set per CAN interface. This means that
if a USB device exports multiple CAN interfaces, each of them
can be assigned a unique channel ID.
This attribute provides read-only access to the currently
configured value of the channel identifier. Depending on the
device type, the identifier has a length of 8 or 32 bit. The
value read from this attribute is always an 8 digit 32 bit
hexadecimal value in big endian format. If the device only
supports an 8 bit identifier, the upper 24 bit of the value are
set to zero.

16 changes: 12 additions & 4 deletions Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,19 @@ properties:
- renesas,r8a77995-canfd # R-Car D3
- const: renesas,rcar-gen3-canfd # R-Car Gen3 and RZ/G2

- items:
- enum:
- renesas,r8a779a0-canfd # R-Car V3U
- renesas,r8a779g0-canfd # R-Car V4H
- const: renesas,rcar-gen4-canfd # R-Car Gen4

- items:
- enum:
- renesas,r9a07g043-canfd # RZ/G2UL and RZ/Five
- renesas,r9a07g044-canfd # RZ/G2{L,LC}
- renesas,r9a07g054-canfd # RZ/V2L
- const: renesas,rzg2l-canfd # RZ/G2L family

- const: renesas,r8a779a0-canfd # R-Car V3U

reg:
maxItems: 1

Expand All @@ -60,7 +64,7 @@ properties:
$ref: /schemas/types.yaml#/definitions/flag
description:
The controller can operate in either CAN FD only mode (default) or
Classical CAN only mode. The mode is global to both the channels.
Classical CAN only mode. The mode is global to all channels.
Specify this property to put the controller in Classical CAN only mode.

assigned-clocks:
Expand All @@ -80,6 +84,10 @@ patternProperties:
The controller supports multiple channels and each is represented as a
child node. Each channel can be enabled/disabled individually.

properties:
phys:
maxItems: 1

additionalProperties: false

required:
Expand Down Expand Up @@ -159,7 +167,7 @@ allOf:
properties:
compatible:
contains:
const: renesas,r8a779a0-canfd
const: renesas,rcar-gen4-canfd
then:
patternProperties:
"^channel[2-7]$": false
Expand Down
120 changes: 93 additions & 27 deletions drivers/net/can/dev/bittiming.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,81 @@

#include <linux/can/dev.h>

void can_sjw_set_default(struct can_bittiming *bt)
{
if (bt->sjw)
return;

/* If user space provides no sjw, use sane default of phase_seg2 / 2 */
bt->sjw = max(1U, min(bt->phase_seg1, bt->phase_seg2 / 2));
}

int can_sjw_check(const struct net_device *dev, const struct can_bittiming *bt,
const struct can_bittiming_const *btc, struct netlink_ext_ack *extack)
{
if (bt->sjw > btc->sjw_max) {
NL_SET_ERR_MSG_FMT(extack, "sjw: %u greater than max sjw: %u",
bt->sjw, btc->sjw_max);
return -EINVAL;
}

if (bt->sjw > bt->phase_seg1) {
NL_SET_ERR_MSG_FMT(extack,
"sjw: %u greater than phase-seg1: %u",
bt->sjw, bt->phase_seg1);
return -EINVAL;
}

if (bt->sjw > bt->phase_seg2) {
NL_SET_ERR_MSG_FMT(extack,
"sjw: %u greater than phase-seg2: %u",
bt->sjw, bt->phase_seg2);
return -EINVAL;
}

return 0;
}

/* Checks the validity of the specified bit-timing parameters prop_seg,
* phase_seg1, phase_seg2 and sjw and tries to determine the bitrate
* prescaler value brp. You can find more information in the header
* file linux/can/netlink.h.
*/
static int can_fixup_bittiming(const struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc)
const struct can_bittiming_const *btc,
struct netlink_ext_ack *extack)
{
const unsigned int tseg1 = bt->prop_seg + bt->phase_seg1;
const struct can_priv *priv = netdev_priv(dev);
unsigned int tseg1, alltseg;
u64 brp64;
int err;

tseg1 = bt->prop_seg + bt->phase_seg1;
if (!bt->sjw)
bt->sjw = 1;
if (bt->sjw > btc->sjw_max ||
tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max ||
bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max)
return -ERANGE;
if (tseg1 < btc->tseg1_min) {
NL_SET_ERR_MSG_FMT(extack, "prop-seg + phase-seg1: %u less than tseg1-min: %u",
tseg1, btc->tseg1_min);
return -EINVAL;
}
if (tseg1 > btc->tseg1_max) {
NL_SET_ERR_MSG_FMT(extack, "prop-seg + phase-seg1: %u greater than tseg1-max: %u",
tseg1, btc->tseg1_max);
return -EINVAL;
}
if (bt->phase_seg2 < btc->tseg2_min) {
NL_SET_ERR_MSG_FMT(extack, "phase-seg2: %u less than tseg2-min: %u",
bt->phase_seg2, btc->tseg2_min);
return -EINVAL;
}
if (bt->phase_seg2 > btc->tseg2_max) {
NL_SET_ERR_MSG_FMT(extack, "phase-seg2: %u greater than tseg2-max: %u",
bt->phase_seg2, btc->tseg2_max);
return -EINVAL;
}

can_sjw_set_default(bt);

err = can_sjw_check(dev, bt, btc, extack);
if (err)
return err;

brp64 = (u64)priv->clock.freq * (u64)bt->tq;
if (btc->brp_inc > 1)
Expand All @@ -35,12 +91,21 @@ static int can_fixup_bittiming(const struct net_device *dev, struct can_bittimin
brp64 *= btc->brp_inc;
bt->brp = (u32)brp64;

if (bt->brp < btc->brp_min || bt->brp > btc->brp_max)
if (bt->brp < btc->brp_min) {
NL_SET_ERR_MSG_FMT(extack, "resulting brp: %u less than brp-min: %u",
bt->brp, btc->brp_min);
return -EINVAL;
}
if (bt->brp > btc->brp_max) {
NL_SET_ERR_MSG_FMT(extack, "resulting brp: %u greater than brp-max: %u",
bt->brp, btc->brp_max);
return -EINVAL;
}

alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1;
bt->bitrate = priv->clock.freq / (bt->brp * alltseg);
bt->sample_point = ((tseg1 + 1) * 1000) / alltseg;
bt->bitrate = priv->clock.freq / (bt->brp * can_bit_time(bt));
bt->sample_point = ((CAN_SYNC_SEG + tseg1) * 1000) / can_bit_time(bt);
bt->tq = DIV_U64_ROUND_CLOSEST(mul_u32_u32(bt->brp, NSEC_PER_SEC),
priv->clock.freq);

return 0;
}
Expand All @@ -49,7 +114,8 @@ static int can_fixup_bittiming(const struct net_device *dev, struct can_bittimin
static int
can_validate_bitrate(const struct net_device *dev, const struct can_bittiming *bt,
const u32 *bitrate_const,
const unsigned int bitrate_const_cnt)
const unsigned int bitrate_const_cnt,
struct netlink_ext_ack *extack)
{
unsigned int i;

Expand All @@ -58,30 +124,30 @@ can_validate_bitrate(const struct net_device *dev, const struct can_bittiming *b
return 0;
}

NL_SET_ERR_MSG_FMT(extack, "bitrate %u bps not supported",
bt->brp);

return -EINVAL;
}

int can_get_bittiming(const struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc,
const u32 *bitrate_const,
const unsigned int bitrate_const_cnt)
const unsigned int bitrate_const_cnt,
struct netlink_ext_ack *extack)
{
int err;

/* Depending on the given can_bittiming parameter structure the CAN
* timing parameters are calculated based on the provided bitrate OR
* alternatively the CAN timing parameters (tq, prop_seg, etc.) are
* provided directly which are then checked and fixed up.
*/
if (!bt->tq && bt->bitrate && btc)
err = can_calc_bittiming(dev, bt, btc);
else if (bt->tq && !bt->bitrate && btc)
err = can_fixup_bittiming(dev, bt, btc);
else if (!bt->tq && bt->bitrate && bitrate_const)
err = can_validate_bitrate(dev, bt, bitrate_const,
bitrate_const_cnt);
else
err = -EINVAL;

return err;
return can_calc_bittiming(dev, bt, btc, extack);
if (bt->tq && !bt->bitrate && btc)
return can_fixup_bittiming(dev, bt, btc, extack);
if (!bt->tq && bt->bitrate && bitrate_const)
return can_validate_bitrate(dev, bt, bitrate_const,
bitrate_const_cnt, extack);

return -EINVAL;
}
34 changes: 15 additions & 19 deletions drivers/net/can/dev/calc_bittiming.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ can_update_sample_point(const struct can_bittiming_const *btc,
}

int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc)
const struct can_bittiming_const *btc, struct netlink_ext_ack *extack)
{
struct can_priv *priv = netdev_priv(dev);
unsigned int bitrate; /* current bitrate */
Expand All @@ -76,6 +76,7 @@ int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
unsigned int best_brp = 0; /* current best value for brp */
unsigned int brp, tsegall, tseg, tseg1 = 0, tseg2 = 0;
u64 v64;
int err;

/* Use CiA recommended sample points */
if (bt->sample_point) {
Expand Down Expand Up @@ -133,13 +134,14 @@ int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
do_div(v64, bt->bitrate);
bitrate_error = (u32)v64;
if (bitrate_error > CAN_CALC_MAX_ERROR) {
netdev_err(dev,
"bitrate error %d.%d%% too high\n",
bitrate_error / 10, bitrate_error % 10);
return -EDOM;
NL_SET_ERR_MSG_FMT(extack,
"bitrate error: %u.%u%% too high",
bitrate_error / 10, bitrate_error % 10);
return -EINVAL;
}
netdev_warn(dev, "bitrate error %d.%d%%\n",
bitrate_error / 10, bitrate_error % 10);
NL_SET_ERR_MSG_FMT(extack,
"bitrate error: %u.%u%%",
bitrate_error / 10, bitrate_error % 10);
}

/* real sample point */
Expand All @@ -154,23 +156,17 @@ int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
bt->phase_seg1 = tseg1 - bt->prop_seg;
bt->phase_seg2 = tseg2;

/* check for sjw user settings */
if (!bt->sjw || !btc->sjw_max) {
bt->sjw = 1;
} else {
/* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
if (bt->sjw > btc->sjw_max)
bt->sjw = btc->sjw_max;
/* bt->sjw must not be higher than tseg2 */
if (tseg2 < bt->sjw)
bt->sjw = tseg2;
}
can_sjw_set_default(bt);

err = can_sjw_check(dev, bt, btc, extack);
if (err)
return err;

bt->brp = best_brp;

/* real bitrate */
bt->bitrate = priv->clock.freq /
(bt->brp * (CAN_SYNC_SEG + tseg1 + tseg2));
(bt->brp * can_bit_time(bt));

return 0;
}
Expand Down
21 changes: 21 additions & 0 deletions drivers/net/can/dev/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,18 @@ static int can_get_termination(struct net_device *ndev)
return 0;
}

static bool
can_bittiming_const_valid(const struct can_bittiming_const *btc)
{
if (!btc)
return true;

if (!btc->sjw_max)
return false;

return true;
}

/* Register the CAN network device */
int register_candev(struct net_device *dev)
{
Expand All @@ -518,6 +530,15 @@ int register_candev(struct net_device *dev)
if (!priv->data_bitrate_const != !priv->data_bitrate_const_cnt)
return -EINVAL;

/* We only support either fixed bit rates or bit timing const. */
if ((priv->bitrate_const || priv->data_bitrate_const) &&
(priv->bittiming_const || priv->data_bittiming_const))
return -EINVAL;

if (!can_bittiming_const_valid(priv->bittiming_const) ||
!can_bittiming_const_valid(priv->data_bittiming_const))
return -EINVAL;

if (!priv->termination_const) {
err = can_get_termination(dev);
if (err)
Expand Down
Loading

0 comments on commit 61d731e

Please sign in to comment.