linux-can-next-for-5.20-20220625

-----BEGIN PGP SIGNATURE-----
 
 iQFHBAABCgAxFiEEBsvAIBsPu6mG7thcrX5LkNig010FAmK28FETHG1rbEBwZW5n
 dXRyb25peC5kZQAKCRCtfkuQ2KDTXdl9B/4h4emFRjxz0BuorLEPezEHbW3ULFES
 CqPOgEOj7YalEqECOYrZLf4tmQQEbWcRrKIRmBp7vVLDfSwVtY7fsjUlh0rrbpDh
 zXF3uCQDkm07Sy1upBbIXFCU7OBETSbtPKWF87YOcJVWpQbkwacPiokapAnnNy/J
 21Sn4dyGADnYxis5QBTu7r5sCF3rxAOBJ+2SrdOeYQ+gdJYlWxPSGL4X+87fYkOE
 3b5qR/8gzkGzDEG5PDnyiYgVCprUioE4WZiY7hKmcjGQBAy2q3NOgtz8m71PMI7v
 IdDapf85SeLZbO96CXpJBokUthb2HefFMJv0FWwF3uHV93kWSp8ge+VY
 =TWdX
 -----END PGP SIGNATURE-----

Merge tag 'linux-can-next-for-5.20-20220625' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next

Marc Kleine-Budde says:

====================
pull-request: can-next 2022-06-25

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

The first 2 patches target the xilinx driver. Srinivas Neeli's patch
adds Transmitter Delay Compensation (TDC) support, a patch by me fixes
a typo.

The next patch is by me and fixes a typo in the m_can driver.

Another patch by me allows the configuration of fixed bit rates
without need for do_set_bittiming callback.

The following 7 patches are by Vincent Mailhol and refactor the
can-dev module and Kbuild, de-inline the can_dropped_invalid_skb()
function, which has grown over the time, and drop outgoing skbs if the
controller is in listen only mode.

Max Staudt's patch fixes a reference in the networking/can.rst
documentation.

Vincent Mailhol provides 2 patches with cleanups for the etas_es58x
driver.

Conor Dooley adds bindings for the mpfs-can to the PolarFire SoC dtsi.

Another patch by me allows the configuration of fixed data bit rates
without need for do_set_data_bittiming callback.

The last 5 patches are by Frank Jungclaus. They prepare the esd_usb
driver to add support for the the CAN-USB/3 device in a later series.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2022-06-27 11:47:18 +01:00
commit 9dd094ee14
23 changed files with 616 additions and 436 deletions

View File

@ -0,0 +1,45 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/can/microchip,mpfs-can.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title:
Microchip PolarFire SoC (MPFS) can controller
maintainers:
- Conor Dooley <conor.dooley@microchip.com>
allOf:
- $ref: can-controller.yaml#
properties:
compatible:
const: microchip,mpfs-can
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
required:
- compatible
- reg
- interrupts
- clocks
additionalProperties: false
examples:
- |
can@2010c000 {
compatible = "microchip,mpfs-can";
reg = <0x2010c000 0x1000>;
clocks = <&clkcfg 17>;
interrupt-parent = <&plic>;
interrupts = <56>;
};

View File

@ -168,7 +168,7 @@ reflect the correct [#f1]_ traffic on the node the loopback of the sent
data has to be performed right after a successful transmission. If
the CAN network interface is not capable of performing the loopback for
some reason the SocketCAN core can do this task as a fallback solution.
See :ref:`socketcan-local-loopback1` for details (recommended).
See :ref:`socketcan-local-loopback2` for details (recommended).
The loopback functionality is enabled by default to reflect standard
networking behaviour for CAN applications. Due to some requests from

View File

@ -7420,6 +7420,13 @@ S: Maintained
F: include/linux/errseq.h
F: lib/errseq.c
ESD CAN/USB DRIVERS
M: Frank Jungclaus <frank.jungclaus@esd.eu>
R: socketcan@esd.eu
L: linux-can@vger.kernel.org
S: Maintained
F: drivers/net/can/usb/esd_usb.c
ET131X NETWORK DRIVER
M: Mark Einon <mark.einon@gmail.com>
S: Odd Fixes

View File

@ -339,6 +339,24 @@
status = "disabled";
};
can0: can@2010c000 {
compatible = "microchip,mpfs-can";
reg = <0x0 0x2010c000 0x0 0x1000>;
clocks = <&clkcfg CLK_CAN0>;
interrupt-parent = <&plic>;
interrupts = <56>;
status = "disabled";
};
can1: can@2010d000 {
compatible = "microchip,mpfs-can";
reg = <0x0 0x2010d000 0x0 0x1000>;
clocks = <&clkcfg CLK_CAN1>;
interrupt-parent = <&plic>;
interrupts = <57>;
status = "disabled";
};
mac0: ethernet@20110000 {
compatible = "cdns,macb";
reg = <0x0 0x20110000 0x0 0x2000>;

View File

@ -499,6 +499,8 @@ config NET_SB1000
source "drivers/net/phy/Kconfig"
source "drivers/net/can/Kconfig"
source "drivers/net/mctp/Kconfig"
source "drivers/net/mdio/Kconfig"

View File

@ -1,5 +1,26 @@
# SPDX-License-Identifier: GPL-2.0-only
menu "CAN Device Drivers"
menuconfig CAN_DEV
tristate "CAN Device Drivers"
default y
depends on CAN
help
Controller Area Network (CAN) is serial communications protocol up to
1Mbit/s for its original release (now known as Classical CAN) and up
to 8Mbit/s for the more recent CAN with Flexible Data-Rate
(CAN-FD). The CAN bus was originally mainly for automotive, but is now
widely used in marine (NMEA2000), industrial, and medical
applications. More information on the CAN network protocol family
PF_CAN is contained in <Documentation/networking/can.rst>.
This section contains all the CAN(-FD) device drivers including the
virtual ones. If you own such devices or plan to use the virtual CAN
interfaces to develop applications, say Y here.
To compile as a module, choose M here: the module will be called
can-dev.
if CAN_DEV
config CAN_VCAN
tristate "Virtual Local CAN Interface (vcan)"
@ -48,15 +69,22 @@ config CAN_SLCAN
can be changed by the 'maxdev=xx' module option. This driver can
also be built as a module. If so, the module will be called slcan.
config CAN_DEV
tristate "Platform CAN drivers with Netlink support"
config CAN_NETLINK
bool "CAN device drivers with Netlink support"
default y
help
Enables the common framework for platform CAN drivers with Netlink
support. This is the standard library for CAN drivers.
If unsure, say Y.
Enables the common framework for CAN device drivers. This is the
standard library and provides features for the Netlink interface such
as bittiming validation, support of CAN error states, device restart
and others.
if CAN_DEV
The additional features selected by this option will be added to the
can-dev module.
This is required by all platform and hardware CAN drivers. If you
plan to use such devices or if unsure, say Y.
if CAN_NETLINK
config CAN_CALC_BITTIMING
bool "CAN bit-timing calculation"
@ -69,8 +97,15 @@ config CAN_CALC_BITTIMING
source clock frequencies. Disabling saves some space, but then the
bit-timing parameters must be specified directly using the Netlink
arguments "tq", "prop_seg", "phase_seg1", "phase_seg2" and "sjw".
The additional features selected by this option will be added to the
can-dev module.
If unsure, say Y.
config CAN_RX_OFFLOAD
bool
config CAN_AT91
tristate "Atmel AT91 onchip CAN controller"
depends on (ARCH_AT91 || COMPILE_TEST) && HAS_IOMEM
@ -82,6 +117,7 @@ config CAN_FLEXCAN
tristate "Support for Freescale FLEXCAN based chips"
depends on OF || COLDFIRE || COMPILE_TEST
depends on HAS_IOMEM
select CAN_RX_OFFLOAD
help
Say Y here if you want to support for Freescale FlexCAN.
@ -131,6 +167,7 @@ config CAN_SUN4I
config CAN_TI_HECC
depends on ARM
tristate "TI High End CAN Controller"
select CAN_RX_OFFLOAD
help
Driver for TI HECC (High End CAN Controller) module found on many
TI devices. The device specifications are available from www.ti.com
@ -164,7 +201,7 @@ source "drivers/net/can/softing/Kconfig"
source "drivers/net/can/spi/Kconfig"
source "drivers/net/can/usb/Kconfig"
endif
endif #CAN_NETLINK
config CAN_DEBUG_DEVICES
bool "CAN devices debugging messages"
@ -174,4 +211,4 @@ config CAN_DEBUG_DEVICES
a problem with CAN support and want to see more of what is going
on.
endmenu
endif #CAN_DEV

View File

@ -1,9 +1,12 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_CAN_DEV) += can-dev.o
can-dev-y += bittiming.o
can-dev-y += dev.o
can-dev-y += length.o
can-dev-y += netlink.o
can-dev-y += rx-offload.o
can-dev-y += skb.o
obj-$(CONFIG_CAN_DEV) += can-dev.o
can-dev-y += skb.o
can-dev-$(CONFIG_CAN_CALC_BITTIMING) += calc_bittiming.o
can-dev-$(CONFIG_CAN_NETLINK) += bittiming.o
can-dev-$(CONFIG_CAN_NETLINK) += dev.o
can-dev-$(CONFIG_CAN_NETLINK) += length.o
can-dev-$(CONFIG_CAN_NETLINK) += netlink.o
can-dev-$(CONFIG_CAN_RX_OFFLOAD) += rx-offload.o

