From 8c07fb0d647772018e0562fc4e920e081efb4c80 Mon Sep 17 00:00:00 2001 From: John Watts Date: Sat, 22 Jul 2023 08:15:50 +1000 Subject: [PATCH 01/21] dt-bindings: net: can: Add support for Allwinner D1 CAN controller The Allwinner D1 has two CAN controllers, both a variant of the R40 controller. Unfortunately the registers for the D1 controllers are moved around enough to be incompatible and require a new compatible. Introduce the "allwinner,sun20i-d1-can" compatible to support this. Signed-off-by: John Watts Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/all/20230721221552.1973203-3-contact@jookia.org Signed-off-by: Marc Kleine-Budde --- .../bindings/net/can/allwinner,sun4i-a10-can.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/net/can/allwinner,sun4i-a10-can.yaml b/Documentation/devicetree/bindings/net/can/allwinner,sun4i-a10-can.yaml index 9c494957a07a..e42ea28d6ab4 100644 --- a/Documentation/devicetree/bindings/net/can/allwinner,sun4i-a10-can.yaml +++ b/Documentation/devicetree/bindings/net/can/allwinner,sun4i-a10-can.yaml @@ -21,6 +21,7 @@ properties: - const: allwinner,sun4i-a10-can - const: allwinner,sun4i-a10-can - const: allwinner,sun8i-r40-can + - const: allwinner,sun20i-d1-can reg: maxItems: 1 @@ -37,8 +38,9 @@ properties: if: properties: compatible: - contains: - const: allwinner,sun8i-r40-can + enum: + - allwinner,sun8i-r40-can + - allwinner,sun20i-d1-can then: required: From 6ea1ad888f5900953a21853e709fa499fdfcb317 Mon Sep 17 00:00:00 2001 From: John Watts Date: Sat, 22 Jul 2023 08:15:51 +1000 Subject: [PATCH 02/21] riscv: dts: allwinner: d1: Add CAN controller nodes The Allwinner D1, T113 provide two CAN controllers that are variants of the R40 controller. I have tested support for these controllers on two boards: - A Lichee Panel RV 86 Panel running a D1 chip - A Mango Pi MQ Dual running a T113-s3 chip Both of these fully support both CAN controllers. Signed-off-by: John Watts Link: https://lore.kernel.org/all/20230721221552.1973203-4-contact@jookia.org Signed-off-by: Marc Kleine-Budde --- .../boot/dts/allwinner/sunxi-d1s-t113.dtsi | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi b/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi index 1bb1e5cae602..4086c0cc0f9d 100644 --- a/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi +++ b/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi @@ -131,6 +131,18 @@ pins = "PB6", "PB7"; function = "uart3"; }; + + /omit-if-no-ref/ + can0_pins: can0-pins { + pins = "PB2", "PB3"; + function = "can0"; + }; + + /omit-if-no-ref/ + can1_pins: can1-pins { + pins = "PB4", "PB5"; + function = "can1"; + }; }; ccu: clock-controller@2001000 { @@ -879,5 +891,23 @@ clock-names = "bus", "hosc", "ahb"; #clock-cells = <1>; }; + + can0: can@2504000 { + compatible = "allwinner,sun20i-d1-can"; + reg = <0x02504000 0x400>; + interrupts = ; + clocks = <&ccu CLK_BUS_CAN0>; + resets = <&ccu RST_BUS_CAN0>; + status = "disabled"; + }; + + can1: can@2504400 { + compatible = "allwinner,sun20i-d1-can"; + reg = <0x02504400 0x400>; + interrupts = ; + clocks = <&ccu CLK_BUS_CAN1>; + resets = <&ccu RST_BUS_CAN1>; + status = "disabled"; + }; }; }; From 8cda0c6dfd42ee6f2586e7dffb553aaf1fcb62ca Mon Sep 17 00:00:00 2001 From: John Watts Date: Sat, 22 Jul 2023 08:15:52 +1000 Subject: [PATCH 03/21] can: sun4i_can: Add acceptance register quirk The Allwinner D1's CAN controllers have the ACPC and ACPM registers moved down. Compensate for this by adding an offset quirk for the acceptance registers. Signed-off-by: John Watts Link: https://lore.kernel.org/all/20230721221552.1973203-5-contact@jookia.org Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sun4i_can.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index 0827830bbf28..1f90fe6dbb8b 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -205,9 +205,11 @@ * struct sun4ican_quirks - Differences between SoC variants. * * @has_reset: SoC needs reset deasserted. + * @acp_offset: Offset of ACPC and ACPM registers */ struct sun4ican_quirks { bool has_reset; + int acp_offset; }; struct sun4ican_priv { @@ -216,6 +218,7 @@ struct sun4ican_priv { struct clk *clk; struct reset_control *reset; spinlock_t cmdreg_lock; /* lock for concurrent cmd register writes */ + int acp_offset; }; static const struct can_bittiming_const sun4ican_bittiming_const = { @@ -338,8 +341,8 @@ static int sun4i_can_start(struct net_device *dev) } /* set filters - we accept all */ - writel(0x00000000, priv->base + SUN4I_REG_ACPC_ADDR); - writel(0xFFFFFFFF, priv->base + SUN4I_REG_ACPM_ADDR); + writel(0x00000000, priv->base + SUN4I_REG_ACPC_ADDR + priv->acp_offset); + writel(0xFFFFFFFF, priv->base + SUN4I_REG_ACPM_ADDR + priv->acp_offset); /* clear error counters and error code capture */ writel(0, priv->base + SUN4I_REG_ERRC_ADDR); @@ -768,10 +771,12 @@ static const struct ethtool_ops sun4ican_ethtool_ops = { static const struct sun4ican_quirks sun4ican_quirks_a10 = { .has_reset = false, + .acp_offset = 0, }; static const struct sun4ican_quirks sun4ican_quirks_r40 = { .has_reset = true, + .acp_offset = 0, }; static const struct of_device_id sun4ican_of_match[] = { @@ -870,6 +875,7 @@ static int sun4ican_probe(struct platform_device *pdev) priv->base = addr; priv->clk = clk; priv->reset = reset; + priv->acp_offset = quirks->acp_offset; spin_lock_init(&priv->cmdreg_lock); platform_set_drvdata(pdev, dev); From e58ee933c27a2ddd587752788dd843817008313f Mon Sep 17 00:00:00 2001 From: Gerhard Uttenthaler Date: Thu, 20 Jul 2023 16:40:32 +0200 Subject: [PATCH 04/21] MAINTAINERS: Add myself as maintainer of the ems_pci.c driver At the suggestion of Marc Kleine-Budde [1], I add myself as maintainer of the ems_pci.c driver. [1] https://lore.kernel.org/all/20230720-purplish-quizzical-247024e66671-mkl@pengutronix.de Signed-off-by: Gerhard Uttenthaler Link: https://lore.kernel.org/all/20230720144032.28960-1-uttenthaler@ems-wuensche.com Signed-off-by: Marc Kleine-Budde --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 24eb7ed6211f..c4f95a9d03b9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7606,6 +7606,13 @@ L: linux-mmc@vger.kernel.org S: Supported F: drivers/mmc/host/cqhci* +EMS CPC-PCI CAN DRIVER +M: Gerhard Uttenthaler +M: support@ems-wuensche.com +L: linux-can@vger.kernel.org +S: Maintained +F: drivers/net/can/sja1000/ems_pci.c + EMULEX 10Gbps iSCSI - OneConnect DRIVER M: Ketan Mukadam L: linux-scsi@vger.kernel.org From 8abb95250ae6af2d51993da8fcae18da2ce24cc4 Mon Sep 17 00:00:00 2001 From: John Watts Date: Sat, 22 Jul 2023 08:15:53 +1000 Subject: [PATCH 05/21] can: sun4i_can: Add support for the Allwinner D1 The controllers present in the D1 are extremely similar to the R40 and require the same reset quirks, but An extra quirk is needed to support receiving packets. Signed-off-by: John Watts Link: https://lore.kernel.org/all/20230721221552.1973203-6-contact@jookia.org Signed-off-by: Marc Kleine-Budde --- drivers/net/can/Kconfig | 4 ++-- drivers/net/can/sun4i_can.c | 12 +++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 18e4a6e94ba9..649453a3c858 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -190,10 +190,10 @@ config CAN_SLCAN config CAN_SUN4I tristate "Allwinner A10 CAN controller" - depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST + depends on MACH_SUN4I || MACH_SUN7I || RISCV || COMPILE_TEST help Say Y here if you want to use CAN controller found on Allwinner - A10/A20 SoCs. + A10/A20/D1 SoCs. To compile this driver as a module, choose M here: the module will be called sun4i_can. diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index 1f90fe6dbb8b..c508a328e38d 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -91,6 +91,8 @@ #define SUN4I_REG_BUF12_ADDR 0x0070 /* CAN Tx/Rx Buffer 12 */ #define SUN4I_REG_ACPC_ADDR 0x0040 /* CAN Acceptance Code 0 */ #define SUN4I_REG_ACPM_ADDR 0x0044 /* CAN Acceptance Mask 0 */ +#define SUN4I_REG_ACPC_ADDR_D1 0x0028 /* CAN Acceptance Code 0 on the D1 */ +#define SUN4I_REG_ACPM_ADDR_D1 0x002C /* CAN Acceptance Mask 0 on the D1 */ #define SUN4I_REG_RBUF_RBACK_START_ADDR 0x0180 /* CAN transmit buffer start */ #define SUN4I_REG_RBUF_RBACK_END_ADDR 0x01b0 /* CAN transmit buffer end */ @@ -779,6 +781,11 @@ static const struct sun4ican_quirks sun4ican_quirks_r40 = { .acp_offset = 0, }; +static const struct sun4ican_quirks sun4ican_quirks_d1 = { + .has_reset = true, + .acp_offset = (SUN4I_REG_ACPC_ADDR_D1 - SUN4I_REG_ACPC_ADDR), +}; + static const struct of_device_id sun4ican_of_match[] = { { .compatible = "allwinner,sun4i-a10-can", @@ -789,6 +796,9 @@ static const struct of_device_id sun4ican_of_match[] = { }, { .compatible = "allwinner,sun8i-r40-can", .data = &sun4ican_quirks_r40 + }, { + .compatible = "allwinner,sun20i-d1-can", + .data = &sun4ican_quirks_d1 }, { /* sentinel */ }, @@ -913,4 +923,4 @@ module_platform_driver(sun4i_can_driver); MODULE_AUTHOR("Peter Chen "); MODULE_AUTHOR("Gerhard Bertelsmann "); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_DESCRIPTION("CAN driver for Allwinner SoCs (A10/A20)"); +MODULE_DESCRIPTION("CAN driver for Allwinner SoCs (A10/A20/D1)"); From 74dedbd74d2bfac24b44acb268ea77faa9fc9c41 Mon Sep 17 00:00:00 2001 From: Peter Seiderer Date: Fri, 21 Jul 2023 20:07:58 +0200 Subject: [PATCH 06/21] can: peak_usb: remove unused/legacy peak_usb_netif_rx() function Remove unused/legacy peak_usb_netif_rx() function (not longer used since commit 28e0a70cede3 ("can: peak_usb: CANFD: store 64-bits hw timestamps"). Signed-off-by: Peter Seiderer Link: https://lore.kernel.org/all/20230721180758.26199-1-ps.report@gmx.net Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/peak_usb/pcan_usb_core.c | 13 ------------- drivers/net/can/usb/peak_usb/pcan_usb_core.h | 2 -- 2 files changed, 15 deletions(-) diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c index d881e1d30183..24ad9f593a77 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -214,19 +214,6 @@ void peak_usb_get_ts_time(struct peak_time_ref *time_ref, u32 ts, ktime_t *time) } } -/* - * post received skb after having set any hw timestamp - */ -int peak_usb_netif_rx(struct sk_buff *skb, - struct peak_time_ref *time_ref, u32 ts_low) -{ - struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb); - - peak_usb_get_ts_time(time_ref, ts_low, &hwts->hwtstamp); - - return netif_rx(skb); -} - /* post received skb with native 64-bit hw timestamp */ int peak_usb_netif_rx_64(struct sk_buff *skb, u32 ts_low, u32 ts_high) { diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.h b/drivers/net/can/usb/peak_usb/pcan_usb_core.h index 980e315186cf..f6cf84bb718f 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.h +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.h @@ -142,8 +142,6 @@ void peak_usb_init_time_ref(struct peak_time_ref *time_ref, void peak_usb_update_ts_now(struct peak_time_ref *time_ref, u32 ts_now); void peak_usb_set_ts_now(struct peak_time_ref *time_ref, u32 ts_now); void peak_usb_get_ts_time(struct peak_time_ref *time_ref, u32 ts, ktime_t *tv); -int peak_usb_netif_rx(struct sk_buff *skb, - struct peak_time_ref *time_ref, u32 ts_low); int peak_usb_netif_rx_64(struct sk_buff *skb, u32 ts_low, u32 ts_high); void peak_usb_async_complete(struct urb *urb); void peak_usb_restart_complete(struct peak_usb_device *dev); From 07382e6b68a742f18d57a27fec5fd0c2b0b61b40 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 24 Jul 2023 15:18:40 -0600 Subject: [PATCH 07/21] can: Explicitly include correct DT includes, part 2 The DT of_device.h and of_platform.h date back to the separate of_platform_bus_type before it as merged into the regular platform bus. As part of that merge prepping Arm DT support 13 years ago, they "temporarily" include each other. They also include platform_device.h and of.h. As a result, there's a pretty much random mix of those include files used throughout the tree. In order to detangle these headers and replace the implicit includes with struct declarations, users need to explicitly include the correct includes. Signed-off-by: Rob Herring Link: https://lore.kernel.org/all/20230724211841.805053-1-robh@kernel.org Signed-off-by: Marc Kleine-Budde --- drivers/net/can/bxcan.c | 1 - drivers/net/can/ifi_canfd/ifi_canfd.c | 1 - drivers/net/can/m_can/m_can.c | 1 - drivers/net/can/m_can/m_can.h | 1 - drivers/net/can/rcar/rcar_canfd.c | 1 - drivers/net/can/sja1000/sja1000_platform.c | 1 - drivers/net/can/sun4i_can.c | 1 - drivers/net/can/ti_hecc.c | 1 - 8 files changed, 8 deletions(-) diff --git a/drivers/net/can/bxcan.c b/drivers/net/can/bxcan.c index 39de7164bc4e..49cf9682b925 100644 --- a/drivers/net/can/bxcan.c +++ b/drivers/net/can/bxcan.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c index 1d6642c94f2f..72307297d75e 100644 --- a/drivers/net/can/ifi_canfd/ifi_canfd.c +++ b/drivers/net/can/ifi_canfd/ifi_canfd.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index 13fd84b2e2dd..a6263a617ac9 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h index 2ac18ac867a4..c543928c756f 100644 --- a/drivers/net/can/m_can/m_can.h +++ b/drivers/net/can/m_can/m_can.h @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c index e4d748913439..b82842718735 100644 --- a/drivers/net/can/rcar/rcar_canfd.c +++ b/drivers/net/can/rcar/rcar_canfd.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c index 4e59952c66d4..33f0e46ab1c2 100644 --- a/drivers/net/can/sja1000/sja1000_platform.c +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -17,7 +17,6 @@ #include #include #include -#include #include "sja1000.h" diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index c508a328e38d..ab8d01784686 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -59,7 +59,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 54284661992e..a8243acde92d 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include From f1a14714bf48f87fa8e774f415ea9815daf3750d Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 18 Jul 2023 11:11:22 +0200 Subject: [PATCH 08/21] can: gs_usb: remove leading space from goto labels Remove leading spaces from goto labels in accordance with the kernel encoding style. Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-1-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index bd9eb066ecf1..c604377138fd 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -645,7 +645,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) netif_rx(skb); } - resubmit_urb: +resubmit_urb: usb_fill_bulk_urb(urb, usbcan->udev, usb_rcvbulkpipe(usbcan->udev, GS_USB_ENDPOINT_IN), hf, dev->parent->hf_size_rx, @@ -655,7 +655,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) /* USB failure take down all interfaces */ if (rc == -ENODEV) { - device_detach: +device_detach: for (rc = 0; rc < GS_MAX_INTF; rc++) { if (usbcan->canch[rc]) netif_device_detach(usbcan->canch[rc]->netdev); @@ -818,12 +818,12 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; - badidx: +badidx: kfree(hf); - nomem_hf: +nomem_hf: usb_free_urb(urb); - nomem_urb: +nomem_urb: gs_free_tx_context(txc); dev_kfree_skb(skb); stats->tx_dropped++; @@ -1354,7 +1354,7 @@ static struct gs_can *gs_make_candev(unsigned int channel, return dev; - out_free_candev: +out_free_candev: free_candev(dev->netdev); return ERR_PTR(rc); } From 5780148bedd6aa7e51d3a18cd70f5b9b6cefb79e Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 6 Jul 2023 13:08:43 +0200 Subject: [PATCH 09/21] can: gs_usb: gs_usb_probe(): align block comment Indent block comment so that it aligns the * on each line. Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-2-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index c604377138fd..966e00ea768d 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -1443,8 +1443,8 @@ static int gs_usb_probe(struct usb_interface *intf, dev->canch[i]->parent = dev; /* set RX packet size based on FD and if hardware - * timestamps are supported. - */ + * timestamps are supported. + */ if (dev->canch[i]->can.ctrlmode_supported & CAN_CTRLMODE_FD) { if (dev->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP) hf_size_rx = struct_size(hf, canfd_ts, 1); From a2002f455c0e1f1c8802e7bdafe370d47d4328de Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 6 Jul 2023 13:04:45 +0200 Subject: [PATCH 10/21] can: gs_usb: gs_usb_set_timestamp(): remove return statements form void function Remove the return statements from void gs_usb_set_timestamp() function, as it's not generally useful. Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-3-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 966e00ea768d..1e08d38b0f96 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -520,8 +520,6 @@ static void gs_usb_set_timestamp(struct gs_can *dev, struct sk_buff *skb, timestamp = le32_to_cpu(hf->classic_can_ts->timestamp_us); gs_usb_skb_set_timestamp(dev, skb, timestamp); - - return; } static void gs_usb_receive_bulk_callback(struct urb *urb) From b6980ad3a90c73c95cab97e9a33129b8f53e2a5b Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 6 Jul 2023 16:16:33 +0200 Subject: [PATCH 11/21] can: gs_usb: uniformly use "parent" as variable name for struct gs_usb To ease readability and maintainability uniformly use the variable name "parent" for the struct gs_usb in the gs_usb driver. Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-4-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 62 ++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 1e08d38b0f96..441143ad740b 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -524,7 +524,7 @@ static void gs_usb_set_timestamp(struct gs_can *dev, struct sk_buff *skb, static void gs_usb_receive_bulk_callback(struct urb *urb) { - struct gs_usb *usbcan = urb->context; + struct gs_usb *parent = urb->context; struct gs_can *dev; struct net_device *netdev; int rc; @@ -535,7 +535,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) struct canfd_frame *cfd; struct sk_buff *skb; - BUG_ON(!usbcan); + BUG_ON(!parent); switch (urb->status) { case 0: /* success */ @@ -552,7 +552,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) if (hf->channel >= GS_MAX_INTF) goto device_detach; - dev = usbcan->canch[hf->channel]; + dev = parent->canch[hf->channel]; netdev = dev->netdev; stats = &netdev->stats; @@ -644,10 +644,10 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) } resubmit_urb: - usb_fill_bulk_urb(urb, usbcan->udev, - usb_rcvbulkpipe(usbcan->udev, GS_USB_ENDPOINT_IN), + usb_fill_bulk_urb(urb, parent->udev, + usb_rcvbulkpipe(parent->udev, GS_USB_ENDPOINT_IN), hf, dev->parent->hf_size_rx, - gs_usb_receive_bulk_callback, usbcan); + gs_usb_receive_bulk_callback, parent); rc = usb_submit_urb(urb, GFP_ATOMIC); @@ -655,8 +655,8 @@ resubmit_urb: if (rc == -ENODEV) { device_detach: for (rc = 0; rc < GS_MAX_INTF; rc++) { - if (usbcan->canch[rc]) - netif_device_detach(usbcan->canch[rc]->netdev); + if (parent->canch[rc]) + netif_device_detach(parent->canch[rc]->netdev); } } } @@ -1369,7 +1369,7 @@ static int gs_usb_probe(struct usb_interface *intf, { struct usb_device *udev = interface_to_usbdev(intf); struct gs_host_frame *hf; - struct gs_usb *dev; + struct gs_usb *parent; struct gs_host_config hconf = { .byte_order = cpu_to_le32(0x0000beef), }; @@ -1412,49 +1412,49 @@ static int gs_usb_probe(struct usb_interface *intf, return -EINVAL; } - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) + parent = kzalloc(sizeof(*parent), GFP_KERNEL); + if (!parent) return -ENOMEM; - init_usb_anchor(&dev->rx_submitted); + init_usb_anchor(&parent->rx_submitted); - usb_set_intfdata(intf, dev); - dev->udev = udev; + usb_set_intfdata(intf, parent); + parent->udev = udev; for (i = 0; i < icount; i++) { unsigned int hf_size_rx = 0; - dev->canch[i] = gs_make_candev(i, intf, &dconf); - if (IS_ERR_OR_NULL(dev->canch[i])) { + parent->canch[i] = gs_make_candev(i, intf, &dconf); + if (IS_ERR_OR_NULL(parent->canch[i])) { /* save error code to return later */ - rc = PTR_ERR(dev->canch[i]); + rc = PTR_ERR(parent->canch[i]); /* on failure destroy previously created candevs */ icount = i; for (i = 0; i < icount; i++) - gs_destroy_candev(dev->canch[i]); + gs_destroy_candev(parent->canch[i]); - usb_kill_anchored_urbs(&dev->rx_submitted); - kfree(dev); + usb_kill_anchored_urbs(&parent->rx_submitted); + kfree(parent); return rc; } - dev->canch[i]->parent = dev; + parent->canch[i]->parent = parent; /* set RX packet size based on FD and if hardware * timestamps are supported. */ - if (dev->canch[i]->can.ctrlmode_supported & CAN_CTRLMODE_FD) { - if (dev->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP) + if (parent->canch[i]->can.ctrlmode_supported & CAN_CTRLMODE_FD) { + if (parent->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP) hf_size_rx = struct_size(hf, canfd_ts, 1); else hf_size_rx = struct_size(hf, canfd, 1); } else { - if (dev->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP) + if (parent->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP) hf_size_rx = struct_size(hf, classic_can_ts, 1); else hf_size_rx = struct_size(hf, classic_can, 1); } - dev->hf_size_rx = max(dev->hf_size_rx, hf_size_rx); + parent->hf_size_rx = max(parent->hf_size_rx, hf_size_rx); } return 0; @@ -1462,22 +1462,22 @@ static int gs_usb_probe(struct usb_interface *intf, static void gs_usb_disconnect(struct usb_interface *intf) { - struct gs_usb *dev = usb_get_intfdata(intf); + struct gs_usb *parent = usb_get_intfdata(intf); unsigned int i; usb_set_intfdata(intf, NULL); - if (!dev) { + if (!parent) { dev_err(&intf->dev, "Disconnect (nodata)\n"); return; } for (i = 0; i < GS_MAX_INTF; i++) - if (dev->canch[i]) - gs_destroy_candev(dev->canch[i]); + if (parent->canch[i]) + gs_destroy_candev(parent->canch[i]); - usb_kill_anchored_urbs(&dev->rx_submitted); - kfree(dev); + usb_kill_anchored_urbs(&parent->rx_submitted); + kfree(parent); } static const struct usb_device_id gs_usb_table[] = { From fcb880ef2f55b9d50baf42c7efa5c45a9baabea9 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 3 Jul 2023 20:37:20 +0200 Subject: [PATCH 12/21] can: gs_usb: gs_usb_receive_bulk_callback(): make use of netdev Make use the previously assigned variable netdev instead of using dev->netdev. Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-5-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 441143ad740b..04cbe949c290 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -565,7 +565,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) if (hf->echo_id == -1) { /* normal rx */ if (hf->flags & GS_CAN_FLAG_FD) { - skb = alloc_canfd_skb(dev->netdev, &cfd); + skb = alloc_canfd_skb(netdev, &cfd); if (!skb) return; @@ -578,7 +578,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) memcpy(cfd->data, hf->canfd->data, cfd->len); } else { - skb = alloc_can_skb(dev->netdev, &cf); + skb = alloc_can_skb(netdev, &cf); if (!skb) return; From 55ad95d944251bb53df958e408964be2499603fd Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 3 Jul 2023 20:39:19 +0200 Subject: [PATCH 13/21] can: gs_usb: gs_usb_receive_bulk_callback(): make use of stats Make use the previously assigned variable stats instead of using netdev->stats. Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-6-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 04cbe949c290..0d0a3405ba19 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -594,8 +594,8 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) gs_usb_set_timestamp(dev, skb, hf); - netdev->stats.rx_packets++; - netdev->stats.rx_bytes += hf->can_dlc; + stats->rx_packets++; + stats->rx_bytes += hf->can_dlc; netif_rx(skb); } else { /* echo_id == hf->echo_id */ @@ -619,9 +619,9 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) skb = dev->can.echo_skb[hf->echo_id]; gs_usb_set_timestamp(dev, skb, hf); - netdev->stats.tx_packets++; - netdev->stats.tx_bytes += can_get_echo_skb(netdev, hf->echo_id, - NULL); + stats->tx_packets++; + stats->tx_bytes += can_get_echo_skb(netdev, hf->echo_id, + NULL); gs_free_tx_context(txc); From 6c8bc15f02b85bc8f47074110d8fd8caf7a1e42d Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 4 Jul 2023 11:23:37 +0200 Subject: [PATCH 14/21] can: gs_usb: gs_usb_receive_bulk_callback(): count RX overflow errors also in case of OOM In case of an RX overflow error from the CAN controller and an OOM where no skb can be allocated, the error counters are not incremented. Fix this by first incrementing the error counters and then allocate the skb. Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices") Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-7-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 0d0a3405ba19..e302d7d568aa 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -631,6 +631,9 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) } if (hf->flags & GS_CAN_FLAG_OVERFLOW) { + stats->rx_over_errors++; + stats->rx_errors++; + skb = alloc_can_err_skb(netdev, &cf); if (!skb) goto resubmit_urb; @@ -638,8 +641,6 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) cf->can_id |= CAN_ERR_CRTL; cf->len = CAN_ERR_DLC; cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; - stats->rx_over_errors++; - stats->rx_errors++; netif_rx(skb); } From 1494ffe4cbe0f97af9c57a4cc37131c8efbe79fc Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 12 Jul 2023 15:49:43 +0200 Subject: [PATCH 15/21] can: gs_usb: gs_can_start_xmit(), gs_can_open(): clean up printouts in error path Remove unnecessary "out of memory" message from the error path of gs_can_start_xmit() and gs_can_open(). Convert the printout in case of a failing usb_submit_urb() in gs_can_open() from numbers to human readable error codes. Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-8-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index e302d7d568aa..a5cab6a07002 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -741,10 +741,8 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, goto nomem_urb; hf = kmalloc(dev->hf_size_tx, GFP_ATOMIC); - if (!hf) { - netdev_err(netdev, "No memory left for USB buffer\n"); + if (!hf) goto nomem_hf; - } idx = txc->echo_id; @@ -877,8 +875,6 @@ static int gs_can_open(struct net_device *netdev) buf = kmalloc(dev->parent->hf_size_rx, GFP_KERNEL); if (!buf) { - netdev_err(netdev, - "No memory left for USB buffer\n"); rc = -ENOMEM; goto out_usb_free_urb; } @@ -901,7 +897,8 @@ static int gs_can_open(struct net_device *netdev) netif_device_detach(dev->netdev); netdev_err(netdev, - "usb_submit failed (err=%d)\n", rc); + "usb_submit_urb() failed, error %pe\n", + ERR_PTR(rc)); goto out_usb_unanchor_urb; } From 5c6c313acdfc3455b20ac1dc9655aa4afcf51ab1 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 8 Feb 2023 10:26:33 +0100 Subject: [PATCH 16/21] can: gs_usb: gs_can_close(): don't complain about failed device reset during ndo_stop When the USB device is unplugged, gs_can_close() (which implements the struct net_device_ops::ndo_stop callback) is called. In this function an attempt is made to shut down the USB device with a USB control message. For disconnected devices this will fail and a warning message is printed. Silence the driver by removing the printout of the error message if the reset command fails. Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-9-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index a5cab6a07002..7718f6a4367e 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -1029,9 +1029,7 @@ static int gs_can_close(struct net_device *netdev) dev->can.state = CAN_STATE_STOPPED; /* reset the device */ - rc = gs_cmd_reset(dev); - if (rc < 0) - netdev_warn(netdev, "Couldn't shutdown device (err=%d)", rc); + gs_cmd_reset(dev); /* reset tx contexts */ for (rc = 0; rc < GS_MAX_TX_URBS; rc++) { From 5391e0cbae02cdf2df501f104c2c7dc0bceeec3d Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 6 Jul 2023 11:38:25 +0200 Subject: [PATCH 17/21] can: gs_usb: gs_destroy_candev(): remove not needed usb_kill_anchored_urbs() In gs_destroy_candev(), the netdev is unregistered first, then all anchored TX URBs (dev->tx_submitted) are disposed with usb_kill_anchored_urbs(). The call to usb_kill_anchored_urbs() is not needed, as unregister_candev() calls gs_can_close(), which already disposes the TX URBS. Remove not needed call to usb_kill_anchored_urbs() from gs_destroy_candev(). Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-10-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 7718f6a4367e..5a0017b98532 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -1356,7 +1356,6 @@ out_free_candev: static void gs_destroy_candev(struct gs_can *dev) { unregister_candev(dev->netdev); - usb_kill_anchored_urbs(&dev->tx_submitted); free_candev(dev->netdev); } From d4cfb83d566c56d062a73d94a9fc7ec258a437c2 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 6 Jul 2023 11:38:25 +0200 Subject: [PATCH 18/21] can: gs_usb: gs_usb_disconnect(): remove not needed usb_kill_anchored_urbs() In gs_usb_disconnect(), all channels are destroyed first, then all anchored RX URBs (parent->rx_submitted) are disposed with usb_kill_anchored_urbs(). The call to usb_kill_anchored_urbs() is not needed, as gs_destroy_candev() of the last active channel already disposes the RX URBS. Remove not needed call to usb_kill_anchored_urbs() from gs_usb_disconnect(). Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-11-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 5a0017b98532..6caf3974e028 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -1471,7 +1471,6 @@ static void gs_usb_disconnect(struct usb_interface *intf) if (parent->canch[i]) gs_destroy_candev(parent->canch[i]); - usb_kill_anchored_urbs(&parent->rx_submitted); kfree(parent); } From 2e3df4a3b3178006d530f4c4d0e91f3d96cddb3c Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 2 Jun 2023 09:36:38 +0200 Subject: [PATCH 19/21] can: rx-offload: rename rx_offload_get_echo_skb() -> can_rx_offload_get_echo_skb_queue_timestamp() Rename the rx_offload_get_echo_skb() function to can_rx_offload_get_echo_skb_queue_timestamp(), since it inserts the echo skb into the rx-offload queue sorted by timestamp. This is a preparation for adding can_rx_offload_get_echo_skb_queue_tail(), which adds the echo skb to the end of the queue. This is intended for devices that do not support timestamps. Link: https://lore.kernel.org/all/20230718-gs_usb-rx-offload-v2-1-716e542d14d5@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/dev/rx-offload.c | 9 +++++---- drivers/net/can/flexcan/flexcan-core.c | 4 ++-- drivers/net/can/m_can/m_can.c | 8 ++++---- drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c | 6 +++--- drivers/net/can/ti_hecc.c | 4 ++-- include/linux/can/rx-offload.h | 6 +++--- 6 files changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c index 161e45a7e8c1..6e87ad908346 100644 --- a/drivers/net/can/dev/rx-offload.c +++ b/drivers/net/can/dev/rx-offload.c @@ -240,9 +240,10 @@ int can_rx_offload_queue_timestamp(struct can_rx_offload *offload, } EXPORT_SYMBOL_GPL(can_rx_offload_queue_timestamp); -unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload, - unsigned int idx, u32 timestamp, - unsigned int *frame_len_ptr) +unsigned int +can_rx_offload_get_echo_skb_queue_timestamp(struct can_rx_offload *offload, + unsigned int idx, u32 timestamp, + unsigned int *frame_len_ptr) { struct net_device *dev = offload->dev; struct net_device_stats *stats = &dev->stats; @@ -262,7 +263,7 @@ unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload, return len; } -EXPORT_SYMBOL_GPL(can_rx_offload_get_echo_skb); +EXPORT_SYMBOL_GPL(can_rx_offload_get_echo_skb_queue_timestamp); int can_rx_offload_queue_tail(struct can_rx_offload *offload, struct sk_buff *skb) diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c index ff0fc18baf13..48273d51f271 100644 --- a/drivers/net/can/flexcan/flexcan-core.c +++ b/drivers/net/can/flexcan/flexcan-core.c @@ -1097,8 +1097,8 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) handled = IRQ_HANDLED; stats->tx_bytes += - can_rx_offload_get_echo_skb(&priv->offload, 0, - reg_ctrl << 16, NULL); + can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload, 0, + reg_ctrl << 16, NULL); stats->tx_packets++; /* after sending a RTR frame MB is in RX mode */ diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index a6263a617ac9..d204703521d2 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -1016,10 +1016,10 @@ static void m_can_tx_update_stats(struct m_can_classdev *cdev, if (cdev->is_peripheral) stats->tx_bytes += - can_rx_offload_get_echo_skb(&cdev->offload, - msg_mark, - timestamp, - NULL); + can_rx_offload_get_echo_skb_queue_timestamp(&cdev->offload, + msg_mark, + timestamp, + NULL); else stats->tx_bytes += can_get_echo_skb(dev, msg_mark, NULL); diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c index 237617b0c125..e5bd57b65aaf 100644 --- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c +++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c @@ -111,9 +111,9 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv, if (skb) mcp251xfd_skb_set_timestamp(priv, skb, hw_tef_obj->ts); stats->tx_bytes += - can_rx_offload_get_echo_skb(&priv->offload, - tef_tail, hw_tef_obj->ts, - frame_len_ptr); + can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload, + tef_tail, hw_tef_obj->ts, + frame_len_ptr); stats->tx_packets++; priv->tef->tail++; diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index a8243acde92d..5aab440074c6 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -747,8 +747,8 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id) spin_unlock_irqrestore(&priv->mbx_lock, flags); stamp = hecc_read_stamp(priv, mbxno); stats->tx_bytes += - can_rx_offload_get_echo_skb(&priv->offload, - mbxno, stamp, NULL); + can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload, + mbxno, stamp, NULL); stats->tx_packets++; --priv->tx_tail; } diff --git a/include/linux/can/rx-offload.h b/include/linux/can/rx-offload.h index c205c51d79c9..e3b4199732c6 100644 --- a/include/linux/can/rx-offload.h +++ b/include/linux/can/rx-offload.h @@ -44,9 +44,9 @@ int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload, int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload); int can_rx_offload_queue_timestamp(struct can_rx_offload *offload, struct sk_buff *skb, u32 timestamp); -unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload, - unsigned int idx, u32 timestamp, - unsigned int *frame_len_ptr); +unsigned int can_rx_offload_get_echo_skb_queue_timestamp(struct can_rx_offload *offload, + unsigned int idx, u32 timestamp, + unsigned int *frame_len_ptr); int can_rx_offload_queue_tail(struct can_rx_offload *offload, struct sk_buff *skb); void can_rx_offload_irq_finish(struct can_rx_offload *offload); From 8e0e2950c9ef48f7f40a7175048744ec2390b16e Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 3 Jul 2023 18:18:19 +0200 Subject: [PATCH 20/21] can: rx-offload: add can_rx_offload_get_echo_skb_queue_tail() Add can_rx_offload_get_echo_skb_queue_tail(). This function addds the echo skb at the end of rx-offload the queue. This is intended for devices without timestamp support. Link: https://lore.kernel.org/all/20230718-gs_usb-rx-offload-v2-2-716e542d14d5@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/dev/rx-offload.c | 27 ++++++++++++++++++++++++++- include/linux/can/rx-offload.h | 5 ++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c index 6e87ad908346..77091f7d1fa7 100644 --- a/drivers/net/can/dev/rx-offload.c +++ b/drivers/net/can/dev/rx-offload.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2014 Protonic Holland, * David Jander - * Copyright (C) 2014-2021 Pengutronix, + * Copyright (C) 2014-2021, 2023 Pengutronix, * Marc Kleine-Budde */ @@ -280,6 +280,31 @@ int can_rx_offload_queue_tail(struct can_rx_offload *offload, } EXPORT_SYMBOL_GPL(can_rx_offload_queue_tail); +unsigned int +can_rx_offload_get_echo_skb_queue_tail(struct can_rx_offload *offload, + unsigned int idx, + unsigned int *frame_len_ptr) +{ + struct net_device *dev = offload->dev; + struct net_device_stats *stats = &dev->stats; + struct sk_buff *skb; + unsigned int len; + int err; + + skb = __can_get_echo_skb(dev, idx, &len, frame_len_ptr); + if (!skb) + return 0; + + err = can_rx_offload_queue_tail(offload, skb); + if (err) { + stats->rx_errors++; + stats->tx_fifo_errors++; + } + + return len; +} +EXPORT_SYMBOL_GPL(can_rx_offload_get_echo_skb_queue_tail); + void can_rx_offload_irq_finish(struct can_rx_offload *offload) { unsigned long flags; diff --git a/include/linux/can/rx-offload.h b/include/linux/can/rx-offload.h index e3b4199732c6..d29bb4521947 100644 --- a/include/linux/can/rx-offload.h +++ b/include/linux/can/rx-offload.h @@ -3,7 +3,7 @@ * linux/can/rx-offload.h * * Copyright (c) 2014 David Jander, Protonic Holland - * Copyright (c) 2014-2017 Pengutronix, Marc Kleine-Budde + * Copyright (c) 2014-2017, 2023 Pengutronix, Marc Kleine-Budde */ #ifndef _CAN_RX_OFFLOAD_H @@ -49,6 +49,9 @@ unsigned int can_rx_offload_get_echo_skb_queue_timestamp(struct can_rx_offload * unsigned int *frame_len_ptr); int can_rx_offload_queue_tail(struct can_rx_offload *offload, struct sk_buff *skb); +unsigned int can_rx_offload_get_echo_skb_queue_tail(struct can_rx_offload *offload, + unsigned int idx, + unsigned int *frame_len_ptr); void can_rx_offload_irq_finish(struct can_rx_offload *offload); void can_rx_offload_threaded_irq_finish(struct can_rx_offload *offload); void can_rx_offload_del(struct can_rx_offload *offload); From 24bc41b4558347672a3db61009c339b1f5692169 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 2 Jun 2023 09:29:07 +0200 Subject: [PATCH 21/21] can: gs_usb: convert to NAPI/rx-offload to avoid OoO reception The driver used to pass received CAN frames/skbs to the network stack with netif_rx(). In netif_rx() the skbs are queued to the local CPU. If IRQs are handled in round robin, OoO packets may occur. To avoid out-of-order reception convert the driver from netif_rx() to NAPI. For USB devices with timestamping support use the rx-offload helper can_rx_offload_queue_timestamp() for the RX, and can_rx_offload_get_echo_skb_queue_timestamp() for the TX path. Devices without timestamping support use can_rx_offload_queue_tail() for RX, and can_rx_offload_get_echo_skb_queue_tail() for the TX path. Link: https://lore.kernel.org/all/559D628C.5020100@hartkopp.net Link: https://github.com/candle-usb/candleLight_fw/issues/166 Link: https://lore.kernel.org/all/20230718-gs_usb-rx-offload-v2-3-716e542d14d5@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/Kconfig | 1 + drivers/net/can/usb/gs_usb.c | 85 ++++++++++++++++++++++++++++-------- 2 files changed, 67 insertions(+), 19 deletions(-) diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig index 58fcd2b34820..d1450722cb3c 100644 --- a/drivers/net/can/usb/Kconfig +++ b/drivers/net/can/usb/Kconfig @@ -52,6 +52,7 @@ config CAN_F81604 config CAN_GS_USB tristate "Geschwister Schneider UG and candleLight compatible interfaces" + select CAN_RX_OFFLOAD help This driver supports the Geschwister Schneider and bytewerk.org candleLight compatible diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 6caf3974e028..95b0fdb602c8 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -5,6 +5,7 @@ * Copyright (C) 2013-2016 Geschwister Schneider Technologie-, * Entwicklungs- und Vertriebs UG (Haftungsbeschränkt). * Copyright (C) 2016 Hubert Denkmair + * Copyright (c) 2023 Pengutronix, Marc Kleine-Budde * * Many thanks to all socketcan devs! */ @@ -24,6 +25,7 @@ #include #include #include +#include /* Device specific constants */ #define USB_GS_USB_1_VENDOR_ID 0x1d50 @@ -282,6 +284,8 @@ struct gs_host_frame { #define GS_MAX_TX_URBS 10 /* Only launch a max of GS_MAX_RX_URBS usb requests at a time. */ #define GS_MAX_RX_URBS 30 +#define GS_NAPI_WEIGHT 32 + /* Maximum number of interfaces the driver supports per device. * Current hardware only supports 3 interfaces. The future may vary. */ @@ -295,6 +299,7 @@ struct gs_tx_context { struct gs_can { struct can_priv can; /* must be the first member */ + struct can_rx_offload offload; struct gs_usb *parent; struct net_device *netdev; @@ -506,20 +511,59 @@ static void gs_update_state(struct gs_can *dev, struct can_frame *cf) } } -static void gs_usb_set_timestamp(struct gs_can *dev, struct sk_buff *skb, - const struct gs_host_frame *hf) +static u32 gs_usb_set_timestamp(struct gs_can *dev, struct sk_buff *skb, + const struct gs_host_frame *hf) { u32 timestamp; - if (!(dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)) - return; - if (hf->flags & GS_CAN_FLAG_FD) timestamp = le32_to_cpu(hf->canfd_ts->timestamp_us); else timestamp = le32_to_cpu(hf->classic_can_ts->timestamp_us); - gs_usb_skb_set_timestamp(dev, skb, timestamp); + if (skb) + gs_usb_skb_set_timestamp(dev, skb, timestamp); + + return timestamp; +} + +static void gs_usb_rx_offload(struct gs_can *dev, struct sk_buff *skb, + const struct gs_host_frame *hf) +{ + struct can_rx_offload *offload = &dev->offload; + int rc; + + if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) { + const u32 ts = gs_usb_set_timestamp(dev, skb, hf); + + rc = can_rx_offload_queue_timestamp(offload, skb, ts); + } else { + rc = can_rx_offload_queue_tail(offload, skb); + } + + if (rc) + dev->netdev->stats.rx_fifo_errors++; +} + +static unsigned int +gs_usb_get_echo_skb(struct gs_can *dev, struct sk_buff *skb, + const struct gs_host_frame *hf) +{ + struct can_rx_offload *offload = &dev->offload; + const u32 echo_id = hf->echo_id; + unsigned int len; + + if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) { + const u32 ts = gs_usb_set_timestamp(dev, skb, hf); + + len = can_rx_offload_get_echo_skb_queue_timestamp(offload, echo_id, + ts, NULL); + } else { + len = can_rx_offload_get_echo_skb_queue_tail(offload, echo_id, + NULL); + } + + return len; } static void gs_usb_receive_bulk_callback(struct urb *urb) @@ -592,12 +636,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) gs_update_state(dev, cf); } - gs_usb_set_timestamp(dev, skb, hf); - - stats->rx_packets++; - stats->rx_bytes += hf->can_dlc; - - netif_rx(skb); + gs_usb_rx_offload(dev, skb, hf); } else { /* echo_id == hf->echo_id */ if (hf->echo_id >= GS_MAX_TX_URBS) { netdev_err(netdev, @@ -617,12 +656,8 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) } skb = dev->can.echo_skb[hf->echo_id]; - gs_usb_set_timestamp(dev, skb, hf); - stats->tx_packets++; - stats->tx_bytes += can_get_echo_skb(netdev, hf->echo_id, - NULL); - + stats->tx_bytes += gs_usb_get_echo_skb(dev, skb, hf); gs_free_tx_context(txc); atomic_dec(&dev->active_tx_urbs); @@ -641,9 +676,12 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) cf->can_id |= CAN_ERR_CRTL; cf->len = CAN_ERR_DLC; cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; - netif_rx(skb); + + gs_usb_rx_offload(dev, skb, hf); } + can_rx_offload_irq_finish(&dev->offload); + resubmit_urb: usb_fill_bulk_urb(urb, parent->udev, usb_rcvbulkpipe(parent->udev, GS_USB_ENDPOINT_IN), @@ -857,6 +895,8 @@ static int gs_can_open(struct net_device *netdev) dev->hf_size_tx = struct_size(hf, classic_can, 1); } + can_rx_offload_enable(&dev->offload); + if (!parent->active_channels) { if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) gs_usb_timestamp_init(parent); @@ -965,6 +1005,7 @@ out_usb_kill_anchored_urbs: gs_usb_timestamp_stop(parent); } + can_rx_offload_disable(&dev->offload); close_candev(netdev); return rc; @@ -1037,6 +1078,8 @@ static int gs_can_close(struct net_device *netdev) dev->tx_context[rc].echo_id = GS_MAX_TX_URBS; } + can_rx_offload_disable(&dev->offload); + /* close the netdev */ close_candev(netdev); @@ -1336,6 +1379,7 @@ static struct gs_can *gs_make_candev(unsigned int channel, dev->can.data_bittiming_const = &dev->data_bt_const; } + can_rx_offload_add_manual(netdev, &dev->offload, GS_NAPI_WEIGHT); SET_NETDEV_DEV(netdev, &intf->dev); rc = register_candev(dev->netdev); @@ -1343,11 +1387,13 @@ static struct gs_can *gs_make_candev(unsigned int channel, dev_err(&intf->dev, "Couldn't register candev for channel %d (%pe)\n", channel, ERR_PTR(rc)); - goto out_free_candev; + goto out_can_rx_offload_del; } return dev; +out_can_rx_offload_del: + can_rx_offload_del(&dev->offload); out_free_candev: free_candev(dev->netdev); return ERR_PTR(rc); @@ -1356,6 +1402,7 @@ out_free_candev: static void gs_destroy_candev(struct gs_can *dev) { unregister_candev(dev->netdev); + can_rx_offload_del(&dev->offload); free_candev(dev->netdev); }