View File

@ -4,205 +4,8 @@
* Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
*/
#include <linux/units.h>
#include <linux/can/dev.h>
#ifdef CONFIG_CAN_CALC_BITTIMING
#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */
/* Bit-timing calculation derived from:
*
* Code based on LinCAN sources and H8S2638 project
* Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
* Copyright 2005 Stanislav Marek
* email: pisa@cmp.felk.cvut.cz
*
* Calculates proper bit-timing parameters for a specified bit-rate
* and sample-point, which can then be used to set the bit-timing
* registers of the CAN controller. You can find more information
* in the header file linux/can/netlink.h.
*/
static int
can_update_sample_point(const struct can_bittiming_const *btc,
const unsigned int sample_point_nominal, const unsigned int tseg,
unsigned int *tseg1_ptr, unsigned int *tseg2_ptr,
unsigned int *sample_point_error_ptr)
{
unsigned int sample_point_error, best_sample_point_error = UINT_MAX;
unsigned int sample_point, best_sample_point = 0;
unsigned int tseg1, tseg2;
int i;
for (i = 0; i <= 1; i++) {
tseg2 = tseg + CAN_SYNC_SEG -
(sample_point_nominal * (tseg + CAN_SYNC_SEG)) /
1000 - i;
tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max);
tseg1 = tseg - tseg2;
if (tseg1 > btc->tseg1_max) {
tseg1 = btc->tseg1_max;
tseg2 = tseg - tseg1;
}
sample_point = 1000 * (tseg + CAN_SYNC_SEG - tseg2) /
(tseg + CAN_SYNC_SEG);
sample_point_error = abs(sample_point_nominal - sample_point);
if (sample_point <= sample_point_nominal &&
sample_point_error < best_sample_point_error) {
best_sample_point = sample_point;
best_sample_point_error = sample_point_error;
*tseg1_ptr = tseg1;
*tseg2_ptr = tseg2;
}
}
if (sample_point_error_ptr)
*sample_point_error_ptr = best_sample_point_error;
return best_sample_point;
}
int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc)
{
struct can_priv *priv = netdev_priv(dev);
unsigned int bitrate; /* current bitrate */
unsigned int bitrate_error; /* difference between current and nominal value */
unsigned int best_bitrate_error = UINT_MAX;
unsigned int sample_point_error; /* difference between current and nominal value */
unsigned int best_sample_point_error = UINT_MAX;
unsigned int sample_point_nominal; /* nominal sample point */
unsigned int best_tseg = 0; /* current best value for tseg */
unsigned int best_brp = 0; /* current best value for brp */
unsigned int brp, tsegall, tseg, tseg1 = 0, tseg2 = 0;
u64 v64;
/* Use CiA recommended sample points */
if (bt->sample_point) {
sample_point_nominal = bt->sample_point;
} else {
if (bt->bitrate > 800 * KILO /* BPS */)
sample_point_nominal = 750;
else if (bt->bitrate > 500 * KILO /* BPS */)
sample_point_nominal = 800;
else
sample_point_nominal = 875;
}
/* tseg even = round down, odd = round up */
for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) {
tsegall = CAN_SYNC_SEG + tseg / 2;
/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2;
/* choose brp step which is possible in system */
brp = (brp / btc->brp_inc) * btc->brp_inc;
if (brp < btc->brp_min || brp > btc->brp_max)
continue;
bitrate = priv->clock.freq / (brp * tsegall);
bitrate_error = abs(bt->bitrate - bitrate);
/* tseg brp biterror */
if (bitrate_error > best_bitrate_error)
continue;
/* reset sample point error if we have a better bitrate */
if (bitrate_error < best_bitrate_error)
best_sample_point_error = UINT_MAX;
can_update_sample_point(btc, sample_point_nominal, tseg / 2,
&tseg1, &tseg2, &sample_point_error);
if (sample_point_error >= best_sample_point_error)
continue;
best_sample_point_error = sample_point_error;
best_bitrate_error = bitrate_error;
best_tseg = tseg / 2;
best_brp = brp;
if (bitrate_error == 0 && sample_point_error == 0)
break;
}
if (best_bitrate_error) {
/* Error in one-tenth of a percent */
v64 = (u64)best_bitrate_error * 1000;
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;
}
netdev_warn(dev, "bitrate error %d.%d%%\n",
bitrate_error / 10, bitrate_error % 10);
}
/* real sample point */
bt->sample_point = can_update_sample_point(btc, sample_point_nominal,
best_tseg, &tseg1, &tseg2,
NULL);
v64 = (u64)best_brp * 1000 * 1000 * 1000;
do_div(v64, priv->clock.freq);
bt->tq = (u32)v64;
bt->prop_seg = tseg1 / 2;
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;
}
bt->brp = best_brp;
/* real bitrate */
bt->bitrate = priv->clock.freq /
(bt->brp * (CAN_SYNC_SEG + tseg1 + tseg2));
return 0;
}
void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const,
const struct can_bittiming *dbt,
u32 *ctrlmode, u32 ctrlmode_supported)
{
if (!tdc_const || !(ctrlmode_supported & CAN_CTRLMODE_TDC_AUTO))
return;
*ctrlmode &= ~CAN_CTRLMODE_TDC_MASK;
/* As specified in ISO 11898-1 section 11.3.3 "Transmitter
* delay compensation" (TDC) is only applicable if data BRP is
* one or two.
*/
if (dbt->brp == 1 || dbt->brp == 2) {
/* Sample point in clock periods */
u32 sample_point_in_tc = (CAN_SYNC_SEG + dbt->prop_seg +
dbt->phase_seg1) * dbt->brp;
if (sample_point_in_tc < tdc_const->tdco_min)
return;
tdc->tdco = min(sample_point_in_tc, tdc_const->tdco_max);
*ctrlmode |= CAN_CTRLMODE_TDC_AUTO;
}
}
#endif /* CONFIG_CAN_CALC_BITTIMING */
/* 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

View File

@ -0,0 +1,202 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
* Copyright (C) 2006 Andrey Volkov, Varma Electronics
* Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
*/
#include <linux/units.h>
#include <linux/can/dev.h>
#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */
/* Bit-timing calculation derived from:
*
* Code based on LinCAN sources and H8S2638 project
* Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
* Copyright 2005 Stanislav Marek
* email: pisa@cmp.felk.cvut.cz
*
* Calculates proper bit-timing parameters for a specified bit-rate
* and sample-point, which can then be used to set the bit-timing
* registers of the CAN controller. You can find more information
* in the header file linux/can/netlink.h.
*/
static int
can_update_sample_point(const struct can_bittiming_const *btc,
const unsigned int sample_point_nominal, const unsigned int tseg,
unsigned int *tseg1_ptr, unsigned int *tseg2_ptr,
unsigned int *sample_point_error_ptr)
{
unsigned int sample_point_error, best_sample_point_error = UINT_MAX;
unsigned int sample_point, best_sample_point = 0;
unsigned int tseg1, tseg2;
int i;
for (i = 0; i <= 1; i++) {
tseg2 = tseg + CAN_SYNC_SEG -
(sample_point_nominal * (tseg + CAN_SYNC_SEG)) /
1000 - i;
tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max);
tseg1 = tseg - tseg2;
if (tseg1 > btc->tseg1_max) {
tseg1 = btc->tseg1_max;
tseg2 = tseg - tseg1;
}
sample_point = 1000 * (tseg + CAN_SYNC_SEG - tseg2) /
(tseg + CAN_SYNC_SEG);
sample_point_error = abs(sample_point_nominal - sample_point);
if (sample_point <= sample_point_nominal &&
sample_point_error < best_sample_point_error) {
best_sample_point = sample_point;
best_sample_point_error = sample_point_error;
*tseg1_ptr = tseg1;
*tseg2_ptr = tseg2;
}
}
if (sample_point_error_ptr)
*sample_point_error_ptr = best_sample_point_error;
return best_sample_point;
}
int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc)
{
struct can_priv *priv = netdev_priv(dev);
unsigned int bitrate; /* current bitrate */
unsigned int bitrate_error; /* difference between current and nominal value */
unsigned int best_bitrate_error = UINT_MAX;
unsigned int sample_point_error; /* difference between current and nominal value */
unsigned int best_sample_point_error = UINT_MAX;
unsigned int sample_point_nominal; /* nominal sample point */
unsigned int best_tseg = 0; /* current best value for tseg */
unsigned int best_brp = 0; /* current best value for brp */
unsigned int brp, tsegall, tseg, tseg1 = 0, tseg2 = 0;
u64 v64;
/* Use CiA recommended sample points */
if (bt->sample_point) {
sample_point_nominal = bt->sample_point;
} else {
if (bt->bitrate > 800 * KILO /* BPS */)
sample_point_nominal = 750;
else if (bt->bitrate > 500 * KILO /* BPS */)
sample_point_nominal = 800;
else
sample_point_nominal = 875;
}
/* tseg even = round down, odd = round up */
for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) {
tsegall = CAN_SYNC_SEG + tseg / 2;
/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2;
/* choose brp step which is possible in system */
brp = (brp / btc->brp_inc) * btc->brp_inc;
if (brp < btc->brp_min || brp > btc->brp_max)
continue;
bitrate = priv->clock.freq / (brp * tsegall);
bitrate_error = abs(bt->bitrate - bitrate);
/* tseg brp biterror */
if (bitrate_error > best_bitrate_error)
continue;
/* reset sample point error if we have a better bitrate */
if (bitrate_error < best_bitrate_error)
best_sample_point_error = UINT_MAX;
can_update_sample_point(btc, sample_point_nominal, tseg / 2,
&tseg1, &tseg2, &sample_point_error);
if (sample_point_error >= best_sample_point_error)
continue;
best_sample_point_error = sample_point_error;
best_bitrate_error = bitrate_error;
best_tseg = tseg / 2;
best_brp = brp;
if (bitrate_error == 0 && sample_point_error == 0)
break;
}
if (best_bitrate_error) {
/* Error in one-tenth of a percent */
v64 = (u64)best_bitrate_error * 1000;
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;
}
netdev_warn(dev, "bitrate error %d.%d%%\n",
bitrate_error / 10, bitrate_error % 10);
}
/* real sample point */
bt->sample_point = can_update_sample_point(btc, sample_point_nominal,
best_tseg, &tseg1, &tseg2,
NULL);
v64 = (u64)best_brp * 1000 * 1000 * 1000;
do_div(v64, priv->clock.freq);
bt->tq = (u32)v64;
bt->prop_seg = tseg1 / 2;
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;
}
bt->brp = best_brp;
/* real bitrate */
bt->bitrate = priv->clock.freq /
(bt->brp * (CAN_SYNC_SEG + tseg1 + tseg2));
return 0;
}
void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const,
const struct can_bittiming *dbt,
u32 *ctrlmode, u32 ctrlmode_supported)
{
if (!tdc_const || !(ctrlmode_supported & CAN_CTRLMODE_TDC_AUTO))
return;
*ctrlmode &= ~CAN_CTRLMODE_TDC_MASK;
/* As specified in ISO 11898-1 section 11.3.3 "Transmitter
* delay compensation" (TDC) is only applicable if data BRP is
* one or two.
*/
if (dbt->brp == 1 || dbt->brp == 2) {
/* Sample point in clock periods */
u32 sample_point_in_tc = (CAN_SYNC_SEG + dbt->prop_seg +
dbt->phase_seg1) * dbt->brp;
if (sample_point_in_tc < tdc_const->tdco_min)
return;
tdc->tdco = min(sample_point_in_tc, tdc_const->tdco_max);
*ctrlmode |= CAN_CTRLMODE_TDC_AUTO;
}
}

View File

@ -4,7 +4,6 @@
* Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
@ -17,12 +16,6 @@
#include <linux/gpio/consumer.h>
#include <linux/of.h>
#define MOD_DESC "CAN device driver interface"
MODULE_DESCRIPTION(MOD_DESC);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
static void can_update_state_error_stats(struct net_device *dev,
enum can_state new_state)
{
@ -513,7 +506,7 @@ static __init int can_dev_init(void)
err = can_netlink_register();
if (!err)
pr_info(MOD_DESC "\n");
pr_info("CAN device driver interface\n");
return err;
}

View File

@ -176,7 +176,8 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
* directly via do_set_bitrate(). Bail out if neither
* is given.
*/
if (!priv->bittiming_const && !priv->do_set_bittiming)
if (!priv->bittiming_const && !priv->do_set_bittiming &&
!priv->bitrate_const)
return -EOPNOTSUPP;
memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt));
@ -278,7 +279,8 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
* directly via do_set_bitrate(). Bail out if neither
* is given.
*/
if (!priv->data_bittiming_const && !priv->do_set_data_bittiming)
if (!priv->data_bittiming_const && !priv->do_set_data_bittiming &&
!priv->data_bitrate_const)
return -EOPNOTSUPP;
memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]),

View File

@ -5,6 +5,14 @@
*/
#include <linux/can/dev.h>
#include <linux/can/netlink.h>
#include <linux/module.h>
#define MOD_DESC "CAN device driver interface"
MODULE_DESCRIPTION(MOD_DESC);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
/* Local echo of CAN messages
*
@ -252,3 +260,67 @@ struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf)
return skb;
}
EXPORT_SYMBOL_GPL(alloc_can_err_skb);
/* Check for outgoing skbs that have not been created by the CAN subsystem */
static bool can_skb_headroom_valid(struct net_device *dev, struct sk_buff *skb)
{
/* af_packet creates a headroom of HH_DATA_MOD bytes which is fine */
if (WARN_ON_ONCE(skb_headroom(skb) < sizeof(struct can_skb_priv)))
return false;
/* af_packet does not apply CAN skb specific settings */
if (skb->ip_summed == CHECKSUM_NONE) {
/* init headroom */
can_skb_prv(skb)->ifindex = dev->ifindex;
can_skb_prv(skb)->skbcnt = 0;
skb->ip_summed = CHECKSUM_UNNECESSARY;
/* perform proper loopback on capable devices */
if (dev->flags & IFF_ECHO)
skb->pkt_type = PACKET_LOOPBACK;
else
skb->pkt_type = PACKET_HOST;
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
skb_reset_transport_header(skb);
}
return true;
}
/* Drop a given socketbuffer if it does not contain a valid CAN frame. */
bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
{
const struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
struct can_priv *priv = netdev_priv(dev);
if (skb->protocol == htons(ETH_P_CAN)) {
if (unlikely(skb->len != CAN_MTU ||
cfd->len > CAN_MAX_DLEN))
goto inval_skb;
} else if (skb->protocol == htons(ETH_P_CANFD)) {
if (unlikely(skb->len != CANFD_MTU ||
cfd->len > CANFD_MAX_DLEN))
goto inval_skb;
} else {
goto inval_skb;
}
if (!can_skb_headroom_valid(dev, skb)) {
goto inval_skb;
} else if (priv->ctrlmode & CAN_CTRLMODE_LISTENONLY) {
netdev_info_once(dev,
"interface in listen only mode, dropping skb\n");
goto inval_skb;
}
return false;
inval_skb:
kfree_skb(skb);
dev->stats.tx_dropped++;
return true;
}
EXPORT_SYMBOL_GPL(can_dropped_invalid_skb);

View File

@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
menuconfig CAN_M_CAN
tristate "Bosch M_CAN support"
select CAN_RX_OFFLOAD
help
Say Y here if you want support for Bosch M_CAN controller framework.
This is common support for devices that embed the Bosch M_CAN IP.

View File

@ -1348,8 +1348,8 @@ static void m_can_chip_config(struct net_device *dev)
/* set bittiming params */
m_can_set_bittiming(dev);
/* enable internal timestamp generation, with a prescalar of 16. The
* prescalar is applied to the nominal bit timing
/* enable internal timestamp generation, with a prescaler of 16. The
* prescaler is applied to the nominal bit timing
*/
m_can_write(cdev, M_CAN_TSCC, FIELD_PREP(TSCC_TCP_MASK, 0xf));

View File

@ -2,6 +2,7 @@
config CAN_MCP251XFD
tristate "Microchip MCP251xFD SPI CAN controllers"
select CAN_RX_OFFLOAD
select REGMAP
select WANT_DEV_COREDUMP
help

View File

@ -14,11 +14,18 @@ config CAN_EMS_USB
This driver is for the one channel CPC-USB/ARM7 CAN/USB interface
from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
config CAN_ESD_USB2
tristate "ESD USB/2 CAN/USB interface"
config CAN_ESD_USB
tristate "esd electronics gmbh CAN/USB interfaces"
help
This driver supports the CAN-USB/2 interface
from esd electronic system design gmbh (http://www.esd.eu).
This driver adds supports for several CAN/USB interfaces
from esd electronics gmbh (https://www.esd.eu).
The drivers supports the following devices:
- esd CAN-USB/2
- esd CAN-USB/Micro
To compile this driver as a module, choose M here: the module
will be called esd_usb.
config CAN_ETAS_ES58X
tristate "ETAS ES58X CAN/USB interfaces"

View File

@ -5,7 +5,7 @@
obj-$(CONFIG_CAN_8DEV_USB) += usb_8dev.o
obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o
obj-$(CONFIG_CAN_ESD_USB2) += esd_usb2.o
obj-$(CONFIG_CAN_ESD_USB) += esd_usb.o
obj-$(CONFIG_CAN_ETAS_ES58X) += etas_es58x/
obj-$(CONFIG_CAN_GS_USB) += gs_usb.o
obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb/

View File

@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* CAN driver for esd CAN-USB/2 and CAN-USB/Micro
* CAN driver for esd electronics gmbh CAN-USB/2 and CAN-USB/Micro
*
* Copyright (C) 2010-2012 Matthias Fuchs <matthias.fuchs@esd.eu>, esd gmbh
* Copyright (C) 2010-2012 esd electronic system design gmbh, Matthias Fuchs <socketcan@esd.eu>
* Copyright (C) 2022 esd electronics gmbh, Frank Jungclaus <frank.jungclaus@esd.eu>
*/
#include <linux/signal.h>
#include <linux/slab.h>
@ -14,20 +15,24 @@
#include <linux/can/dev.h>
#include <linux/can/error.h>
MODULE_AUTHOR("Matthias Fuchs <matthias.fuchs@esd.eu>");
MODULE_DESCRIPTION("CAN driver for esd CAN-USB/2 and CAN-USB/Micro interfaces");
MODULE_AUTHOR("Matthias Fuchs <socketcan@esd.eu>");
MODULE_AUTHOR("Frank Jungclaus <frank.jungclaus@esd.eu>");
MODULE_DESCRIPTION("CAN driver for esd electronics gmbh CAN-USB/2 and CAN-USB/Micro interfaces");
MODULE_LICENSE("GPL v2");
/* Define these values to match your devices */
/* USB vendor and product ID */
#define USB_ESDGMBH_VENDOR_ID 0x0ab4
#define USB_CANUSB2_PRODUCT_ID 0x0010
#define USB_CANUSBM_PRODUCT_ID 0x0011
/* CAN controller clock frequencies */
#define ESD_USB2_CAN_CLOCK 60000000
#define ESD_USBM_CAN_CLOCK 36000000
#define ESD_USB2_MAX_NETS 2
/* USB2 commands */
/* Maximum number of CAN nets */
#define ESD_USB_MAX_NETS 2
/* USB commands */
#define CMD_VERSION 1 /* also used for VERSION_REPLY */
#define CMD_CAN_RX 2 /* device to host only */
#define CMD_CAN_TX 3 /* also used for TX_DONE */
@ -43,13 +48,15 @@ MODULE_LICENSE("GPL v2");
#define ESD_EVENT 0x40000000
#define ESD_IDMASK 0x1fffffff
/* esd CAN event ids used by this driver */
#define ESD_EV_CAN_ERROR_EXT 2
/* esd CAN event ids */
#define ESD_EV_CAN_ERROR_EXT 2 /* CAN controller specific diagnostic data */
/* baudrate message flags */
#define ESD_USB2_UBR 0x80000000
#define ESD_USB2_LOM 0x40000000
#define ESD_USB2_NO_BAUDRATE 0x7fffffff
#define ESD_USB_UBR 0x80000000
#define ESD_USB_LOM 0x40000000
#define ESD_USB_NO_BAUDRATE 0x7fffffff
/* bit timing CAN-USB/2 */
#define ESD_USB2_TSEG1_MIN 1
#define ESD_USB2_TSEG1_MAX 16
#define ESD_USB2_TSEG1_SHIFT 16
@ -68,7 +75,7 @@ MODULE_LICENSE("GPL v2");
#define ESD_ID_ENABLE 0x80
#define ESD_MAX_ID_SEGMENT 64
/* SJA1000 ECC register (emulated by usb2 firmware) */
/* SJA1000 ECC register (emulated by usb firmware) */
#define SJA1000_ECC_SEG 0x1F
#define SJA1000_ECC_DIR 0x20
#define SJA1000_ECC_ERR 0x06
@ -158,7 +165,7 @@ struct set_baudrate_msg {
};
/* Main message type used between library and application */
struct __attribute__ ((packed)) esd_usb2_msg {
struct __packed esd_usb_msg {
union {
struct header_msg hdr;
struct version_msg version;
@ -171,23 +178,23 @@ struct __attribute__ ((packed)) esd_usb2_msg {
} msg;
};
static struct usb_device_id esd_usb2_table[] = {
static struct usb_device_id esd_usb_table[] = {
{USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSB2_PRODUCT_ID)},
{USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSBM_PRODUCT_ID)},
{}
};
MODULE_DEVICE_TABLE(usb, esd_usb2_table);
MODULE_DEVICE_TABLE(usb, esd_usb_table);
struct esd_usb2_net_priv;
struct esd_usb_net_priv;
struct esd_tx_urb_context {
struct esd_usb2_net_priv *priv;
struct esd_usb_net_priv *priv;
u32 echo_index;
};
struct esd_usb2 {
struct esd_usb {
struct usb_device *udev;
struct esd_usb2_net_priv *nets[ESD_USB2_MAX_NETS];
struct esd_usb_net_priv *nets[ESD_USB_MAX_NETS];
struct usb_anchor rx_submitted;
@ -198,22 +205,22 @@ struct esd_usb2 {
dma_addr_t rxbuf_dma[MAX_RX_URBS];
};
struct esd_usb2_net_priv {
struct esd_usb_net_priv {
struct can_priv can; /* must be the first member */
atomic_t active_tx_jobs;
struct usb_anchor tx_submitted;
struct esd_tx_urb_context tx_contexts[MAX_TX_URBS];
struct esd_usb2 *usb2;
struct esd_usb *usb;
struct net_device *netdev;
int index;
u8 old_state;
struct can_berr_counter bec;
};
static void esd_usb2_rx_event(struct esd_usb2_net_priv *priv,
struct esd_usb2_msg *msg)
static void esd_usb_rx_event(struct esd_usb_net_priv *priv,
struct esd_usb_msg *msg)
{
struct net_device_stats *stats = &priv->netdev->stats;
struct can_frame *cf;
@ -296,8 +303,8 @@ static void esd_usb2_rx_event(struct esd_usb2_net_priv *priv,
}
}
static void esd_usb2_rx_can_msg(struct esd_usb2_net_priv *priv,
struct esd_usb2_msg *msg)
static void esd_usb_rx_can_msg(struct esd_usb_net_priv *priv,
struct esd_usb_msg *msg)
{
struct net_device_stats *stats = &priv->netdev->stats;
struct can_frame *cf;
@ -311,7 +318,7 @@ static void esd_usb2_rx_can_msg(struct esd_usb2_net_priv *priv,
id = le32_to_cpu(msg->msg.rx.id);
if (id & ESD_EVENT) {
esd_usb2_rx_event(priv, msg);
esd_usb_rx_event(priv, msg);
} else {
skb = alloc_can_skb(priv->netdev, &cf);
if (skb == NULL) {
@ -338,12 +345,10 @@ static void esd_usb2_rx_can_msg(struct esd_usb2_net_priv *priv,
netif_rx(skb);
}
return;
}
static void esd_usb2_tx_done_msg(struct esd_usb2_net_priv *priv,
struct esd_usb2_msg *msg)
static void esd_usb_tx_done_msg(struct esd_usb_net_priv *priv,
struct esd_usb_msg *msg)
{
struct net_device_stats *stats = &priv->netdev->stats;
struct net_device *netdev = priv->netdev;
@ -370,9 +375,9 @@ static void esd_usb2_tx_done_msg(struct esd_usb2_net_priv *priv,
netif_wake_queue(netdev);
}
static void esd_usb2_read_bulk_callback(struct urb *urb)
static void esd_usb_read_bulk_callback(struct urb *urb)
{
struct esd_usb2 *dev = urb->context;
struct esd_usb *dev = urb->context;
int retval;
int pos = 0;
int i;
@ -394,9 +399,9 @@ static void esd_usb2_read_bulk_callback(struct urb *urb)
}
while (pos < urb->actual_length) {
struct esd_usb2_msg *msg;
struct esd_usb_msg *msg;
msg = (struct esd_usb2_msg *)(urb->transfer_buffer + pos);
msg = (struct esd_usb_msg *)(urb->transfer_buffer + pos);
switch (msg->msg.hdr.cmd) {
case CMD_CAN_RX:
@ -405,7 +410,7 @@ static void esd_usb2_read_bulk_callback(struct urb *urb)
break;
}
esd_usb2_rx_can_msg(dev->nets[msg->msg.rx.net], msg);
esd_usb_rx_can_msg(dev->nets[msg->msg.rx.net], msg);
break;
case CMD_CAN_TX:
@ -414,8 +419,8 @@ static void esd_usb2_read_bulk_callback(struct urb *urb)
break;
}
esd_usb2_tx_done_msg(dev->nets[msg->msg.txdone.net],
msg);
esd_usb_tx_done_msg(dev->nets[msg->msg.txdone.net],
msg);
break;
}
@ -430,7 +435,7 @@ static void esd_usb2_read_bulk_callback(struct urb *urb)
resubmit_urb:
usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
urb->transfer_buffer, RX_BUFFER_SIZE,
esd_usb2_read_bulk_callback, dev);
esd_usb_read_bulk_callback, dev);
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval == -ENODEV) {
@ -442,19 +447,15 @@ resubmit_urb:
dev_err(dev->udev->dev.parent,
"failed resubmitting read bulk urb: %d\n", retval);
}
return;
}
/*
* callback for bulk IN urb
*/
static void esd_usb2_write_bulk_callback(struct urb *urb)
/* callback for bulk IN urb */
static void esd_usb_write_bulk_callback(struct urb *urb)
{
struct esd_tx_urb_context *context = urb->context;
struct esd_usb2_net_priv *priv;
struct esd_usb_net_priv *priv;
struct net_device *netdev;
size_t size = sizeof(struct esd_usb2_msg);
size_t size = sizeof(struct esd_usb_msg);
WARN_ON(!context);
@ -478,7 +479,7 @@ static ssize_t firmware_show(struct device *d,
struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(d);
struct esd_usb2 *dev = usb_get_intfdata(intf);
struct esd_usb *dev = usb_get_intfdata(intf);
return sprintf(buf, "%d.%d.%d\n",
(dev->version >> 12) & 0xf,
@ -491,7 +492,7 @@ static ssize_t hardware_show(struct device *d,
struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(d);
struct esd_usb2 *dev = usb_get_intfdata(intf);
struct esd_usb *dev = usb_get_intfdata(intf);
return sprintf(buf, "%d.%d.%d\n",
(dev->version >> 28) & 0xf,
@ -504,13 +505,13 @@ static ssize_t nets_show(struct device *d,
struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(d);
struct esd_usb2 *dev = usb_get_intfdata(intf);
struct esd_usb *dev = usb_get_intfdata(intf);
return sprintf(buf, "%d", dev->net_count);
}
static DEVICE_ATTR_RO(nets);
static int esd_usb2_send_msg(struct esd_usb2 *dev, struct esd_usb2_msg *msg)
static int esd_usb_send_msg(struct esd_usb *dev, struct esd_usb_msg *msg)
{
int actual_length;
@ -522,8 +523,8 @@ static int esd_usb2_send_msg(struct esd_usb2 *dev, struct esd_usb2_msg *msg)
1000);
}
static int esd_usb2_wait_msg(struct esd_usb2 *dev,
struct esd_usb2_msg *msg)
static int esd_usb_wait_msg(struct esd_usb *dev,
struct esd_usb_msg *msg)
{
int actual_length;
@ -535,7 +536,7 @@ static int esd_usb2_wait_msg(struct esd_usb2 *dev,
1000);
}
static int esd_usb2_setup_rx_urbs(struct esd_usb2 *dev)
static int esd_usb_setup_rx_urbs(struct esd_usb *dev)
{
int i, err = 0;
@ -568,7 +569,7 @@ static int esd_usb2_setup_rx_urbs(struct esd_usb2 *dev)
usb_fill_bulk_urb(urb, dev->udev,
usb_rcvbulkpipe(dev->udev, 1),
buf, RX_BUFFER_SIZE,
esd_usb2_read_bulk_callback, dev);
esd_usb_read_bulk_callback, dev);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
usb_anchor_urb(urb, &dev->rx_submitted);
@ -606,14 +607,12 @@ freeurb:
return 0;
}
/*
* Start interface
*/
static int esd_usb2_start(struct esd_usb2_net_priv *priv)
/* Start interface */
static int esd_usb_start(struct esd_usb_net_priv *priv)
{
struct esd_usb2 *dev = priv->usb2;
struct esd_usb *dev = priv->usb;
struct net_device *netdev = priv->netdev;
struct esd_usb2_msg *msg;
struct esd_usb_msg *msg;
int err, i;
msg = kmalloc(sizeof(*msg), GFP_KERNEL);
@ -622,8 +621,7 @@ static int esd_usb2_start(struct esd_usb2_net_priv *priv)
goto out;
}
/*
* Enable all IDs
/* Enable all IDs
* The IDADD message takes up to 64 32 bit bitmasks (2048 bits).
* Each bit represents one 11 bit CAN identifier. A set bit
* enables reception of the corresponding CAN identifier. A cleared
@ -644,11 +642,11 @@ static int esd_usb2_start(struct esd_usb2_net_priv *priv)
/* enable 29bit extended IDs */
msg->msg.filter.mask[ESD_MAX_ID_SEGMENT] = cpu_to_le32(0x00000001);
err = esd_usb2_send_msg(dev, msg);
err = esd_usb_send_msg(dev, msg);
if (err)
goto out;
err = esd_usb2_setup_rx_urbs(dev);
err = esd_usb_setup_rx_urbs(dev);
if (err)
goto out;
@ -664,9 +662,9 @@ out:
return err;
}
static void unlink_all_urbs(struct esd_usb2 *dev)
static void unlink_all_urbs(struct esd_usb *dev)
{
struct esd_usb2_net_priv *priv;
struct esd_usb_net_priv *priv;
int i, j;
usb_kill_anchored_urbs(&dev->rx_submitted);
@ -687,9 +685,9 @@ static void unlink_all_urbs(struct esd_usb2 *dev)
}
}
static int esd_usb2_open(struct net_device *netdev)
static int esd_usb_open(struct net_device *netdev)
{
struct esd_usb2_net_priv *priv = netdev_priv(netdev);
struct esd_usb_net_priv *priv = netdev_priv(netdev);
int err;
/* common open */
@ -698,7 +696,7 @@ static int esd_usb2_open(struct net_device *netdev)
return err;
/* finally start device */
err = esd_usb2_start(priv);
err = esd_usb_start(priv);
if (err) {
netdev_warn(netdev, "couldn't start device: %d\n", err);
close_candev(netdev);
@ -710,20 +708,20 @@ static int esd_usb2_open(struct net_device *netdev)
return 0;
}
static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb,
static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb,
struct net_device *netdev)
{
struct esd_usb2_net_priv *priv = netdev_priv(netdev);
struct esd_usb2 *dev = priv->usb2;
struct esd_usb_net_priv *priv = netdev_priv(netdev);
struct esd_usb *dev = priv->usb;
struct esd_tx_urb_context *context = NULL;
struct net_device_stats *stats = &netdev->stats;
struct can_frame *cf = (struct can_frame *)skb->data;
struct esd_usb2_msg *msg;
struct esd_usb_msg *msg;
struct urb *urb;
u8 *buf;
int i, err;
int ret = NETDEV_TX_OK;
size_t size = sizeof(struct esd_usb2_msg);
size_t size = sizeof(struct esd_usb_msg);
if (can_dropped_invalid_skb(netdev, skb))
return NETDEV_TX_OK;
@ -745,7 +743,7 @@ static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb,
goto nobufmem;
}
msg = (struct esd_usb2_msg *)buf;
msg = (struct esd_usb_msg *)buf;
msg->msg.hdr.len = 3; /* minimal length */
msg->msg.hdr.cmd = CMD_CAN_TX;
@ -771,9 +769,7 @@ static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb,
}
}
/*
* This may never happen.
*/
/* This may never happen */
if (!context) {
netdev_warn(netdev, "couldn't find free context\n");
ret = NETDEV_TX_BUSY;
@ -788,7 +784,7 @@ static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb,
usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), buf,
msg->msg.hdr.len << 2,
esd_usb2_write_bulk_callback, context);
esd_usb_write_bulk_callback, context);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@ -821,8 +817,7 @@ static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb,
netif_trans_update(netdev);
/*
* Release our reference to this URB, the USB core will eventually free
/* Release our reference to this URB, the USB core will eventually free
* it entirely.
*/
usb_free_urb(urb);
@ -839,24 +834,24 @@ nourbmem:
return ret;
}
static int esd_usb2_close(struct net_device *netdev)
static int esd_usb_close(struct net_device *netdev)
{
struct esd_usb2_net_priv *priv = netdev_priv(netdev);
struct esd_usb2_msg *msg;
struct esd_usb_net_priv *priv = netdev_priv(netdev);
struct esd_usb_msg *msg;
int i;
msg = kmalloc(sizeof(*msg), GFP_KERNEL);
if (!msg)
return -ENOMEM;
/* Disable all IDs (see esd_usb2_start()) */
/* Disable all IDs (see esd_usb_start()) */
msg->msg.hdr.cmd = CMD_IDADD;
msg->msg.hdr.len = 2 + ESD_MAX_ID_SEGMENT;
msg->msg.filter.net = priv->index;
msg->msg.filter.option = ESD_ID_ENABLE; /* start with segment 0 */
for (i = 0; i <= ESD_MAX_ID_SEGMENT; i++)
msg->msg.filter.mask[i] = 0;
if (esd_usb2_send_msg(priv->usb2, msg) < 0)
if (esd_usb_send_msg(priv->usb, msg) < 0)
netdev_err(netdev, "sending idadd message failed\n");
/* set CAN controller to reset mode */
@ -864,8 +859,8 @@ static int esd_usb2_close(struct net_device *netdev)
msg->msg.hdr.cmd = CMD_SETBAUD;
msg->msg.setbaud.net = priv->index;
msg->msg.setbaud.rsvd = 0;
msg->msg.setbaud.baud = cpu_to_le32(ESD_USB2_NO_BAUDRATE);
if (esd_usb2_send_msg(priv->usb2, msg) < 0)
msg->msg.setbaud.baud = cpu_to_le32(ESD_USB_NO_BAUDRATE);
if (esd_usb_send_msg(priv->usb, msg) < 0)
netdev_err(netdev, "sending setbaud message failed\n");
priv->can.state = CAN_STATE_STOPPED;
@ -879,10 +874,10 @@ static int esd_usb2_close(struct net_device *netdev)
return 0;
}
static const struct net_device_ops esd_usb2_netdev_ops = {
.ndo_open = esd_usb2_open,
.ndo_stop = esd_usb2_close,
.ndo_start_xmit = esd_usb2_start_xmit,
static const struct net_device_ops esd_usb_netdev_ops = {
.ndo_open = esd_usb_open,
.ndo_stop = esd_usb_close,
.ndo_start_xmit = esd_usb_start_xmit,
.ndo_change_mtu = can_change_mtu,
};
@ -900,20 +895,20 @@ static const struct can_bittiming_const esd_usb2_bittiming_const = {
static int esd_usb2_set_bittiming(struct net_device *netdev)
{
struct esd_usb2_net_priv *priv = netdev_priv(netdev);
struct esd_usb_net_priv *priv = netdev_priv(netdev);
struct can_bittiming *bt = &priv->can.bittiming;
struct esd_usb2_msg *msg;
struct esd_usb_msg *msg;
int err;
u32 canbtr;
int sjw_shift;
canbtr = ESD_USB2_UBR;
canbtr = ESD_USB_UBR;
if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
canbtr |= ESD_USB2_LOM;
canbtr |= ESD_USB_LOM;
canbtr |= (bt->brp - 1) & (ESD_USB2_BRP_MAX - 1);
if (le16_to_cpu(priv->usb2->udev->descriptor.idProduct) ==
if (le16_to_cpu(priv->usb->udev->descriptor.idProduct) ==
USB_CANUSBM_PRODUCT_ID)
sjw_shift = ESD_USBM_SJW_SHIFT;
else
@ -941,16 +936,16 @@ static int esd_usb2_set_bittiming(struct net_device *netdev)
netdev_info(netdev, "setting BTR=%#x\n", canbtr);
err = esd_usb2_send_msg(priv->usb2, msg);
err = esd_usb_send_msg(priv->usb, msg);
kfree(msg);
return err;
}
static int esd_usb2_get_berr_counter(const struct net_device *netdev,
struct can_berr_counter *bec)
static int esd_usb_get_berr_counter(const struct net_device *netdev,
struct can_berr_counter *bec)
{
struct esd_usb2_net_priv *priv = netdev_priv(netdev);
struct esd_usb_net_priv *priv = netdev_priv(netdev);
bec->txerr = priv->bec.txerr;
bec->rxerr = priv->bec.rxerr;
@ -958,7 +953,7 @@ static int esd_usb2_get_berr_counter(const struct net_device *netdev,
return 0;
}
static int esd_usb2_set_mode(struct net_device *netdev, enum can_mode mode)
static int esd_usb_set_mode(struct net_device *netdev, enum can_mode mode)
{
switch (mode) {
case CAN_MODE_START:
@ -972,11 +967,11 @@ static int esd_usb2_set_mode(struct net_device *netdev, enum can_mode mode)
return 0;
}
static int esd_usb2_probe_one_net(struct usb_interface *intf, int index)
static int esd_usb_probe_one_net(struct usb_interface *intf, int index)
{
struct esd_usb2 *dev = usb_get_intfdata(intf);
struct esd_usb *dev = usb_get_intfdata(intf);
struct net_device *netdev;
struct esd_usb2_net_priv *priv;
struct esd_usb_net_priv *priv;
int err = 0;
int i;
@ -995,7 +990,7 @@ static int esd_usb2_probe_one_net(struct usb_interface *intf, int index)
for (i = 0; i < MAX_TX_URBS; i++)
priv->tx_contexts[i].echo_index = MAX_TX_URBS;
priv->usb2 = dev;
priv->usb = dev;
priv->netdev = netdev;
priv->index = index;
@ -1013,12 +1008,12 @@ static int esd_usb2_probe_one_net(struct usb_interface *intf, int index)
priv->can.bittiming_const = &esd_usb2_bittiming_const;
priv->can.do_set_bittiming = esd_usb2_set_bittiming;
priv->can.do_set_mode = esd_usb2_set_mode;
priv->can.do_get_berr_counter = esd_usb2_get_berr_counter;
priv->can.do_set_mode = esd_usb_set_mode;
priv->can.do_get_berr_counter = esd_usb_get_berr_counter;
netdev->flags |= IFF_ECHO; /* we support local echo */
netdev->netdev_ops = &esd_usb2_netdev_ops;
netdev->netdev_ops = &esd_usb_netdev_ops;
SET_NETDEV_DEV(netdev, &intf->dev);
netdev->dev_id = index;
@ -1038,17 +1033,16 @@ done:
return err;
}
/*
* probe function for new USB2 devices
/* probe function for new USB devices
*
* check version information and number of available
* CAN interfaces
*/
static int esd_usb2_probe(struct usb_interface *intf,
static int esd_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct esd_usb2 *dev;
struct esd_usb2_msg *msg;
struct esd_usb *dev;
struct esd_usb_msg *msg;
int i, err;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
@ -1076,13 +1070,13 @@ static int esd_usb2_probe(struct usb_interface *intf,
msg->msg.version.flags = 0;
msg->msg.version.drv_version = 0;
err = esd_usb2_send_msg(dev, msg);
err = esd_usb_send_msg(dev, msg);
if (err < 0) {
dev_err(&intf->dev, "sending version message failed\n");
goto free_msg;
}
err = esd_usb2_wait_msg(dev, msg);
err = esd_usb_wait_msg(dev, msg);
if (err < 0) {
dev_err(&intf->dev, "no version message answer\n");
goto free_msg;
@ -1105,7 +1099,7 @@ static int esd_usb2_probe(struct usb_interface *intf,
/* do per device probing */
for (i = 0; i < dev->net_count; i++)
esd_usb2_probe_one_net(intf, i);
esd_usb_probe_one_net(intf, i);
free_msg:
kfree(msg);
@ -1115,12 +1109,10 @@ done:
return err;
}
/*
* called by the usb core when the device is removed from the system
*/
static void esd_usb2_disconnect(struct usb_interface *intf)
/* called by the usb core when the device is removed from the system */
static void esd_usb_disconnect(struct usb_interface *intf)
{
struct esd_usb2 *dev = usb_get_intfdata(intf);
struct esd_usb *dev = usb_get_intfdata(intf);
struct net_device *netdev;
int i;
@ -1144,11 +1136,11 @@ static void esd_usb2_disconnect(struct usb_interface *intf)
}
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver esd_usb2_driver = {
.name = "esd_usb2",
.probe = esd_usb2_probe,
.disconnect = esd_usb2_disconnect,
.id_table = esd_usb2_table,
static struct usb_driver esd_usb_driver = {
.name = "esd_usb",
.probe = esd_usb_probe,
.disconnect = esd_usb_disconnect,
.id_table = esd_usb_table,
};
module_usb_driver(esd_usb2_driver);
module_usb_driver(esd_usb_driver);

View File

@ -1707,7 +1707,7 @@ static int es58x_alloc_rx_urbs(struct es58x_device *es58x_dev)
{
const struct device *dev = es58x_dev->dev;
const struct es58x_parameters *param = es58x_dev->param;
size_t rx_buf_len = es58x_dev->rx_max_packet_size;
u16 rx_buf_len = usb_maxpacket(es58x_dev->udev, es58x_dev->rx_pipe);
struct urb *urb;
u8 *buf;
int i;
@ -1739,7 +1739,7 @@ static int es58x_alloc_rx_urbs(struct es58x_device *es58x_dev)
dev_err(dev, "%s: Could not setup any rx URBs\n", __func__);
return ret;
}
dev_dbg(dev, "%s: Allocated %d rx URBs each of size %zu\n",
dev_dbg(dev, "%s: Allocated %d rx URBs each of size %u\n",
__func__, i, rx_buf_len);
return ret;
@ -2223,7 +2223,6 @@ static struct es58x_device *es58x_init_es58x_dev(struct usb_interface *intf,
ep_in->bEndpointAddress);
es58x_dev->tx_pipe = usb_sndbulkpipe(es58x_dev->udev,
ep_out->bEndpointAddress);
es58x_dev->rx_max_packet_size = le16_to_cpu(ep_in->wMaxPacketSize);
return es58x_dev;
}

View File

@ -380,7 +380,6 @@ struct es58x_operators {
* @timestamps: a temporary buffer to store the time stamps before
* feeding them to es58x_can_get_echo_skb(). Can only be used
* in RX branches.
* @rx_max_packet_size: Maximum length of bulk-in URB.
* @num_can_ch: Number of CAN channel (i.e. number of elements of @netdev).
* @opened_channel_cnt: number of channels opened. Free of race
* conditions because its two users (net_device_ops:ndo_open()
@ -401,8 +400,8 @@ struct es58x_device {
const struct es58x_parameters *param;
const struct es58x_operators *ops;
int rx_pipe;
int tx_pipe;
unsigned int rx_pipe;
unsigned int tx_pipe;
struct usb_anchor rx_urbs;
struct usb_anchor tx_urbs_busy;
@ -414,7 +413,6 @@ struct es58x_device {
u64 timestamps[ES58X_ECHO_BULK_MAX];
u16 rx_max_packet_size;
u8 num_can_ch;
u8 opened_channel_cnt;

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/* Xilinx CAN device driver
*
* Copyright (C) 2012 - 2014 Xilinx, Inc.
* Copyright (C) 2012 - 2022 Xilinx, Inc.
* Copyright (C) 2009 PetaLogix. All rights reserved.
* Copyright (C) 2017 - 2018 Sandvik Mining and Construction Oy
*
@ -9,6 +9,7 @@
* This driver is developed for Axi CAN IP and for Zynq CANPS Controller.
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/errno.h>
#include <linux/init.h>
@ -50,7 +51,7 @@ enum xcan_reg {
/* only on CAN FD cores */
XCAN_F_BRPR_OFFSET = 0x088, /* Data Phase Baud Rate
* Prescalar
* Prescaler
*/
XCAN_F_BTR_OFFSET = 0x08C, /* Data Phase Bit Timing */
XCAN_TRR_OFFSET = 0x0090, /* TX Buffer Ready Request */
@ -86,6 +87,8 @@ enum xcan_reg {
#define XCAN_MSR_LBACK_MASK 0x00000002 /* Loop back mode select */
#define XCAN_MSR_SLEEP_MASK 0x00000001 /* Sleep mode select */
#define XCAN_BRPR_BRP_MASK 0x000000FF /* Baud rate prescaler */
#define XCAN_BRPR_TDCO_MASK GENMASK(12, 8) /* TDCO */
#define XCAN_2_BRPR_TDCO_MASK GENMASK(13, 8) /* TDCO for CANFD 2.0 */
#define XCAN_BTR_SJW_MASK 0x00000180 /* Synchronous jump width */
#define XCAN_BTR_TS2_MASK 0x00000070 /* Time segment 2 */
#define XCAN_BTR_TS1_MASK 0x0000000F /* Time segment 1 */
@ -99,6 +102,7 @@ enum xcan_reg {
#define XCAN_ESR_STER_MASK 0x00000004 /* Stuff error */
#define XCAN_ESR_FMER_MASK 0x00000002 /* Form error */
#define XCAN_ESR_CRCER_MASK 0x00000001 /* CRC error */
#define XCAN_SR_TDCV_MASK GENMASK(22, 16) /* TDCV Value */
#define XCAN_SR_TXFLL_MASK 0x00000400 /* TX FIFO is full */
#define XCAN_SR_ESTAT_MASK 0x00000180 /* Error status */
#define XCAN_SR_ERRWRN_MASK 0x00000040 /* Error warning */
@ -132,6 +136,7 @@ enum xcan_reg {
#define XCAN_DLCR_BRS_MASK 0x04000000 /* BRS Mask in DLC */
/* CAN register bit shift - XCAN_<REG>_<BIT>_SHIFT */
#define XCAN_BRPR_TDC_ENABLE BIT(16) /* Transmitter Delay Compensation (TDC) Enable */
#define XCAN_BTR_SJW_SHIFT 7 /* Synchronous jump width */
#define XCAN_BTR_TS2_SHIFT 4 /* Time segment 2 */
#define XCAN_BTR_SJW_SHIFT_CANFD 16 /* Synchronous jump width */
@ -276,6 +281,26 @@ static const struct can_bittiming_const xcan_data_bittiming_const_canfd2 = {
.brp_inc = 1,
};
/* Transmission Delay Compensation constants for CANFD 1.0 */
static const struct can_tdc_const xcan_tdc_const_canfd = {
.tdcv_min = 0,
.tdcv_max = 0, /* Manual mode not supported. */
.tdco_min = 0,
.tdco_max = 32,
.tdcf_min = 0, /* Filter window not supported */
.tdcf_max = 0,
};
/* Transmission Delay Compensation constants for CANFD 2.0 */
static const struct can_tdc_const xcan_tdc_const_canfd2 = {
.tdcv_min = 0,
.tdcv_max = 0, /* Manual mode not supported. */
.tdco_min = 0,
.tdco_max = 64,
.tdcf_min = 0, /* Filter window not supported */
.tdcf_max = 0,
};
/**
* xcan_write_reg_le - Write a value to the device register little endian
* @priv: Driver private data structure
@ -405,7 +430,7 @@ static int xcan_set_bittiming(struct net_device *ndev)
return -EPERM;
}
/* Setting Baud Rate prescalar value in BRPR Register */
/* Setting Baud Rate prescaler value in BRPR Register */
btr0 = (bt->brp - 1);
/* Setting Time Segment 1 in BTR Register */
@ -422,8 +447,16 @@ static int xcan_set_bittiming(struct net_device *ndev)
if (priv->devtype.cantype == XAXI_CANFD ||
priv->devtype.cantype == XAXI_CANFD_2_0) {
/* Setting Baud Rate prescalar value in F_BRPR Register */
/* Setting Baud Rate prescaler value in F_BRPR Register */
btr0 = dbt->brp - 1;
if (can_tdc_is_enabled(&priv->can)) {
if (priv->devtype.cantype == XAXI_CANFD)
btr0 |= FIELD_PREP(XCAN_BRPR_TDCO_MASK, priv->can.tdc.tdco) |
XCAN_BRPR_TDC_ENABLE;
else
btr0 |= FIELD_PREP(XCAN_2_BRPR_TDCO_MASK, priv->can.tdc.tdco) |
XCAN_BRPR_TDC_ENABLE;
}
/* Setting Time Segment 1 in BTR Register */
btr1 = dbt->prop_seg + dbt->phase_seg1 - 1;
@ -1483,6 +1516,22 @@ static int xcan_get_berr_counter(const struct net_device *ndev,
return 0;
}
/**
* xcan_get_auto_tdcv - Get Transmitter Delay Compensation Value
* @ndev: Pointer to net_device structure
* @tdcv: Pointer to TDCV value
*
* Return: 0 on success
*/
static int xcan_get_auto_tdcv(const struct net_device *ndev, u32 *tdcv)
{
struct xcan_priv *priv = netdev_priv(ndev);
*tdcv = FIELD_GET(XCAN_SR_TDCV_MASK, priv->read_reg(priv, XCAN_SR_OFFSET));
return 0;
}
static const struct net_device_ops xcan_netdev_ops = {
.ndo_open = xcan_open,
.ndo_stop = xcan_close,
@ -1735,17 +1784,24 @@ static int xcan_probe(struct platform_device *pdev)
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
CAN_CTRLMODE_BERR_REPORTING;
if (devtype->cantype == XAXI_CANFD)
if (devtype->cantype == XAXI_CANFD) {
priv->can.data_bittiming_const =
&xcan_data_bittiming_const_canfd;
priv->can.tdc_const = &xcan_tdc_const_canfd;
}
if (devtype->cantype == XAXI_CANFD_2_0)
if (devtype->cantype == XAXI_CANFD_2_0) {
priv->can.data_bittiming_const =
&xcan_data_bittiming_const_canfd2;
priv->can.tdc_const = &xcan_tdc_const_canfd2;
}
if (devtype->cantype == XAXI_CANFD ||
devtype->cantype == XAXI_CANFD_2_0)
priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
devtype->cantype == XAXI_CANFD_2_0) {
priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD |
CAN_CTRLMODE_TDC_AUTO;
priv->can.do_get_auto_tdcv = xcan_get_auto_tdcv;
}
priv->reg_base = addr;
priv->tx_max = tx_max;

View File

@ -31,6 +31,7 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev,
struct canfd_frame **cfd);
struct sk_buff *alloc_can_err_skb(struct net_device *dev,
struct can_frame **cf);
bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb);
/*
* The struct can_skb_priv is used to transport additional information along
@ -96,64 +97,6 @@ static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb)
return nskb;
}
/* Check for outgoing skbs that have not been created by the CAN subsystem */
static inline bool can_skb_headroom_valid(struct net_device *dev,
struct sk_buff *skb)
{
/* af_packet creates a headroom of HH_DATA_MOD bytes which is fine */
if (WARN_ON_ONCE(skb_headroom(skb) < sizeof(struct can_skb_priv)))
return false;
/* af_packet does not apply CAN skb specific settings */
if (skb->ip_summed == CHECKSUM_NONE) {
/* init headroom */
can_skb_prv(skb)->ifindex = dev->ifindex;
can_skb_prv(skb)->skbcnt = 0;
skb->ip_summed = CHECKSUM_UNNECESSARY;
/* perform proper loopback on capable devices */
if (dev->flags & IFF_ECHO)
skb->pkt_type = PACKET_LOOPBACK;
else
skb->pkt_type = PACKET_HOST;
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
skb_reset_transport_header(skb);
}
return true;
}
/* Drop a given socketbuffer if it does not contain a valid CAN frame. */
static inline bool can_dropped_invalid_skb(struct net_device *dev,
struct sk_buff *skb)
{
const struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
if (skb->protocol == htons(ETH_P_CAN)) {
if (unlikely(skb->len != CAN_MTU ||
cfd->len > CAN_MAX_DLEN))
goto inval_skb;
} else if (skb->protocol == htons(ETH_P_CANFD)) {
if (unlikely(skb->len != CANFD_MTU ||
cfd->len > CANFD_MAX_DLEN))
goto inval_skb;
} else
goto inval_skb;
if (!can_skb_headroom_valid(dev, skb))
goto inval_skb;
return false;
inval_skb:
kfree_skb(skb);
dev->stats.tx_dropped++;
return true;
}
static inline bool can_is_canfd_skb(const struct sk_buff *skb)
{
/* the CAN specific type of skb is identified by its data length */

View File

@ -15,7 +15,8 @@ menuconfig CAN
PF_CAN is contained in <Documentation/networking/can.rst>.
If you want CAN support you should say Y here and also to the
specific driver for your controller(s) below.
specific driver for your controller(s) under the Network device
support section.
if CAN
@ -69,6 +70,4 @@ config CAN_ISOTP
If you want to perform automotive vehicle diagnostic services (UDS),
say 'y'.
source "drivers/net/can/Kconfig"
endif